diff options
author | Andrew Ferguson | 2007-04-20 11:29:57 +0000 |
---|---|---|
committer | Andrew Ferguson | 2007-04-20 11:29:57 +0000 |
commit | c7553e11bfc06a644bd4a4f8c1e1a4707a2827ee (patch) | |
tree | 7bf75902058d560aa24fbf461449f6584a84f195 | |
parent | 72a57a2bbb8f8b02944123b9aced40dcd4d94bb3 (diff) | |
download | org.eclipse.cdt-c7553e11bfc06a644bd4a4f8c1e1a4707a2827ee.tar.gz org.eclipse.cdt-c7553e11bfc06a644bd4a4f8c1e1a4707a2827ee.tar.xz org.eclipse.cdt-c7553e11bfc06a644bd4a4f8c1e1a4707a2827ee.zip |
183160 - fix for class implicits
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 |