Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Ferguson2007-04-20 11:29:57 +0000
committerAndrew Ferguson2007-04-20 11:29:57 +0000
commitc7553e11bfc06a644bd4a4f8c1e1a4707a2827ee (patch)
tree7bf75902058d560aa24fbf461449f6584a84f195
parent72a57a2bbb8f8b02944123b9aced40dcd4d94bb3 (diff)
downloadorg.eclipse.cdt-c7553e11bfc06a644bd4a4f8c1e1a4707a2827ee.tar.gz
org.eclipse.cdt-c7553e11bfc06a644bd4a4f8c1e1a4707a2827ee.tar.xz
org.eclipse.cdt-c7553e11bfc06a644bd4a4f8c1e1a4707a2827ee.zip
183160 - fix for class implicits
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java232
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java48
-rw-r--r--core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp10
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java255
4 files changed, 461 insertions, 84 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
index a12a7f93b0f..ff9cf738bd4 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
@@ -9,12 +9,16 @@
* IBM Corporation - initial API and implementation
* Ed Swartz (Nokia)
* Markus Schorn (Wind River Systems)
+ * Andrew Ferguson (Symbian)
*******************************************************************************/
/*
* Created on Nov 29, 2004
*/
package org.eclipse.cdt.core.parser.tests.ast2;
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
@@ -1250,7 +1254,7 @@ public class AST2CPPTests extends AST2BaseTest {
public void testConstructors() throws Exception {
StringBuffer buffer = new StringBuffer();
- buffer.append("class A { A(); A( const A & ); }; "); //$NON-NLS-1$
+ buffer.append("class A { A(void); A( const A & ); }; "); //$NON-NLS-1$
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
@@ -1274,7 +1278,223 @@ public class AST2CPPTests extends AST2BaseTest {
assertTrue(qt.isConst());
assertSame(qt.getType(), A);
}
-
+
+ // class A {~A(); };
+ // class B {~B(void); };
+ public void testExplicitDestructor_183160() throws Exception {
+ // class F {(~)F(); };
+ // class G {(~)G(void); };
+
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+
+ ICPPMethod[] methods = ((ICPPClassScope)A.getCompositeScope()).getImplicitMethods();
+ assertNotNull(methods);
+ int count=0;
+ for(int i=0; i<methods.length; i++)
+ count+= methods[i].getName().startsWith("~") ? 1 : 0;
+ assertEquals(line, 0, count);
+
+ methods = A.getDeclaredMethods();
+ assertNotNull(methods);
+ count=0;
+ for(int i=0; i<methods.length; i++)
+ count+= methods[i].getName().startsWith("~") ? 1 : 0;
+ assertEquals(line, 1, count);
+ }
+ }
+
+ // class C {};
+ // class D {D();};
+ // class E {E(void);};
+ public void testImplicitDestructor_183160() throws Exception {
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+
+ ICPPMethod[] methods = ((ICPPClassScope)A.getCompositeScope()).getImplicitMethods();
+ assertNotNull(methods);
+ int count=0;
+ for(int i=0; i<methods.length; i++)
+ count+= methods[i].getName().startsWith("~") ? 1 : 0;
+ assertEquals(line, 1, count);
+
+ methods = A.getDeclaredMethods();
+ assertNotNull(methods);
+ count=0;
+ for(int i=0; i<methods.length; i++)
+ count+= methods[i].getName().startsWith("~") ? 1 : 0;
+ assertEquals(line, 0, count);
+ }
+ }
+
+ // class A {public: A();};
+ // class B {public: B() {}};
+ // class C {public: C() {}};
+ // class D {public: D(void) {}};
+ // class E {protected: E();};
+ // class F {protected: F() {}};
+ // class G {protected: G() {}};
+ // class H {protected: H(void) {}};
+ // class I {private: I();};
+ // class J {private: J() {}};
+ // class K {private: K() {}};
+ // class L {private: L(void) {}};
+ // class M {M();};
+ // class N {N() {}};
+ // class O {O() {}};
+ // class P {P(void) {}};
+ // class Q {public: Q(int k=5);};
+ // class R {public: R(int k=5, long k=4);};
+ // class S {public: S(int k=5, int* ip= 0);};
+ // class T {public: T(int k=5, int* ip= 0, T* t= 0);};
+ public void testExplicitDefaultConstructor_183160() throws Exception {
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+ ICPPConstructor[] ctors = A.getConstructors();
+
+ assertNotNull(ctors);
+ assertEquals(2, ctors.length); // one user-declared default constructor, one implicit copy constructor
+ }
+ }
+
+ // class Q {public: Q(int k);};
+ // class R {public: R(int k=5, long k);};
+ // class S {public: S(int k=5, int* ip);};
+ // class T {public: T(int k, int* ip= 0, T* t= 0);};
+ public void testExplicitNonDefaultConstructor_183160() throws Exception {
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+ ICPPConstructor[] ctors = A.getConstructors();
+
+ assertNotNull(ctors);
+ assertEquals(2, ctors.length); // one user-declared non-default constructor, one implicit copy constructor
+ }
+ }
+
+ // class A {public: A(A &);};
+ // class B {private: B(const B &);};
+ // class C {protected: C(volatile C &);};
+ // class D {D(const volatile D &) {}};
+ // class E {public: E(E &, int k=5);};
+ // class F {private: F(const F &, int j=2, int k=3);};
+ // class G {protected: G(volatile G &, int i=4, int l=2);};
+ // class H {H(const volatile H &, int i=1, long k=2) {}};
+ public void testExplicitCopyConstructor_183160() throws Exception {
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+ ICPPConstructor[] ctors = A.getConstructors();
+
+ assertNotNull(ctors);
+ // one copy constructor, no implicit default constructor
+ assertEquals(1, ctors.length);
+ }
+ }
+
+ // class I {public: I(I *, int k=5);}; // I * rather than I &
+ // class J {private: J(const J *, int j, int k=3);}; // J * rather than J &
+ // class K {protected: K(volatile K *, int i=4, int l=2);}; // K * rather than K &
+ // class L {L(const volatile L &, int i=1, long k=2, int* x) {}}; // param int* x has no initializer
+ public void testNotExplicitCopyConstructor_183160() throws Exception {
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+ ICPPConstructor[] ctors = A.getConstructors();
+
+ assertNotNull(ctors);
+ // one copy constructor, one user declared constructor (not a copy constructor)
+ assertEquals(2, ctors.length);
+ }
+ }
+
+ // class A {public: void operator=(int); }; // legitimate, but not a copy assignment operator
+ // class B {public: void operator=(B &, int); }; // compile error
+ // class C {public: void operator=(C &c, int k=5) {} }; // compile error
+ // class D {public: void operator=(const D &, const D &); }; // compile error
+ public void testNotExplicitCopyAssignmentOperator_183160() throws Exception {
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+ ICPPMethod[] methods = ((ICPPClassScope)A.getCompositeScope()).getImplicitMethods();
+ assertNotNull(methods);
+ int count=0;
+ for(int i=0; i<methods.length; i++) {
+ boolean eq= Arrays.equals(methods[i].getName().toCharArray(), ICPPASTOperatorName.OPERATOR_ASSIGN);
+ count+= eq ? 1 : 0;
+ }
+
+ assertEquals(1, count); // check for one implicit operator= method
+
+ methods = A.getDeclaredMethods();
+ assertNotNull(methods);
+ count=0;
+ for(int i=0; i<methods.length; i++) {
+ boolean eq= Arrays.equals(methods[i].getName().toCharArray(), ICPPASTOperatorName.OPERATOR_ASSIGN);
+ count+= eq ? 1 : 0;
+ }
+
+ assertEquals(1, count); // check for the user declared
+ }
+ }
+
+ // class A {public: void operator=(A &); };
+ // class B {protected: void operator=(const B &); };
+ // class C {private: void operator=(volatile C &) {} };
+ // class D {D& operator=(volatile const D &); };
+ public void testExplicitCopyAssignmentOperator_183160() throws Exception {
+ BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString()));
+ for(String line= br.readLine(); line!=null; line= br.readLine()) {
+ IASTTranslationUnit tu = parse(line, ParserLanguage.CPP);
+ IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
+ IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier();
+ ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding();
+ ICPPMethod[] methods = ((ICPPClassScope)A.getCompositeScope()).getImplicitMethods();
+ assertNotNull(methods);
+ int count=0;
+ for(int i=0; i<methods.length; i++) {
+ boolean eq= Arrays.equals(methods[i].getName().toCharArray(), ICPPASTOperatorName.OPERATOR_ASSIGN);
+ count+= eq ? 1 : 0;
+ }
+
+ assertEquals(0, count); // check for no implicit operator= methods
+
+ methods = A.getDeclaredMethods();
+ assertNotNull(methods);
+ count=0;
+ for(int i=0; i<methods.length; i++) {
+ boolean eq= Arrays.equals(methods[i].getName().toCharArray(), ICPPASTOperatorName.OPERATOR_ASSIGN);
+ count+= eq ? 1 : 0;
+ }
+
+ assertEquals(1, count); // only should get the user declared
+ }
+ }
+
public void testNamespaceAlias() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("namespace A { int x; } \n"); //$NON-NLS-1$
@@ -4256,8 +4476,8 @@ public class AST2CPPTests extends AST2BaseTest {
.resolveBinding();
ICPPConstructor[] ctors = A.getConstructors();
- assertEquals(ctors.length, 2);
- assertSame(ctor, ctors[0]);
+ assertEquals(2, ctors.length); // one user declared constructor, one copy constructor
+ assertSame(ctor, ctors[1]);
tu = parse("class A { A( void ); };", ParserLanguage.CPP); //$NON-NLS-1$
col = new CPPNameCollector();
@@ -4267,8 +4487,8 @@ public class AST2CPPTests extends AST2BaseTest {
ctor = (ICPPConstructor) col.getName(1).resolveBinding();
ctors = A.getConstructors();
- assertEquals(ctors.length, 2);
- assertSame(ctor, ctors[0]);
+ assertEquals(2, ctors.length); // one user declared constructor, one copy constructor
+ assertSame(ctor, ctors[1]);
}
public void testBug95461() throws Exception {
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java
index 3a37289eba8..d807ca8ef53 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassTests.java
@@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
@@ -30,7 +31,6 @@ import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
-import org.eclipse.core.runtime.NullProgressMonitor;
/**
* @author Doug Schaefer
@@ -57,7 +57,7 @@ public class ClassTests extends PDOMTestBase {
}
public void test1() throws Exception {
- IBinding[] Bs = pdom.findBindings(Pattern.compile("B"), false, new IndexFilter(), new NullProgressMonitor());
+ IBinding[] Bs = pdom.findBindings(Pattern.compile("B"), false, IndexFilter.ALL, NPM);
assertEquals(1, Bs.length);
ICPPClassType B = (ICPPClassType)Bs[0];
ICPPMethod[] Bmethods = B.getAllDeclaredMethods();
@@ -71,7 +71,7 @@ public class ClassTests extends PDOMTestBase {
}
public void testNested() throws Exception {
- IBinding[] bindings = pdom.findBindings(Pattern.compile("NestedA"), false, new IndexFilter(), new NullProgressMonitor());
+ IBinding[] bindings = pdom.findBindings(Pattern.compile("NestedA"), false, IndexFilter.ALL, NPM);
assertEquals(1, bindings.length);
ICPPClassType NestedA = (ICPPClassType)bindings[0];
ICPPClassType[] nested = NestedA.getNestedClasses();
@@ -94,7 +94,7 @@ public class ClassTests extends PDOMTestBase {
}
public void test147903() throws Exception {
- IBinding[] bindings = pdom.findBindings(Pattern.compile("pr147903"), false, new IndexFilter(), new NullProgressMonitor());
+ IBinding[] bindings = pdom.findBindings(Pattern.compile("pr147903"), false, IndexFilter.ALL, NPM);
assertEquals(1, bindings.length);
ICPPNamespaceScope ns = ((ICPPNamespace)bindings[0]).getNamespaceScope();
bindings = ns.find("testRef");
@@ -108,28 +108,28 @@ public class ClassTests extends PDOMTestBase {
/* Test friend relationships between classes */
public void _testFriend() throws Exception {
//TODO this test is failing
- IBinding[] bindings = pdom.findBindings(Pattern.compile("ClassA"), false, new IndexFilter(), new NullProgressMonitor());
+ IBinding[] bindings = pdom.findBindings(Pattern.compile("ClassA"), false, IndexFilter.ALL, NPM);
assertEquals(1, bindings.length);
ICPPClassType classA = (ICPPClassType) bindings[0];
IBinding[] friends = classA.getFriends();
assertEquals(1, friends.length);
- bindings = pdom.findBindings(Pattern.compile("ClassC"), false, new IndexFilter(), new NullProgressMonitor());
+ bindings = pdom.findBindings(Pattern.compile("ClassC"), false, IndexFilter.ALL, NPM);
assertEquals(bindings[0], friends[0]); //ClassC is a friend class of ClassA
- bindings = pdom.findBindings(Pattern.compile("ClassC"), false, new IndexFilter(), new NullProgressMonitor());
+ bindings = pdom.findBindings(Pattern.compile("ClassC"), false, IndexFilter.ALL, NPM);
assertEquals(1, bindings.length);
ICPPClassType classC = (ICPPClassType) bindings[0];
friends = classC.getFriends();
assertEquals(1, friends.length);
Pattern[] patterns = {Pattern.compile("ClassB"),Pattern.compile("functionB")};
- bindings = pdom.findBindings(patterns, false, new IndexFilter(), new NullProgressMonitor());
+ bindings = pdom.findBindings(patterns, false, IndexFilter.ALL, NPM);
assertEquals(bindings[0], friends[0]); //functionB is a friend of ClassC
}
public void _testConstructor() throws Exception {
// the source does not define Class1, so it is no surprise that the test is failing.
//TODO PDOM doesn't have information on constructor
- IBinding[] bindings = pdom.findBindings(Pattern.compile("Class1"), false, new IndexFilter(), new NullProgressMonitor());
+ IBinding[] bindings = pdom.findBindings(Pattern.compile("Class1"), false, IndexFilter.ALL, NPM);
assertEquals(2, bindings.length);
assertTrue(bindings[0] instanceof ICPPClassType);
assertTrue(bindings[1] instanceof ICPPMethod);
@@ -143,7 +143,7 @@ public class ClassTests extends PDOMTestBase {
assertEquals(offset("constructor.cpp","Class1::Class1") + 8, loc.getNodeOffset()); //character offset
/* Member initialization */
- bindings = pdom.findBindings(Pattern.compile("number"), false, new IndexFilter(), new NullProgressMonitor());
+ bindings = pdom.findBindings(Pattern.compile("number"), false, IndexFilter.ALL, NPM);
assertEquals(1, bindings.length);
IName[] refs = pdom.findNames(bindings[0], IIndex.FIND_REFERENCES);
@@ -153,4 +153,32 @@ public class ClassTests extends PDOMTestBase {
assertEquals(bindings[0], ((PDOMName)refs[0]).resolveBinding());
}
+
+ public void testAbsenceOfDefaultConstructorWhenExplicitNonDefaultPresentA() throws Exception {
+ IndexFilter JUST_CONSTRUCTORS= new IndexFilter() {
+ public boolean acceptBinding(IBinding binding) {
+ return binding instanceof ICPPConstructor;
+ }
+ public boolean acceptImplicitMethods() {
+ return true;
+ }
+ };
+ IBinding[] bindings = pdom.findBindings(Pattern.compile("C"), false, JUST_CONSTRUCTORS, NPM);
+ // expecting C(int) and C(const C &)
+ assertEquals(2, bindings.length);
+ }
+
+ public void testAbsenceOfDefaultConstructorWhenExplicitNonDefaultPresentB() throws Exception {
+ IndexFilter JUST_CONSTRUCTORS= new IndexFilter() {
+ public boolean acceptBinding(IBinding binding) {
+ return binding instanceof ICPPConstructor;
+ }
+ public boolean acceptImplicitMethods() {
+ return true;
+ }
+ };
+ IBinding[] bindings = pdom.findBindings(Pattern.compile("D"), false, JUST_CONSTRUCTORS, NPM);
+ // expecting just D(D &)
+ assertEquals(1, bindings.length);
+ }
}
diff --git a/core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp b/core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp
index 1b0968ee2d8..69b094a806d 100644
--- a/core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp
+++ b/core/org.eclipse.cdt.core.tests/resources/pdomtests/classTests/class.cpp
@@ -11,3 +11,13 @@ int main() {
B b;
b.f();
}
+
+class C {
+ public:
+ C(int a) {}
+};
+
+class D {
+ public:
+ D(D &) {}
+};
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
index a2227b0a0df..35f011b3641 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
@@ -9,15 +9,18 @@
* IBM Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
+ * Andrew Ferguson (Symbian)
*******************************************************************************/
/*
* Created on Nov 29, 2004
*/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
+import java.util.ArrayList;
+import java.util.List;
+
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.DOMException;
-import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
@@ -36,9 +39,11 @@ import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
@@ -81,7 +86,6 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
if( !(binding instanceof ICPPClassType ) )
return;
- implicits = new ICPPMethod[4];
ICPPClassType clsType = (ICPPClassType) binding;
if( clsType instanceof ICPPClassTemplate ){
try {
@@ -94,72 +98,43 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
char [] className = name.toCharArray();
IParameter [] voidPs = new IParameter [] { new CPPParameter( CPPSemantics.VOID_TYPE ) };
- if( !hasNonStandardDefaultConstructor( compTypeSpec ) ) {
- //default constructor: A(void)
- ICPPMethod m = new CPPImplicitConstructor( this, className, voidPs );
- implicits[0] = m;
- addBinding( m );
- }
-
- //copy constructor: A( const A & )
- IType pType = new CPPReferenceType( new CPPQualifierType( clsType, true, false ) );
- IParameter [] ps = new IParameter [] { new CPPParameter( pType ) };
- ICPPMethod m = new CPPImplicitConstructor( this, className, ps );
- implicits[1] = m;
- addBinding( m );
-
- //copy assignment operator: A& operator = ( const A & )
- IType refType = new CPPReferenceType( clsType );
- m = new CPPImplicitMethod( this, ICPPASTOperatorName.OPERATOR_ASSIGN, refType, ps );
- implicits[2] = m;
- addBinding( m );
-
- //destructor: ~A()
- char [] dtorName = CharArrayUtils.concat( "~".toCharArray(), className ); //$NON-NLS-1$
- m = new CPPImplicitMethod( this, dtorName, new CPPBasicType( IBasicType.t_unspecified, 0 ), voidPs );
- implicits[3] = m;
- addBinding( m );
- }
-
- private boolean hasNonStandardDefaultConstructor( ICPPASTCompositeTypeSpecifier compSpec ){
- IASTDeclaration [] members = compSpec.getMembers();
- char [] name = compSpec.getName().toCharArray();
- IASTDeclarator dtor = null;
- IASTDeclSpecifier spec = null;
- for( int i = 0; i < members.length; i++ ){
- if( members[i] instanceof IASTSimpleDeclaration ){
- IASTDeclarator [] dtors = ((IASTSimpleDeclaration)members[i]).getDeclarators();
- if( dtors.length == 0 || dtors.length > 1 )
- continue;
- dtor = dtors[0];
- spec = ((IASTSimpleDeclaration)members[i]).getDeclSpecifier();
- } else if( members[i] instanceof IASTFunctionDefinition ){
- dtor = ((IASTFunctionDefinition)members[i]).getDeclarator();
- spec = ((IASTFunctionDefinition)members[i]).getDeclSpecifier();
- }
- if( !(dtor instanceof ICPPASTFunctionDeclarator) || !(spec instanceof IASTSimpleDeclSpecifier) ||
- ((IASTSimpleDeclSpecifier)spec).getType() != IASTSimpleDeclSpecifier.t_unspecified ||
- !CharArrayUtils.equals( dtor.getName().toCharArray(), name ) )
- {
- continue;
- }
-
- IASTParameterDeclaration [] ps = ((ICPPASTFunctionDeclarator)dtor).getParameters();
- if( ps.length >= 1 ){
- IASTDeclarator d = ps[0].getDeclarator();
- IASTDeclSpecifier s = ps[0].getDeclSpecifier();
- if( s instanceof IASTSimpleDeclSpecifier &&
- ((IASTSimpleDeclSpecifier)s).getType() == IASTSimpleDeclSpecifier.t_void &&
- d.getPointerOperators().length == 0 && !(d instanceof IASTArrayDeclarator) )
- {
- continue; //A(void)
- }
-
- if( d.getInitializer() != null )
- return true;
- }
- }
- return false;
+ IType pType = new CPPReferenceType( new CPPQualifierType( clsType, true, false ) );
+ IParameter [] ps = new IParameter [] { new CPPParameter( pType ) };
+
+ int i= 0;
+ ImplicitsAnalysis ia= new ImplicitsAnalysis( compTypeSpec );
+ implicits= new ICPPMethod[ia.getImplicitsToDeclareCount()];
+
+ if( !ia.hasUserDeclaredConstructor() ) {
+ //default constructor: A(void)
+ ICPPMethod m = new CPPImplicitConstructor( this, className, voidPs );
+ implicits[i++]=m;
+ addBinding( m );
+ }
+
+ if( !ia.hasUserDeclaredCopyConstructor() ) {
+ //copy constructor: A( const A & )
+
+ ICPPMethod m = new CPPImplicitConstructor( this, className, ps );
+ implicits[i++]=m;
+ addBinding( m );
+ }
+
+ if( !ia.hasUserDeclaredCopyAssignmentOperator() ) {
+ //copy assignment operator: A& operator = ( const A & )
+ IType refType = new CPPReferenceType( clsType );
+ ICPPMethod m = new CPPImplicitMethod( this, ICPPASTOperatorName.OPERATOR_ASSIGN, refType, ps );
+ implicits[i++]=m;
+ addBinding( m );
+ }
+
+ if( !ia.hasUserDeclaredDestructor() ) {
+ //destructor: ~A()
+ char [] dtorName = CharArrayUtils.concat( "~".toCharArray(), className ); //$NON-NLS-1$
+ ICPPMethod m = new CPPImplicitMethod( this, dtorName, new CPPBasicType( IBasicType.t_unspecified, 0 ), voidPs );
+ implicits[i++]=m;
+ addBinding( m );
+ }
}
public IScope getParent() {
@@ -390,3 +365,147 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
}
}
}
+
+/**
+ * Helps analyzis of the class declaration for user declared members relevent
+ * to deciding which implicit bindings to declare.
+ */
+class ImplicitsAnalysis {
+ private boolean hasUserDeclaredConstructor;
+ private boolean hasUserDeclaredCopyConstructor;
+ private boolean hasUserDeclaredCopyAssignmentOperator;
+ private boolean hasUserDeclaredDestructor;
+
+ ImplicitsAnalysis( ICPPASTCompositeTypeSpecifier compSpec ) {
+ ICPPASTFunctionDeclarator[] ctors= getUserDeclaredCtorOrDtor(compSpec, true);
+
+ hasUserDeclaredConstructor= ctors.length> 0;
+ hasUserDeclaredCopyConstructor= false;
+ hasUserDeclaredCopyAssignmentOperator= false;
+ hasUserDeclaredDestructor= getUserDeclaredCtorOrDtor(compSpec, false).length>0;
+
+ outer: for(int i=0; i<ctors.length; i++) {
+ ICPPASTFunctionDeclarator dcltor= ctors[i];
+ IASTParameterDeclaration [] ps = ((ICPPASTFunctionDeclarator)dcltor).getParameters();
+ if( ps.length >= 1 ){
+ if(paramHasTypeReferenceToTheAssociatedClassType(ps[0])) {
+ // and all remaining arguments have initializers
+ for(int j=1; j<ps.length; j++) {
+ if( ps[j].getDeclarator().getInitializer() == null ) {
+ continue outer;
+ }
+ }
+ hasUserDeclaredCopyConstructor= true;
+ }
+ }
+ }
+
+ boolean hasUserDeclaredCAO= getUserDeclaredCopyAssignmentOperators(compSpec).length > 0;
+ hasUserDeclaredCopyAssignmentOperator= hasUserDeclaredCAO;
+ }
+
+ public int getImplicitsToDeclareCount() {
+ return (!hasUserDeclaredDestructor ? 1 : 0)
+ + (!hasUserDeclaredConstructor ? 1 : 0)
+ + (!hasUserDeclaredCopyConstructor ? 1 : 0)
+ + (!hasUserDeclaredCopyAssignmentOperator ? 1 : 0);
+ }
+
+ private static ICPPASTFunctionDeclarator[] getUserDeclaredCtorOrDtor( ICPPASTCompositeTypeSpecifier compSpec, boolean constructor ) {
+ List result= new ArrayList();
+ IASTDeclaration [] members = compSpec.getMembers();
+ char [] name = compSpec.getName().toCharArray();
+ IASTDeclarator dcltor = null;
+ IASTDeclSpecifier spec = null;
+ for( int i = 0; i < members.length; i++ ){
+ if( members[i] instanceof IASTSimpleDeclaration ){
+ IASTDeclarator [] dtors = ((IASTSimpleDeclaration)members[i]).getDeclarators();
+ if( dtors.length == 0 || dtors.length > 1 )
+ continue;
+ dcltor = dtors[0];
+ spec = ((IASTSimpleDeclaration)members[i]).getDeclSpecifier();
+ } else if( members[i] instanceof IASTFunctionDefinition ){
+ dcltor = ((IASTFunctionDefinition)members[i]).getDeclarator();
+ spec = ((IASTFunctionDefinition)members[i]).getDeclSpecifier();
+ }
+
+
+ if( !(dcltor instanceof ICPPASTFunctionDeclarator) || !(spec instanceof IASTSimpleDeclSpecifier) ||
+ ((IASTSimpleDeclSpecifier)spec).getType() != IASTSimpleDeclSpecifier.t_unspecified)
+ {
+ continue;
+ }
+
+ boolean nameEquals= false;
+ if(constructor) {
+ nameEquals= CharArrayUtils.equals( dcltor.getName().toCharArray(), name );
+ } else {
+ char[] cname= dcltor.getName().toCharArray();
+ if(cname.length>0 && cname[0]=='~') {
+ nameEquals= CharArrayUtils.equals( cname, 1, name.length, name );
+ }
+ }
+
+ if(!nameEquals)
+ continue;
+
+ result.add(dcltor);
+ }
+ return (ICPPASTFunctionDeclarator[]) result.toArray(new ICPPASTFunctionDeclarator[result.size()]);
+ }
+
+ private static ICPPASTFunctionDeclarator[] getUserDeclaredCopyAssignmentOperators( ICPPASTCompositeTypeSpecifier compSpec ) {
+ List result= new ArrayList();
+ IASTDeclaration [] members = compSpec.getMembers();
+ IASTDeclarator dcltor = null;
+ for( int i = 0; i < members.length; i++ ){
+ if( members[i] instanceof IASTSimpleDeclaration ){
+ IASTDeclarator [] dtors = ((IASTSimpleDeclaration)members[i]).getDeclarators();
+ if( dtors.length == 0 || dtors.length > 1 )
+ continue;
+ dcltor = dtors[0];
+ } else if( members[i] instanceof IASTFunctionDefinition ){
+ dcltor = ((IASTFunctionDefinition)members[i]).getDeclarator();
+ }
+ if( !(dcltor instanceof ICPPASTFunctionDeclarator) ||
+ !CharArrayUtils.equals( dcltor.getName().toCharArray(), ICPPASTOperatorName.OPERATOR_ASSIGN ) )
+ {
+ continue;
+ }
+
+ IASTParameterDeclaration [] ps = ((ICPPASTFunctionDeclarator)dcltor).getParameters();
+ if( ps.length != 1 || !paramHasTypeReferenceToTheAssociatedClassType(ps[0]) )
+ continue;
+
+ result.add(dcltor);
+ }
+ return (ICPPASTFunctionDeclarator[]) result.toArray(new ICPPASTFunctionDeclarator[result.size()]);
+ }
+
+ private static boolean paramHasTypeReferenceToTheAssociatedClassType(IASTParameterDeclaration dec) {
+ boolean result= false;
+ IASTDeclarator pdtor= dec.getDeclarator();
+ if(pdtor.getPointerOperators().length==1 && pdtor.getPointerOperators()[0] instanceof ICPPASTReferenceOperator) {
+ if(dec.getDeclSpecifier() instanceof ICPPASTNamedTypeSpecifier) {
+ result= true;
+ }
+ }
+ return result;
+ }
+
+ public boolean hasUserDeclaredConstructor() {
+ return hasUserDeclaredConstructor;
+ }
+
+ public boolean hasUserDeclaredCopyConstructor() {
+ return hasUserDeclaredCopyConstructor;
+ }
+
+ public boolean hasUserDeclaredCopyAssignmentOperator() {
+ return hasUserDeclaredCopyAssignmentOperator;
+ }
+
+ public boolean hasUserDeclaredDestructor() {
+ return hasUserDeclaredDestructor;
+ }
+} \ No newline at end of file

Back to the top