mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 10:16:03 +02:00
183160 - fix for class implicits
This commit is contained in:
parent
72a57a2bbb
commit
c7553e11bf
4 changed files with 460 additions and 83 deletions
|
@ -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);
|
||||
|
||||
|
@ -1275,6 +1279,222 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,3 +11,13 @@ int main() {
|
|||
B b;
|
||||
b.f();
|
||||
}
|
||||
|
||||
class C {
|
||||
public:
|
||||
C(int a) {}
|
||||
};
|
||||
|
||||
class D {
|
||||
public:
|
||||
D(D &) {}
|
||||
};
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
IType pType = new CPPReferenceType( new CPPQualifierType( clsType, true, false ) );
|
||||
IParameter [] ps = new IParameter [] { new CPPParameter( pType ) };
|
||||
|
||||
//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 );
|
||||
int i= 0;
|
||||
ImplicitsAnalysis ia= new ImplicitsAnalysis( compTypeSpec );
|
||||
implicits= new ICPPMethod[ia.getImplicitsToDeclareCount()];
|
||||
|
||||
//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 );
|
||||
if( !ia.hasUserDeclaredConstructor() ) {
|
||||
//default constructor: A(void)
|
||||
ICPPMethod m = new CPPImplicitConstructor( this, className, voidPs );
|
||||
implicits[i++]=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 );
|
||||
}
|
||||
if( !ia.hasUserDeclaredCopyConstructor() ) {
|
||||
//copy constructor: A( const A & )
|
||||
|
||||
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;
|
||||
}
|
||||
ICPPMethod m = new CPPImplicitConstructor( this, className, ps );
|
||||
implicits[i++]=m;
|
||||
addBinding( m );
|
||||
}
|
||||
|
||||
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( !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( d.getInitializer() != null )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue