1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 360223: Detection of user-defined copy constructor.

This commit is contained in:
Markus Schorn 2011-10-31 13:59:52 +01:00
parent 01d3c53747
commit b7224bd864
9 changed files with 271 additions and 212 deletions

View file

@ -524,7 +524,8 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// struct Base::Datum; // error: Datum undefined
// struct Base::Data* pBase; // OK: refers to nested Data
public void test3_4_4s3() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
String[] problems= {"::Glob", "Glob", "Base::Datum", "Datum"};
parse(getAboveComment(), ParserLanguage.CPP, problems);
}
// static void f();

View file

@ -9554,4 +9554,32 @@ public class AST2CPPTests extends AST2BaseTest {
public void testAmbiguityResolution_Bug359364() throws Exception {
parseAndCheckBindings();
}
// template<typename T> struct C {
// C(const C<T>& c) {}
// };
// struct D {
// typedef const D& TD;
// D(TD c) {}
// };
// struct E {
// E();
// };
// typedef E F;
// F::E(){}
public void testImplicitCtors_360223() throws Exception {
BindingAssertionHelper bh= getAssertionHelper();
ICPPClassType c= bh.assertNonProblem("C", 0);
ICPPConstructor[] ctors = c.getConstructors();
assertEquals(1, ctors.length);
assertFalse(ctors[0].isImplicit());
c= bh.assertNonProblem("D", 0);
ctors = c.getConstructors();
assertEquals(1, ctors.length);
assertFalse(ctors[0].isImplicit());
IBinding ctor= bh.assertNonProblem("E(){}", 1);
assertTrue(ctor instanceof ICPPConstructor);
}
}

View file

@ -3761,17 +3761,17 @@ public class AST2TemplateTests extends AST2BaseTest {
// ~DumbPtr<T> ();
// };
// template <class T>
// DumbPtr<T>::DumbPtr<T>/**/ (const DumbPtr<T>& aObj) {
// DumbPtr<T>::DumbPtr/**/ (const DumbPtr<T>& aObj) {
// }
// template <class T>
// DumbPtr<T>::~DumbPtr<T>/**/ () {
// DumbPtr<T>::~DumbPtr/**/ () {
// }
public void testCtorWithTemplateID_259600() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPConstructor ctor= bh.assertNonProblem("DumbPtr<T>/**/", 10);
ICPPMethod dtor= bh.assertNonProblem("~DumbPtr<T>/**/", 11);
ICPPConstructor ctor= bh.assertNonProblem("DumbPtr/**/", 7);
ICPPMethod dtor= bh.assertNonProblem("~DumbPtr/**/", 8);
}
// template <class T> class XT {
@ -5562,4 +5562,16 @@ public class AST2TemplateTests extends AST2BaseTest {
final String code= getAboveComment();
parseAndCheckBindings(code);
}
// template<typename T> struct B {
// void m();
// };
// template<typename T> struct C : B<T> {
// using B<T*>::m;
// void m();
// };
// template<typename T> void C<T>::m() {}
public void testDependentUsingDeclaration() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -655,7 +655,7 @@ public class CompleteParser2Tests extends BaseTestCase {
public void testNestedClassname() throws Exception
{
IASTTranslationUnit tu = parse( "namespace A { } \n class A::B { };"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( "namespace A { \n class A::B { };}"); //$NON-NLS-1$
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );

View file

@ -35,6 +35,7 @@ import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
@ -458,9 +459,10 @@ class ProjectBuilder {
CProjectHelper.createCCProject(name, "bin", IPDOMManager.ID_NO_INDEXER) :
CProjectHelper.createCCProject(name, "bin", IPDOMManager.ID_NO_INDEXER);
IFile lastFile= null;
for (Iterator i = path2content.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
TestSourceReader.createFile(result.getProject(), new Path((String)entry.getKey()), (String) entry.getValue());
lastFile= TestSourceReader.createFile(result.getProject(), new Path((String)entry.getKey()), (String) entry.getValue());
}
IProjectDescription desc = result.getProject().getDescription();
@ -468,6 +470,10 @@ class ProjectBuilder {
result.getProject().setDescription(desc, new NullProgressMonitor());
CCorePlugin.getIndexManager().setIndexerId(result, IPDOMManager.ID_FAST_INDEXER);
if (lastFile != null) {
IIndex index= CCorePlugin.getIndexManager().getIndex(result);
TestSourceReader.waitUntilFileIsIndexed(index, lastFile, 2000);
}
BaseTestCase.waitForIndexer(result);
return result;
}

View file

@ -15,6 +15,10 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import java.util.ArrayList;
import java.util.List;
@ -39,10 +43,9 @@ import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
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.ICPPASTParameterDeclaration;
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;
@ -51,6 +54,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
@ -106,7 +110,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
ICPPParameter[] ps = new ICPPParameter[] { new CPPParameter(pType, 0) };
int i= 0;
ImplicitsAnalysis ia= new ImplicitsAnalysis(compTypeSpec);
ImplicitsAnalysis ia= new ImplicitsAnalysis(compTypeSpec, clsType);
implicits= new ICPPMethod[ia.getImplicitsToDeclareCount()];
if (!ia.hasUserDeclaredConstructor()) {
@ -405,10 +409,12 @@ class ImplicitsAnalysis {
private boolean hasUserDeclaredCopyConstructor;
private boolean hasUserDeclaredCopyAssignmentOperator;
private boolean hasUserDeclaredDestructor;
private ICPPClassType classType;
ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compSpec) {
ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compSpec, ICPPClassType clsType) {
classType= clsType;
ICPPASTFunctionDeclarator[] ctors= getUserDeclaredCtorOrDtor(compSpec, true);
hasUserDeclaredConstructor= ctors.length> 0;
hasUserDeclaredCopyConstructor= false;
hasUserDeclaredCopyAssignmentOperator= false;
@ -418,7 +424,7 @@ class ImplicitsAnalysis {
ICPPASTFunctionDeclarator dcltor= ctors[i];
IASTParameterDeclaration[] ps = dcltor.getParameters();
if (ps.length >= 1) {
if (paramHasTypeReferenceToTheAssociatedClassType(ps[0], compSpec.getName().getRawSignature())) {
if (hasTypeReferenceToClassType(ps[0])) {
// and all remaining arguments have initializers
for (int j = 1; j < ps.length; j++) {
if (ps[j].getDeclarator().getInitializer() == null) {
@ -441,7 +447,7 @@ class ImplicitsAnalysis {
+ (!hasUserDeclaredCopyAssignmentOperator ? 1 : 0);
}
private static ICPPASTFunctionDeclarator[] getUserDeclaredCtorOrDtor(ICPPASTCompositeTypeSpecifier compSpec, boolean constructor) {
private ICPPASTFunctionDeclarator[] getUserDeclaredCtorOrDtor(ICPPASTCompositeTypeSpecifier compSpec, boolean constructor) {
List<ICPPASTFunctionDeclarator> result= new ArrayList<ICPPASTFunctionDeclarator>();
IASTDeclaration[] members = compSpec.getMembers();
char[] name = compSpec.getName().getLookupKey();
@ -483,7 +489,7 @@ class ImplicitsAnalysis {
return result.toArray(new ICPPASTFunctionDeclarator[result.size()]);
}
private static ICPPASTFunctionDeclarator[] getUserDeclaredCopyAssignmentOperators(ICPPASTCompositeTypeSpecifier compSpec) {
private ICPPASTFunctionDeclarator[] getUserDeclaredCopyAssignmentOperators(ICPPASTCompositeTypeSpecifier compSpec) {
List<ICPPASTFunctionDeclarator> result= new ArrayList<ICPPASTFunctionDeclarator>();
IASTDeclaration[] members = compSpec.getMembers();
IASTDeclarator dcltor = null;
@ -504,7 +510,7 @@ class ImplicitsAnalysis {
continue;
IASTParameterDeclaration[] ps = ((ICPPASTFunctionDeclarator)dcltor).getParameters();
if (ps.length != 1 || !paramHasTypeReferenceToTheAssociatedClassType(ps[0], null))
if (ps.length != 1 || !hasTypeReferenceToClassType(ps[0]))
continue;
result.add((ICPPASTFunctionDeclarator)dcltor);
@ -512,25 +518,20 @@ class ImplicitsAnalysis {
return result.toArray(new ICPPASTFunctionDeclarator[result.size()]);
}
/**
* @param compSpec the name the parameter must have in order to match, or null for any name
* @param dec
* @return whether the specified parameter is a reference to the associated class type, and
* (optionally) if it has the specified name
*/
private static boolean paramHasTypeReferenceToTheAssociatedClassType(IASTParameterDeclaration dec, String name) {
boolean result= false;
IASTDeclarator pdtor= ASTQueries.findTypeRelevantDeclarator(dec.getDeclarator());
if (pdtor != null && pdtor.getPointerOperators().length == 1 &&
pdtor.getPointerOperators()[0] instanceof ICPPASTReferenceOperator &&
pdtor.getParent() == dec &&
dec.getDeclSpecifier() instanceof ICPPASTNamedTypeSpecifier) {
ICPPASTNamedTypeSpecifier nts= (ICPPASTNamedTypeSpecifier) dec.getDeclSpecifier();
if (name == null || name.equals(nts.getName().getRawSignature())) {
result= true;
private boolean hasTypeReferenceToClassType(IASTParameterDeclaration dec) {
if (dec instanceof ICPPASTParameterDeclaration) {
IType t= CPPVisitor.createType((ICPPASTParameterDeclaration) dec, false);
if (t != null) {
t= SemanticUtil.getNestedType(t, TDEF);
if (t instanceof ICPPReferenceType) {
if (!((ICPPReferenceType) t).isRValueReference()) {
t= SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE);
return classType.isSameType(t);
}
}
}
}
return result;
return false;
}
public boolean hasUserDeclaredConstructor() {

View file

@ -1222,10 +1222,10 @@ public class CPPSemantics {
// For index scopes the point of declaration is ignored.
bindings= scope.getBindings(data.astName, true, data.prefixLookup, fileSet);
}
return expandUsingDeclarationsAndRemoveObjects(bindings, data.typesOnly);
return expandUsingDeclarationsAndRemoveObjects(bindings, data);
}
private static IBinding[] expandUsingDeclarationsAndRemoveObjects(final IBinding[] bindings, boolean removeObjects) {
private static IBinding[] expandUsingDeclarationsAndRemoveObjects(final IBinding[] bindings, LookupData data) {
if (bindings == null || bindings.length == 0)
return IBinding.EMPTY_BINDING_ARRAY;
@ -1233,9 +1233,9 @@ public class CPPSemantics {
if (b == null)
break;
if (b instanceof ICPPUsingDeclaration || (removeObjects && isObject(b))) {
if (b instanceof ICPPUsingDeclaration || (data.typesOnly && isObject(b))) {
List<IBinding> result= new ArrayList<IBinding>(bindings.length);
expandUsingDeclarations(bindings, removeObjects, result);
expandUsingDeclarations(bindings, data, result);
return result.toArray(new IBinding[result.size()]);
}
}
@ -1246,18 +1246,21 @@ public class CPPSemantics {
return !(b instanceof IType || b instanceof ICPPNamespace);
}
private static void expandUsingDeclarations(IBinding[] bindings, boolean removeObjects, List<IBinding> result) {
private static void expandUsingDeclarations(IBinding[] bindings, LookupData data, List<IBinding> result) {
if (bindings != null) {
for (IBinding b : bindings) {
if (b == null)
return;
// Lookup for a declaration shall ignore the using declarations.
if (b instanceof ICPPUsingDeclaration) {
for (IBinding d : ((ICPPUsingDeclaration) b).getDelegates()) {
if (d != null && !(removeObjects && isObject(d))) {
result.add(d);
if (data.forDeclaration() == null) {
for (IBinding d : ((ICPPUsingDeclaration) b).getDelegates()) {
if (d != null && !(data.typesOnly && isObject(d))) {
result.add(d);
}
}
}
} else if (!(removeObjects && isObject(b))) {
} else if (!(data.typesOnly && isObject(b))) {
result.add(b);
}
}

View file

@ -14,6 +14,7 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import java.util.ArrayList;
import java.util.Collections;
@ -54,7 +55,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBas
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
@ -91,7 +91,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArraySet;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
@ -254,16 +253,18 @@ public class CPPTemplates {
static IBinding isUsedInClassTemplateScope(ICPPClassTemplate ct, IASTName name) {
try {
IScope scope;
ICPPASTFunctionDefinition func= CPPVisitor.findEnclosingFunctionDefinition(name);
if (func != null) {
name= ASTQueries.findInnermostDeclarator(func.getDeclarator()).getName().getLastName();
scope= CPPVisitor.getContainingScope(name);
} else {
scope= CPPVisitor.getContainingScope(name);
if (!(scope instanceof IASTInternalScope))
return null;
IASTNode node= name;
while (node != null) {
if (node.getPropertyInParent() == IASTFunctionDefinition.DECLARATOR)
break;
if (node instanceof IASTFunctionDefinition) {
name= ASTQueries.findInnermostDeclarator(((IASTFunctionDefinition) node).getDeclarator()).getName().getLastName();
break;
}
node= node.getParent();
}
scope= CPPVisitor.getContainingScope(name);
while (scope != null) {
if (scope instanceof ISemanticProblem)
return null;
@ -1231,12 +1232,12 @@ public class CPPTemplates {
tdecl= getDirectlyEnclosingTemplateDeclaration(tdecl);
}
}
// not enough template declartaions
// not enough template declarations
return null;
}
public static void associateTemplateDeclarations(ICPPASTInternalTemplateDeclaration tdecl) {
// find innermost template declaration
// Find innermost template declaration
IASTDeclaration decl= tdecl.getDeclaration();
while (decl instanceof ICPPASTInternalTemplateDeclaration) {
tdecl= (ICPPASTInternalTemplateDeclaration) decl;
@ -1244,111 +1245,119 @@ public class CPPTemplates {
}
final ICPPASTInternalTemplateDeclaration innerMostTDecl= tdecl;
// find name declared within the template declaration
IASTName name= getNameForDeclarationInTemplateDeclaration(decl);
// Find name declared within the template declaration
final IASTName declName= getNameForDeclarationInTemplateDeclaration(decl);
// count template declarations
int tdeclcount= 1;
IASTNode node= tdecl.getParent();
// Count non-empty template declarations
int instDeclCount= 0;
int tdeclCount= 0;
IASTNode node= tdecl;
while (node instanceof ICPPASTInternalTemplateDeclaration) {
tdeclcount++;
tdecl = (ICPPASTInternalTemplateDeclaration) node;
node= node.getParent();
if (tdecl.getTemplateParameters().length == 0) {
instDeclCount++;
} else {
instDeclCount= 0;
}
tdeclCount++;
}
final ICPPASTInternalTemplateDeclaration outerMostTDecl= tdecl;
final int paramTDeclCount = tdeclCount-instDeclCount;
// determine association of names with template declarations
// Determine association of names with template declarations
boolean lastIsTemplate= true;
int missingTemplateDecls= 0;
if (name instanceof ICPPASTQualifiedName) {
ICPPASTQualifiedName qname= (ICPPASTQualifiedName) name;
final IASTName lastName = qname.getLastName();
final boolean lastIsID = lastName instanceof ICPPASTTemplateId;
int nestingLevel;
if (declName instanceof ICPPASTQualifiedName) {
ICPPASTQualifiedName qname= (ICPPASTQualifiedName) declName;
// count template-ids
int idcount= 0;
// Count dependent-ids
CharArraySet tparnames= collectTemplateParameterNames(outerMostTDecl);
int depIDCount= 0;
IASTName owner= null;
final IASTName[] ns= qname.getNames();
for (final IASTName n : ns) {
for (int i = 0; i < ns.length-1; i++) {
IASTName n= ns[i];
if (n instanceof ICPPASTTemplateId) {
idcount++;
}
}
boolean isCtorWithTemplateID= false;
if (lastIsID && ns.length > 1) {
IASTName secondLastName= ns[ns.length-2];
if (secondLastName instanceof ICPPASTTemplateId) {
final char[] lastNamesLookupKey = lastName.getLookupKey();
if (CharArrayUtils.equals(lastNamesLookupKey, ((ICPPASTTemplateId) secondLastName).getLookupKey()) ||
(lastNamesLookupKey.length > 0 && lastNamesLookupKey[0] == '~')) {
isCtorWithTemplateID= true;
idcount--;
if (depIDCount > 0 || usesTemplateParameter((ICPPASTTemplateId) n, tparnames)) {
depIDCount++;
}
}
if (depIDCount == 0) {
owner= n;
}
}
if (lastIsID && !isCtorWithTemplateID) {
missingTemplateDecls= idcount-tdeclcount;
if (qname.getLastName() instanceof ICPPASTTemplateId
|| paramTDeclCount > depIDCount // not enough template ids
|| ns.length < 2 // ::name
) {
lastIsTemplate= true;
depIDCount++;
} else {
missingTemplateDecls= idcount+1-tdeclcount;
if (missingTemplateDecls > 0) {
// last name is probably not a template
missingTemplateDecls--;
lastIsTemplate= false;
CharArraySet tparnames= collectTemplateParameterNames(outerMostTDecl);
int j= 0;
for (IASTName n : ns) {
if (n instanceof ICPPASTTemplateId) {
// if we find a dependent id, there can be no explicit specialization.
ICPPASTTemplateId id= (ICPPASTTemplateId) n;
if (usesTemplateParameter(id, tparnames))
break;
if (j++ == missingTemplateDecls) {
IBinding b= n.resolveBinding();
if (b instanceof ICPPTemplateInstance && b instanceof ICPPClassType) {
if (((ICPPTemplateInstance) b).isExplicitSpecialization()) {
// For a template-id of an explicit specialization.
// we don't have a template declaration. (see 14.7.3.5)
missingTemplateDecls++;
lastIsTemplate= true;
}
}
break;
}
}
lastIsTemplate= false;
}
nestingLevel= 0;
if (owner != null) {
int consumesTDecl= 0;
IBinding b= owner.resolveBinding();
if (b instanceof IType) {
IType t= SemanticUtil.getNestedType((IType) b, TDEF);
if (t instanceof IBinding)
b= (IBinding) t;
}
while (b != null) {
if (b instanceof ICPPTemplateInstance) {
nestingLevel++;
if (!((ICPPTemplateInstance) b).isExplicitSpecialization())
consumesTDecl++;
} else if (b instanceof ICPPClassTemplate || b instanceof ICPPClassTemplatePartialSpecialization) {
nestingLevel++;
consumesTDecl++;
}
b= b.getOwner();
}
}
}
if (missingTemplateDecls < 0) {
missingTemplateDecls= 0; // too many template declarations
}
// determine nesting level of parent
int level= missingTemplateDecls;
if (!isFriendFunctionDeclaration(innerMostTDecl.getDeclaration())) {
node= outerMostTDecl.getParent();
while (node != null) {
if (node instanceof ICPPASTInternalTemplateDeclaration) {
level+= ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel() + 1;
break;
if (depIDCount > 0) {
nestingLevel+= depIDCount;
} else if (consumesTDecl < tdeclCount && !lastIsTemplate) {
nestingLevel++;
lastIsTemplate= true;
}
node= node.getParent();
}
}
tdecl= outerMostTDecl;
while(true) {
tdecl.setNestingLevel((short) level++);
tdecl.setAssociatedWithLastName(false);
node= tdecl.getDeclaration();
if (node instanceof ICPPASTInternalTemplateDeclaration) {
tdecl= (ICPPASTInternalTemplateDeclaration) node;
} else {
break;
nestingLevel+= depIDCount;
node= outerMostTDecl.getParent();
while (node != null) {
if (node instanceof ICPPASTInternalTemplateDeclaration) {
nestingLevel+= ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel() + 1;
break;
}
node= node.getParent();
}
}
} else {
nestingLevel= 1;
lastIsTemplate= true;
if (!isFriendFunctionDeclaration(innerMostTDecl.getDeclaration())) {
node= outerMostTDecl.getParent();
while (node != null) {
if (node instanceof ICPPASTInternalTemplateDeclaration) {
nestingLevel+= ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel() + 1;
break;
}
node= node.getParent();
}
}
}
node= innerMostTDecl;
while(node instanceof ICPPASTInternalTemplateDeclaration) {
if (--nestingLevel < 0)
nestingLevel= 0;
tdecl= (ICPPASTInternalTemplateDeclaration) node;
tdecl.setNestingLevel((short) nestingLevel);
tdecl.setAssociatedWithLastName(false);
node= tdecl.getParent();
}
innerMostTDecl.setAssociatedWithLastName(lastIsTemplate);
}

View file

@ -241,35 +241,8 @@ public class CPPVisitor extends ASTQueries {
return CPPSemantics.resolveBinding(name);
parent = parent.getParent();
binding = CPPSemantics.resolveBinding(name);
if (binding instanceof IProblemBinding && !(parent instanceof ICPPASTNamespaceAlias)) {
final IASTName[] ns = qname.getNames();
if (ns.length > 1 && ns[ns.length - 2].getBinding() instanceof IProblemBinding)
return binding;
if (((IProblemBinding) binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND) {
IASTNode node = getContainingBlockItem(name.getParent());
ASTNodeProperty prop= node.getPropertyInParent();
while (prop == ICPPASTTemplateDeclaration.OWNED_DECLARATION) {
node= node.getParent();
prop= node.getPropertyInParent();
}
if (prop != IASTCompositeTypeSpecifier.MEMBER_DECLARATION &&
prop != ICPPASTNamespaceDefinition.OWNED_DECLARATION) {
return binding;
}
IScope scope= getContainingScope(qname);
while (scope instanceof ICPPTemplateScope) {
try {
scope= scope.getParent();
} catch (DOMException e) {
return binding;
}
}
if (scope != getContainingScope(name))
return binding;
}
} else {
if (!declaresMemberInClassOrNamespace(qname)) {
binding = CPPSemantics.resolveBinding(name);
if (parent instanceof IASTCompositeTypeSpecifier) {
if (binding instanceof IIndexBinding) {
// Need to create an AST binding
@ -319,6 +292,52 @@ public class CPPVisitor extends ASTQueries {
return null;
}
private static boolean declaresMemberInClassOrNamespace(ICPPASTQualifiedName qname) {
IASTName[] names= qname.getNames();
if (names.length < 2)
return false;
IBinding pb= names[names.length-2].resolvePreBinding();
if (pb instanceof IProblemBinding)
return false;
IScope scope= null;
if (pb instanceof IType) {
IType t= SemanticUtil.getNestedType((IType) pb, TDEF);
if (t instanceof ICPPClassType) {
scope= ((ICPPClassType) t).getCompositeScope();
}
} else if (pb instanceof ICPPNamespace) {
scope= ((ICPPNamespace)pb).getNamespaceScope();
}
if (scope == null)
return false;
IASTNode parent= qname.getParent();
IASTNode decl= null;
if (parent instanceof IASTCompositeTypeSpecifier) {
decl= parent.getParent();
} else if (parent instanceof IASTDeclarator) {
decl= ASTQueries.findOutermostDeclarator((IASTDeclarator) parent).getParent();
}
while (decl != null) {
ASTNodeProperty prop = decl.getPropertyInParent();
if (prop == IASTCompositeTypeSpecifier.MEMBER_DECLARATION) {
return scope == ((ICPPASTCompositeTypeSpecifier) decl.getParent()).getScope();
}
if (prop == ICPPASTNamespaceDefinition.OWNED_DECLARATION) {
return scope == ((ICPPASTNamespaceDefinition) decl.getParent()).getScope();
}
if (prop == ICPPASTTemplateDeclaration.OWNED_DECLARATION) {
decl= decl.getParent();
} else {
return false;
}
}
return false;
}
private static IBinding createBinding(IASTGotoStatement gotoStatement) {
ICPPFunctionScope functionScope = (ICPPFunctionScope) getContainingScope(gotoStatement.getName());
IASTName name = gotoStatement.getName();
@ -801,21 +820,12 @@ public class CPPVisitor extends ASTQueries {
}
public static boolean isConstructor(IScope containingScope, IASTDeclarator declarator) {
if (containingScope == null || !(containingScope instanceof ICPPClassScope))
return false;
IASTNode node = ASTInternal.getPhysicalNodeOfScope(containingScope);
if (!(node instanceof ICPPASTCompositeTypeSpecifier)) {
return false;
if (containingScope instanceof ICPPClassScope && isConstructorDtor(declarator)) {
ICPPClassType classType= ((ICPPClassScope) containingScope).getClassType();
final char[] dtorName = findInnermostDeclarator(declarator).getName().getLookupKey();
return CharArrayUtils.equals(dtorName, classType.getNameCharArray());
}
ICPPASTCompositeTypeSpecifier clsTypeSpec = (ICPPASTCompositeTypeSpecifier) node;
IASTName clsName = clsTypeSpec.getName();
if (clsName instanceof ICPPASTQualifiedName) {
IASTName[] names = ((ICPPASTQualifiedName) clsName).getNames();
clsName = names[names.length - 1];
}
return isConstructor(clsName, declarator);
return false;
}
public static boolean isConstructorDeclaration(IASTName name) {
@ -836,35 +846,39 @@ public class CPPVisitor extends ASTQueries {
parent= name.getParent();
}
if (parent instanceof IASTDeclarator) {
IASTDeclarator dtor= findTypeRelevantDeclarator((IASTDeclarator) parent);
if (dtor instanceof ICPPASTFunctionDeclarator) {
if (isConstructorDtor((IASTDeclarator) parent)) {
if (name instanceof ICPPASTQualifiedName) {
IASTName[] names = ((ICPPASTQualifiedName) name).getNames();
if (names.length >= 2) {
return CPPVisitor.isConstructor(names[names.length - 2], dtor);
}
} else {
while (parent != null && !(parent instanceof ICPPASTCompositeTypeSpecifier)) {
parent= parent.getParent();
IBinding b= names[names.length-2].resolvePreBinding();
if (b instanceof IType) {
IType classType= getNestedType((IType) b, TDEF);
if (classType instanceof ICPPClassType) {
final char[] dtorName = names[names.length-1].getLookupKey();
final char[] className = ((ICPPClassType) classType).getNameCharArray();
return CharArrayUtils.equals(dtorName, className);
}
}
}
return false;
}
while (parent != null) {
if (parent instanceof ICPPASTCompositeTypeSpecifier) {
IASTName compName= ((ICPPASTCompositeTypeSpecifier) parent).getName().getLastName();
return CPPVisitor.isConstructor(compName, dtor);
final char[] className= ((ICPPASTCompositeTypeSpecifier) parent).getName().getLastName().getLookupKey();
final char[] dtorName = name.getLookupKey();
return CharArrayUtils.equals(dtorName, className);
}
parent= parent.getParent();
}
}
}
return false;
}
public static boolean isConstructor(IASTName parentName, IASTDeclarator declarator) {
private static boolean isConstructorDtor(IASTDeclarator declarator) {
if (declarator == null || !(declarator instanceof IASTFunctionDeclarator))
return false;
IASTName name = findInnermostDeclarator(declarator).getName();
if (!CharArrayUtils.equals(name.getLookupKey(), parentName.getLookupKey()))
return false;
IASTDeclSpecifier declSpec = null;
IASTNode parent = findOutermostDeclarator(declarator).getParent();
if (parent instanceof IASTSimpleDeclaration) {
@ -877,7 +891,6 @@ public class CPPVisitor extends ASTQueries {
}
return false;
}
public static IScope getContainingNonTemplateScope(final IASTNode inputNode) {
@ -1072,21 +1085,7 @@ public class CPPVisitor extends ASTQueries {
}
return null;
}
/**
* Returns enclosing function definition, or <code>null</code> if the given node
* is not part of a function definition.
*/
public static ICPPASTFunctionDefinition findEnclosingFunctionDefinition(IASTNode node) {
while (node != null) {
if (node instanceof ICPPASTFunctionDefinition) {
return (ICPPASTFunctionDefinition) node;
}
node= node.getParent();
}
return null;
}
public static IScope getContainingScope(IASTName name) {
return getContainingScope(name, null);
}