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:
parent
01d3c53747
commit
b7224bd864
9 changed files with 271 additions and 212 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, ICPPClassType clsType) {
|
||||
classType= clsType;
|
||||
|
||||
ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compSpec) {
|
||||
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() {
|
||||
|
|
|
@ -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) {
|
||||
if (data.forDeclaration() == null) {
|
||||
for (IBinding d : ((ICPPUsingDeclaration) b).getDelegates()) {
|
||||
if (d != null && !(removeObjects && isObject(d))) {
|
||||
if (d != null && !(data.typesOnly && isObject(d))) {
|
||||
result.add(d);
|
||||
}
|
||||
}
|
||||
} else if (!(removeObjects && isObject(b))) {
|
||||
}
|
||||
} else if (!(data.typesOnly && isObject(b))) {
|
||||
result.add(b);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
final IASTName[] ns= qname.getNames();
|
||||
for (final IASTName n : ns) {
|
||||
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 (lastIsID && !isCtorWithTemplateID) {
|
||||
missingTemplateDecls= idcount-tdeclcount;
|
||||
} else {
|
||||
missingTemplateDecls= idcount+1-tdeclcount;
|
||||
if (missingTemplateDecls > 0) {
|
||||
// last name is probably not a template
|
||||
missingTemplateDecls--;
|
||||
lastIsTemplate= false;
|
||||
// Count dependent-ids
|
||||
CharArraySet tparnames= collectTemplateParameterNames(outerMostTDecl);
|
||||
int j= 0;
|
||||
for (IASTName n : ns) {
|
||||
int depIDCount= 0;
|
||||
IASTName owner= null;
|
||||
final IASTName[] ns= qname.getNames();
|
||||
for (int i = 0; i < ns.length-1; i++) {
|
||||
IASTName n= ns[i];
|
||||
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 (depIDCount > 0 || usesTemplateParameter((ICPPASTTemplateId) n, tparnames)) {
|
||||
depIDCount++;
|
||||
}
|
||||
}
|
||||
if (depIDCount == 0) {
|
||||
owner= n;
|
||||
}
|
||||
}
|
||||
|
||||
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++;
|
||||
if (qname.getLastName() instanceof ICPPASTTemplateId
|
||||
|| paramTDeclCount > depIDCount // not enough template ids
|
||||
|| ns.length < 2 // ::name
|
||||
) {
|
||||
lastIsTemplate= true;
|
||||
depIDCount++;
|
||||
} else {
|
||||
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 (depIDCount > 0) {
|
||||
nestingLevel+= depIDCount;
|
||||
} else if (consumesTDecl < tdeclCount && !lastIsTemplate) {
|
||||
nestingLevel++;
|
||||
lastIsTemplate= true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nestingLevel+= depIDCount;
|
||||
node= outerMostTDecl.getParent();
|
||||
while (node != null) {
|
||||
if (node instanceof ICPPASTInternalTemplateDeclaration) {
|
||||
nestingLevel+= ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel() + 1;
|
||||
break;
|
||||
}
|
||||
node= node.getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (missingTemplateDecls < 0) {
|
||||
missingTemplateDecls= 0; // too many template declarations
|
||||
}
|
||||
|
||||
// determine nesting level of parent
|
||||
int level= missingTemplateDecls;
|
||||
} else {
|
||||
nestingLevel= 1;
|
||||
lastIsTemplate= true;
|
||||
if (!isFriendFunctionDeclaration(innerMostTDecl.getDeclaration())) {
|
||||
node= outerMostTDecl.getParent();
|
||||
while (node != null) {
|
||||
if (node instanceof ICPPASTInternalTemplateDeclaration) {
|
||||
level+= ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel() + 1;
|
||||
nestingLevel+= ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel() + 1;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -241,35 +241,8 @@ public class CPPVisitor extends ASTQueries {
|
|||
return CPPSemantics.resolveBinding(name);
|
||||
|
||||
parent = parent.getParent();
|
||||
if (!declaresMemberInClassOrNamespace(qname)) {
|
||||
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 (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);
|
||||
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) {
|
||||
final char[] className= ((ICPPASTCompositeTypeSpecifier) parent).getName().getLastName().getLookupKey();
|
||||
final char[] dtorName = name.getLookupKey();
|
||||
return CharArrayUtils.equals(dtorName, className);
|
||||
}
|
||||
} else {
|
||||
while (parent != null && !(parent instanceof ICPPASTCompositeTypeSpecifier)) {
|
||||
parent= parent.getParent();
|
||||
}
|
||||
if (parent instanceof ICPPASTCompositeTypeSpecifier) {
|
||||
IASTName compName= ((ICPPASTCompositeTypeSpecifier) parent).getName().getLastName();
|
||||
return CPPVisitor.isConstructor(compName, dtor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
@ -1073,20 +1086,6 @@ 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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue