From 9adfab7918fcd9bed971e3f4ef6950516a3024a5 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 30 Sep 2011 10:00:09 +0200 Subject: [PATCH] Bug 359364: Prevent premature access to ambiguous nodes. --- .../core/parser/tests/ast2/AST2CPPTests.java | 12 ++ .../parser/cpp/CPPASTAmbiguityResolver.java | 37 +++++- .../cpp/CPPASTCompositeTypeSpecifier.java | 22 ++-- .../core/dom/parser/cpp/CPPASTTemplateId.java | 8 +- .../core/dom/parser/cpp/CPPClassScope.java | 12 +- .../parser/cpp/CPPClassSpecialization.java | 87 +------------ .../core/dom/parser/cpp/CPPClassTemplate.java | 77 +----------- .../core/dom/parser/cpp/CPPClassType.java | 118 ++++-------------- .../dom/parser/cpp/semantics/CPPVisitor.java | 101 ++++++++++----- 9 files changed, 164 insertions(+), 310 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 7ee28813f70..23d42cca070 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -9526,4 +9526,16 @@ public class AST2CPPTests extends AST2BaseTest { ICPPClassType c= bh.assertNonProblem("A", 1); assertEquals(0, ClassTypeHelper.getPureVirtualMethods(c).length); } + + // template struct CT1 {}; + // template struct CT2 {}; + // typedef char Tdef; + // template<> struct CT1< CT2 > { + // CT1 x; // Ambiguity causes lookup in CT1< CT2 > + // }; + // template<> struct CT2 { // Accessed before ambiguity is resolved + // }; + public void testAmbiguityResolution_Bug359364() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java index 4fb6e5ec736..d31041261e3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java @@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import java.util.HashSet; import java.util.LinkedList; +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -29,7 +30,10 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization; import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; @@ -101,6 +105,14 @@ final class CPPASTAmbiguityResolver extends ASTVisitor { public int leave(IASTDeclSpecifier declSpec) { if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { fDeferFunctions--; + + // Resolve class type definitions, such that the scope is available + // during ambiguity resolution. + ((ICPPASTCompositeTypeSpecifier) declSpec).getName().resolveBinding(); + + // Trigger computation of implicit members. + if (declSpec instanceof CPPASTCompositeTypeSpecifier) + ((CPPASTCompositeTypeSpecifier) declSpec).setAmbiguitiesResolved(); } return PROCESS_CONTINUE; } @@ -128,17 +140,30 @@ final class CPPASTAmbiguityResolver extends ASTVisitor { if (fRepopulate.remove(declaration)) { repopulateScope(declaration); } - // Explicit and partial class template specializations need to be resolved right away, - // otherwise we fail to correctly resolve qualified names that depend on a partial specialization. + // We need to create class bindings for all definitions and for the specializations. + // Otherwise, name resolution cannot access members or correct specialization. if (declaration instanceof IASTSimpleDeclaration) { IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) declaration; + IASTName name= null; IASTDeclSpecifier declspec = sdecl.getDeclSpecifier(); - if (declspec instanceof IASTCompositeTypeSpecifier && sdecl.getDeclarators().length == 0) { - IASTName name= ((IASTCompositeTypeSpecifier) declspec).getName().getLastName(); - if (name instanceof ICPPASTTemplateId) { - name.resolveBinding(); + if (declspec instanceof IASTCompositeTypeSpecifier) { + // Definition of a class[template[specialization]] + name= ((IASTCompositeTypeSpecifier) declspec).getName().getLastName(); + } else if (declspec instanceof ICPPASTElaboratedTypeSpecifier + && sdecl.getDeclarators().length == 0) { + ASTNodeProperty prop = declaration.getPropertyInParent(); + if (prop == ICPPASTTemplateDeclaration.OWNED_DECLARATION + || prop == ICPPASTTemplateSpecialization.OWNED_DECLARATION) { + ICPPASTElaboratedTypeSpecifier elab= (ICPPASTElaboratedTypeSpecifier) declspec; + if (!elab.isFriend()) { + // Declaration of a class template specialization. + name= elab.getName().getLastName(); + } } } + if (name instanceof ICPPASTTemplateId) { + name.resolveBinding(); + } } return PROCESS_CONTINUE; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java index 6209de3ac31..c7752367055 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java @@ -30,12 +30,13 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier private int fKey; private IASTName fName; - private ICPPClassScope fScope; + private CPPClassScope fScope; private IASTDeclaration[] fAllDeclarations; private IASTDeclaration[] fActiveDeclarations; private int fDeclarationsPos=-1; private ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier[] baseSpecs = null; private int baseSpecsPos = -1; + private boolean fAmbiguitiesResolved= false; public CPPASTCompositeTypeSpecifier() { @@ -46,6 +47,13 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier setName(n); } + public void setAmbiguitiesResolved() { + if (!fAmbiguitiesResolved && fScope != null) { + fScope.createImplicitMembers(); + } + fAmbiguitiesResolved= true; + } + public CPPASTCompositeTypeSpecifier copy() { return copy(CopyStyle.withoutLocations); } @@ -140,15 +148,15 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier } public ICPPClassScope getScope() { - if (fScope == null) + if (fScope == null) { fScope = new CPPClassScope(this); + if (fAmbiguitiesResolved) { + fScope.createImplicitMembers(); + } + } return fScope; } - - public void setScope(ICPPClassScope scope) { - this.fScope = scope; - } - + @Override public boolean accept(ASTVisitor action) { if (action.shouldVisitDeclSpecifiers) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java index ae367bf1e92..44c7ab3c778 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java @@ -15,8 +15,10 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ISemanticProblem; @@ -128,7 +130,11 @@ public class CPPASTTemplateId extends CPPASTNameBase implements ICPPASTTemplateI if (needComma) buf.append(", "); //$NON-NLS-1$ needComma= true; - if (arg instanceof IASTExpression) { + IASTNodeLocation[] nodeLocs = arg.getNodeLocations(); + if (nodeLocs.length == 1 && nodeLocs[0] instanceof IASTFileLocation) { + buf.append(arg.getRawSignature()); + cleanupWhitespace= true; + } else if (arg instanceof IASTExpression) { IValue value= Value.create((IASTExpression) arg, Value.MAX_RECURSION_DEPTH); if (value != Value.UNKNOWN && !Value.isDependentValue(value)) { buf.append(value.getSignature()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index 618c29500d2..382288893f0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -71,18 +71,18 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { public CPPClassScope(ICPPASTCompositeTypeSpecifier physicalNode) { super(physicalNode); - ((CPPASTCompositeTypeSpecifier) physicalNode).setScope(this); - createImplicitMembers(); } public EScopeKind getKind() { return EScopeKind.eClassType; } - // 12.1 The default constructor, copy constructor, copy assignment operator, and destructor are - //special member functions. The implementation will implicitly declare these member functions - //for a class type when the program does not declare them. - private void createImplicitMembers() { + /** + * Add in default constructor, copy constructor, copy assignment operator and destructor, + * if appropriate. + * Method will be called after ambiguity resolution. + */ + public void createImplicitMembers() { //create bindings for the implicit members, if the user declared them then those declarations //will resolve to these bindings. ICPPASTCompositeTypeSpecifier compTypeSpec = (ICPPASTCompositeTypeSpecifier) getPhysicalNode(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index 6e2447413ea..53a3453f8be 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -12,22 +12,15 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; -import org.eclipse.cdt.core.dom.ast.ASTVisitor; -import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; -import org.eclipse.cdt.core.dom.ast.IASTDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; @@ -35,7 +28,6 @@ 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.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; @@ -51,7 +43,6 @@ public class CPPClassSpecialization extends CPPSpecialization private ICPPClassSpecializationScope specScope; private ObjectMap specializationMap= ObjectMap.EMPTY_MAP; - private boolean checked; public CPPClassSpecialization(ICPPClassType specialized, IBinding owner, ICPPTemplateParameterMap argumentMap) { super(specialized, owner, argumentMap); @@ -82,84 +73,8 @@ public class CPPClassSpecialization extends CPPSpecialization } } - private class FindDeclarationDefinitionAction extends ASTVisitor { - private char [] nameArray = CPPClassSpecialization.this.getNameCharArray(); - public IASTName foundDef = null; - public IASTName foundDecl = null; - - { - shouldVisitNames = true; - shouldVisitDeclarations = true; - shouldVisitDeclSpecifiers = true; - shouldVisitDeclarators = true; - } - - @Override - public int visit(IASTName name) { - final IASTNode parent = name.getParent(); - final boolean isDef = parent instanceof ICPPASTCompositeTypeSpecifier; - final boolean isDecl = !isDef && parent instanceof ICPPASTElaboratedTypeSpecifier - && parent.getParent() instanceof IASTSimpleDeclaration; - if (isDef || isDecl) { - name= name.getLastName(); - if (CharArrayUtils.equals(name.getLookupKey(), nameArray)) { - IBinding binding = name.resolveBinding(); - if (binding == CPPClassSpecialization.this) { - if (isDef) { - foundDef= name; - return PROCESS_ABORT; - } - if (foundDecl == null) - foundDecl= name; - } - } - } - // Don't look at members of qualified names or template ids. - return PROCESS_SKIP; - } - - @Override - public int visit( IASTDeclaration declaration ){ - if(declaration instanceof IASTSimpleDeclaration || declaration instanceof ICPPASTTemplateDeclaration) - return PROCESS_CONTINUE; - return PROCESS_SKIP; - } - @Override - public int visit( IASTDeclSpecifier declSpec ){ - return (declSpec instanceof ICPPASTCompositeTypeSpecifier ) ? PROCESS_CONTINUE : PROCESS_SKIP; - } - @Override - public int visit( IASTDeclarator declarator ) { return PROCESS_SKIP; } - } - public void checkForDefinition() { - if( !checked && definition == null ) { - IBinding orig= getSpecializedBinding(); - IASTTranslationUnit tu= null; - while (orig != null) { - if (orig instanceof ICPPInternalBinding) { - IASTNode node= ((ICPPInternalBinding) orig).getDefinition(); - if (node != null) { - tu= node.getTranslationUnit(); - if (tu != null) - break; - } - } - if (!(orig instanceof ICPPSpecialization)) - break; - orig= ((ICPPSpecialization) orig).getSpecializedBinding(); - } - if (tu != null) { - FindDeclarationDefinitionAction action= new FindDeclarationDefinitionAction(); - tu.accept( action ); - definition = action.foundDef; - if (definition == null && action.foundDecl != null) { - addDeclaration(action.foundDecl); - } - } - checked = true; - } - return; + // Ambiguity resolution ensures that declarations and definitions are resolved. } public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java index 409de0c5536..09640c55525 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java @@ -14,14 +14,9 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; -import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; -import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; -import org.eclipse.cdt.core.dom.ast.IASTDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IField; @@ -31,8 +26,6 @@ import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; @@ -46,9 +39,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.util.ArrayUtil; -import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; /** * Represents a class template. @@ -58,56 +49,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass private ICPPClassTemplate fIndexBinding= null; private boolean checkedIndex= false; - private boolean checkedDefinition= false; - private class FindDefinitionAction extends ASTVisitor { - private char[] nameArray = CPPClassTemplate.this.getNameCharArray(); - public IASTName result = null; - - FindDefinitionAction() { - shouldVisitNames = true; - shouldVisitDeclarations = true; - shouldVisitDeclSpecifiers = true; - shouldVisitDeclarators = true; - } - - @Override - public int visit(IASTName name) { - if (name instanceof ICPPASTTemplateId || name instanceof ICPPASTQualifiedName) - return PROCESS_CONTINUE; - char[] c = name.getLookupKey(); - if (name.getParent() instanceof ICPPASTTemplateId) - name = (IASTName) name.getParent(); - if (name.getParent() instanceof ICPPASTQualifiedName) { - IASTName[] ns = ((ICPPASTQualifiedName) name.getParent()).getNames(); - if (ns[ns.length - 1] != name) - return PROCESS_CONTINUE; - name = (IASTName) name.getParent(); - } - - if (name.getParent() instanceof ICPPASTCompositeTypeSpecifier && CharArrayUtils.equals(c, nameArray)) { - IBinding binding = name.resolveBinding(); - if (binding == CPPClassTemplate.this) { - result = name.getLastName(); - return PROCESS_ABORT; - } - } - return PROCESS_CONTINUE; - } - - @Override - public int visit(IASTDeclaration declaration) { - if (declaration instanceof IASTSimpleDeclaration || declaration instanceof ICPPASTTemplateDeclaration) - return PROCESS_CONTINUE; - return PROCESS_SKIP; - } - @Override - public int visit(IASTDeclSpecifier declSpec) { - return (declSpec instanceof ICPPASTCompositeTypeSpecifier) ? PROCESS_CONTINUE : PROCESS_SKIP; - } - @Override - public int visit(IASTDeclarator declarator) { return PROCESS_SKIP; } - } private ICPPClassTemplatePartialSpecialization[] partialSpecializations = null; private ICPPDeferredClassInstance fDeferredInstance; @@ -117,24 +59,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass } public void checkForDefinition() { - if (checkedDefinition) - return; - - checkedDefinition= true; - if (definition != null) - return; - - FindDefinitionAction action = new FindDefinitionAction(); - IASTNode node = CPPVisitor.getContainingBlockItem(declarations[0]).getParent(); - while (node instanceof ICPPASTTemplateDeclaration) - node = node.getParent(); - node.accept(action); - definition = action.result; - - if (definition == null) { - node.getTranslationUnit().accept(action); - definition = action.result; - } + // Ambiguity resolution ensures that definitions are resolved. } public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index f48af6c28ac..4b9064f2ef8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -15,16 +15,11 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ILinkage; -import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; -import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; -import org.eclipse.cdt.core.dom.ast.IASTDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IScope; @@ -33,8 +28,6 @@ import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; @@ -46,7 +39,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.util.ArrayUtil; -import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; @@ -103,58 +95,6 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp } } - private class FindDefinitionAction extends ASTVisitor { - private char[] nameArray = CPPClassType.this.getNameCharArray(); - public IASTName result = null; - - { - shouldVisitNames = true; - shouldVisitDeclarations = true; - shouldVisitDeclSpecifiers = true; - shouldVisitDeclarators = true; - } - - @Override - public int visit(IASTName name) { - if (name instanceof ICPPASTTemplateId) - return PROCESS_SKIP; - if (name instanceof ICPPASTQualifiedName) - return PROCESS_CONTINUE; - char[] c = name.getLookupKey(); - - if (name.getParent() instanceof ICPPASTQualifiedName) { - IASTName[] ns = ((ICPPASTQualifiedName) name.getParent()).getNames(); - if (ns[ns.length - 1] != name) - return PROCESS_CONTINUE; - name = (IASTName) name.getParent(); - } - - if (name.getParent() instanceof ICPPASTCompositeTypeSpecifier && CharArrayUtils.equals(c, nameArray)) { - IBinding binding = name.resolveBinding(); - if (binding == CPPClassType.this) { - result= name.getLastName(); - return PROCESS_ABORT; - } - } - return PROCESS_CONTINUE; - } - - @Override - public int visit(IASTDeclaration declaration) { - if (declaration instanceof IASTSimpleDeclaration || declaration instanceof ICPPASTTemplateDeclaration) - return PROCESS_CONTINUE; - return PROCESS_SKIP; - } - @Override - public int visit(IASTDeclSpecifier declSpec) { - return (declSpec instanceof ICPPASTCompositeTypeSpecifier) ? PROCESS_CONTINUE : PROCESS_SKIP; - } - @Override - public int visit(IASTDeclarator declarator) { - return PROCESS_SKIP; - } - } - private IASTName definition; private IASTName[] declarations; private boolean checked = false; @@ -188,30 +128,16 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp } public void checkForDefinition() { - if (!checked && definition == null) { - FindDefinitionAction action = new FindDefinitionAction(); - IASTNode node = CPPVisitor.getContainingBlockItem(getPhysicalNode()).getParent(); - - if (node instanceof ICPPASTCompositeTypeSpecifier) - node = CPPVisitor.getContainingBlockItem(node.getParent()); - while(node instanceof ICPPASTTemplateDeclaration) - node = node.getParent(); - node.accept(action); - definition = action.result; - - if (definition == null) { - final IASTTranslationUnit translationUnit = node.getTranslationUnit(); - translationUnit.accept(action); - definition = action.result; - if (definition == null && typeInIndex == null) { - IIndex index= translationUnit.getIndex(); - if (index != null) { - typeInIndex= (ICPPClassType) index.adaptBinding(this); - } + // Ambiguity resolution ensures that definitions are resolved. + if (!checked) { + if (definition == null && typeInIndex == null) { + IIndex index= getPhysicalNode().getTranslationUnit().getIndex(); + if (index != null) { + typeInIndex= (ICPPClassType) index.adaptBinding(this); } } + checked = true; } - checked = true; } public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() { @@ -291,26 +217,30 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp } public void addDefinition(IASTNode node) { - if (node instanceof ICPPASTCompositeTypeSpecifier) + if (node instanceof ICPPASTCompositeTypeSpecifier) { definition = ((ICPPASTCompositeTypeSpecifier)node).getName(); + } else { + assert false; + } } public void addDeclaration(IASTNode node) { - if (!(node instanceof ICPPASTElaboratedTypeSpecifier)) - return; + if (node instanceof ICPPASTElaboratedTypeSpecifier) { + IASTName name = ((ICPPASTElaboratedTypeSpecifier) node).getName(); - IASTName name = ((ICPPASTElaboratedTypeSpecifier) node).getName(); + if (declarations == null) { + declarations = new IASTName[] { name }; + return; + } - if (declarations == null) { - declarations = new IASTName[] { name }; - return; - } - - // Keep the lowest offset declaration in [0] - if (declarations.length > 0 && ((ASTNode)node).getOffset() < ((ASTNode) declarations[0]).getOffset()) { - declarations = (IASTName[]) ArrayUtil.prepend(IASTName.class, declarations, name); + // Keep the lowest offset declaration in [0] + if (declarations.length > 0 && ((ASTNode)node).getOffset() < ((ASTNode) declarations[0]).getOffset()) { + declarations = (IASTName[]) ArrayUtil.prepend(IASTName.class, declarations, name); + } else { + declarations = (IASTName[]) ArrayUtil.append(IASTName.class, declarations, name); + } } else { - declarations = (IASTName[]) ArrayUtil.append(IASTName.class, declarations, name); + assert false; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index c074fcfc1b0..5799476eeb0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -222,26 +222,29 @@ public class CPPVisitor extends ASTQueries { IASTNode parent = name.getParent(); IBinding binding = null; if (parent instanceof IASTNamedTypeSpecifier || - parent instanceof ICPPASTQualifiedName || parent instanceof ICPPASTBaseSpecifier || parent instanceof ICPPASTConstructorChainInitializer || name.getPropertyInParent() == ICPPASTNamespaceAlias.MAPPING_NAME) { if (name.getLookupKey().length == 0) return null; - - binding = CPPSemantics.resolveBinding(name); - if (binding instanceof IProblemBinding && parent instanceof ICPPASTQualifiedName && - !(parent.getParent() instanceof ICPPASTNamespaceAlias)) { - final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) parent; - final IASTName[] ns = qname.getNames(); - if (ns[ns.length - 1] != name) - return binding; - - if (ns.length > 1 && ns[ns.length - 2].getBinding() instanceof IProblemBinding) - return binding; - - parent = parent.getParent(); - if (((IProblemBinding) binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND) { + + return CPPSemantics.resolveBinding(name); + } else if (parent instanceof ICPPASTQualifiedName) { + if (name.getLookupKey().length == 0) + return null; + + final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) parent; + if (name != qname.getLastName()) + 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) { @@ -264,8 +267,13 @@ public class CPPVisitor extends ASTQueries { return binding; } } else { - if (binding instanceof ICPPClassType && binding instanceof IIndexBinding && name.isDefinition()) { - parent= parent.getParent(); // need to create an ast binding. + if (parent instanceof IASTCompositeTypeSpecifier) { + if (binding instanceof IIndexBinding) { + // Need to create an AST binding + } else { + ASTInternal.addDefinition(binding, parent); + return binding; + } } else { return binding; } @@ -428,7 +436,7 @@ public class CPPVisitor extends ASTQueries { (elabType.getName() instanceof ICPPASTQualifiedName || elabType.getKind() == IASTElaboratedTypeSpecifier.k_enum)) { return binding; } - + try { boolean template = false; ICPPScope scope = (ICPPScope) getContainingScope(name); @@ -457,21 +465,46 @@ public class CPPVisitor extends ASTQueries { } } } - if (!(binding instanceof ICPPInternalBinding) || !(binding instanceof ICPPClassType) && name.isActive()) { - if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) { - if (template) - binding = new CPPClassTemplate(name); - else - binding = new CPPClassType(name, binding); - // name may live in a different scope, so make sure to add it to the owner scope, as well. - ASTInternal.addName(scope, elabType.getName()); - } - } else { - if ((binding instanceof ICPPClassTemplate) == template) { - ASTInternal.addDeclaration(binding, elabType); - } else { - binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION); - } + if (binding instanceof ICPPInternalBinding) { + if (!name.isActive()) + return binding; + + if (binding instanceof ICPPClassType) { + final ICPPInternalBinding ib = (ICPPInternalBinding) binding; + if ((binding instanceof ICPPClassTemplate) == template) { + ib.addDeclaration(elabType); + return binding; + } + if (CPPSemantics.declaredBefore(binding, name, false)) { + return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION); + } + + // Mark the other declarations as problem and create the binding + final IASTNode[] decls = ib.getDeclarations(); + if (decls != null) { + for (IASTNode decl : decls) { + if (decl instanceof IASTName) { + final IASTName n = (IASTName) decl; + n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDECLARATION)); + } + } + } + IASTNode decl= ib.getDefinition(); + if (decl instanceof IASTName) { + final IASTName n = (IASTName) decl; + n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDEFINITION)); + } + } + } + + // Create a binding + if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) { + if (template) + binding = new CPPClassTemplate(name); + else + binding = new CPPClassType(name, binding); + // name may live in a different scope, so make sure to add it to the owner scope, as well. + ASTInternal.addName(scope, elabType.getName()); } } catch (DOMException e) { binding = e.getProblem(); @@ -2314,7 +2347,7 @@ public class CPPVisitor extends ASTQueries { } public static IBinding findNameOwner(IASTName name, boolean allowFunction) { - IASTNode node= name; + IASTNode node= name.getLastName(); while (node instanceof IASTName) { if (node instanceof ICPPASTQualifiedName) { IASTName[] qn= ((ICPPASTQualifiedName) node).getNames();