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

Bug 359364: Prevent premature access to ambiguous nodes.

This commit is contained in:
Markus Schorn 2011-09-30 10:00:09 +02:00
parent e290bc4877
commit 9adfab7918
9 changed files with 164 additions and 310 deletions

View file

@ -9526,4 +9526,16 @@ public class AST2CPPTests extends AST2BaseTest {
ICPPClassType c= bh.assertNonProblem("A", 1); ICPPClassType c= bh.assertNonProblem("A", 1);
assertEquals(0, ClassTypeHelper.getPureVirtualMethods(c).length); assertEquals(0, ClassTypeHelper.getPureVirtualMethods(c).length);
} }
// template <typename T> struct CT1 {};
// template <typename T> struct CT2 {};
// typedef char Tdef;
// template<> struct CT1< CT2<int> > {
// CT1<Tdef> x; // Ambiguity causes lookup in CT1< CT2<int> >
// };
// template<> struct CT2<Tdef> { // Accessed before ambiguity is resolved
// };
public void testAmbiguityResolution_Bug359364() throws Exception {
parseAndCheckBindings();
}
} }

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; 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.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; 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.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IScope; 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.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.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.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; 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) { public int leave(IASTDeclSpecifier declSpec) {
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
fDeferFunctions--; 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; return PROCESS_CONTINUE;
} }
@ -128,17 +140,30 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
if (fRepopulate.remove(declaration)) { if (fRepopulate.remove(declaration)) {
repopulateScope(declaration); repopulateScope(declaration);
} }
// Explicit and partial class template specializations need to be resolved right away, // We need to create class bindings for all definitions and for the specializations.
// otherwise we fail to correctly resolve qualified names that depend on a partial specialization. // Otherwise, name resolution cannot access members or correct specialization.
if (declaration instanceof IASTSimpleDeclaration) { if (declaration instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) declaration; IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) declaration;
IASTName name= null;
IASTDeclSpecifier declspec = sdecl.getDeclSpecifier(); IASTDeclSpecifier declspec = sdecl.getDeclSpecifier();
if (declspec instanceof IASTCompositeTypeSpecifier && sdecl.getDeclarators().length == 0) { if (declspec instanceof IASTCompositeTypeSpecifier) {
IASTName name= ((IASTCompositeTypeSpecifier) declspec).getName().getLastName(); // Definition of a class[template[specialization]]
if (name instanceof ICPPASTTemplateId) { name= ((IASTCompositeTypeSpecifier) declspec).getName().getLastName();
name.resolveBinding(); } 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; return PROCESS_CONTINUE;
} }

View file

@ -30,12 +30,13 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier
private int fKey; private int fKey;
private IASTName fName; private IASTName fName;
private ICPPClassScope fScope; private CPPClassScope fScope;
private IASTDeclaration[] fAllDeclarations; private IASTDeclaration[] fAllDeclarations;
private IASTDeclaration[] fActiveDeclarations; private IASTDeclaration[] fActiveDeclarations;
private int fDeclarationsPos=-1; private int fDeclarationsPos=-1;
private ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier[] baseSpecs = null; private ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier[] baseSpecs = null;
private int baseSpecsPos = -1; private int baseSpecsPos = -1;
private boolean fAmbiguitiesResolved= false;
public CPPASTCompositeTypeSpecifier() { public CPPASTCompositeTypeSpecifier() {
@ -46,6 +47,13 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier
setName(n); setName(n);
} }
public void setAmbiguitiesResolved() {
if (!fAmbiguitiesResolved && fScope != null) {
fScope.createImplicitMembers();
}
fAmbiguitiesResolved= true;
}
public CPPASTCompositeTypeSpecifier copy() { public CPPASTCompositeTypeSpecifier copy() {
return copy(CopyStyle.withoutLocations); return copy(CopyStyle.withoutLocations);
} }
@ -140,15 +148,15 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier
} }
public ICPPClassScope getScope() { public ICPPClassScope getScope() {
if (fScope == null) if (fScope == null) {
fScope = new CPPClassScope(this); fScope = new CPPClassScope(this);
if (fAmbiguitiesResolved) {
fScope.createImplicitMembers();
}
}
return fScope; return fScope;
} }
public void setScope(ICPPClassScope scope) {
this.fScope = scope;
}
@Override @Override
public boolean accept(ASTVisitor action) { public boolean accept(ASTVisitor action) {
if (action.shouldVisitDeclSpecifiers) { if (action.shouldVisitDeclSpecifiers) {

View file

@ -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.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTExpression; 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.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; 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.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
@ -128,7 +130,11 @@ public class CPPASTTemplateId extends CPPASTNameBase implements ICPPASTTemplateI
if (needComma) if (needComma)
buf.append(", "); //$NON-NLS-1$ buf.append(", "); //$NON-NLS-1$
needComma= true; 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); IValue value= Value.create((IASTExpression) arg, Value.MAX_RECURSION_DEPTH);
if (value != Value.UNKNOWN && !Value.isDependentValue(value)) { if (value != Value.UNKNOWN && !Value.isDependentValue(value)) {
buf.append(value.getSignature()); buf.append(value.getSignature());

View file

@ -71,18 +71,18 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
public CPPClassScope(ICPPASTCompositeTypeSpecifier physicalNode) { public CPPClassScope(ICPPASTCompositeTypeSpecifier physicalNode) {
super(physicalNode); super(physicalNode);
((CPPASTCompositeTypeSpecifier) physicalNode).setScope(this);
createImplicitMembers();
} }
public EScopeKind getKind() { public EScopeKind getKind() {
return EScopeKind.eClassType; 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 * Add in default constructor, copy constructor, copy assignment operator and destructor,
//for a class type when the program does not declare them. * if appropriate.
private void createImplicitMembers() { * Method will be called after ambiguity resolution.
*/
public void createImplicitMembers() {
//create bindings for the implicit members, if the user declared them then those declarations //create bindings for the implicit members, if the user declared them then those declarations
//will resolve to these bindings. //will resolve to these bindings.
ICPPASTCompositeTypeSpecifier compTypeSpec = (ICPPASTCompositeTypeSpecifier) getPhysicalNode(); ICPPASTCompositeTypeSpecifier compTypeSpec = (ICPPASTCompositeTypeSpecifier) getPhysicalNode();

View file

@ -12,22 +12,15 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; 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.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; 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.IBinding;
import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef; 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.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.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; 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.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; 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.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.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
@ -51,7 +43,6 @@ public class CPPClassSpecialization extends CPPSpecialization
private ICPPClassSpecializationScope specScope; private ICPPClassSpecializationScope specScope;
private ObjectMap specializationMap= ObjectMap.EMPTY_MAP; private ObjectMap specializationMap= ObjectMap.EMPTY_MAP;
private boolean checked;
public CPPClassSpecialization(ICPPClassType specialized, IBinding owner, ICPPTemplateParameterMap argumentMap) { public CPPClassSpecialization(ICPPClassType specialized, IBinding owner, ICPPTemplateParameterMap argumentMap) {
super(specialized, owner, 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() { public void checkForDefinition() {
if( !checked && definition == null ) { // Ambiguity resolution ensures that declarations and definitions are resolved.
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;
} }
public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() { public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() {

View file

@ -14,14 +14,9 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; 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.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.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; 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.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField; 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.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; 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.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.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; 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.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil; 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.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/** /**
* Represents a class template. * Represents a class template.
@ -58,56 +49,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass
private ICPPClassTemplate fIndexBinding= null; private ICPPClassTemplate fIndexBinding= null;
private boolean checkedIndex= false; 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 ICPPClassTemplatePartialSpecialization[] partialSpecializations = null;
private ICPPDeferredClassInstance fDeferredInstance; private ICPPDeferredClassInstance fDeferredInstance;
@ -117,24 +59,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass
} }
public void checkForDefinition() { public void checkForDefinition() {
if (checkedDefinition) // Ambiguity resolution ensures that definitions are resolved.
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;
}
} }
public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec) { public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec) {

View file

@ -15,16 +15,11 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ILinkage; 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.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; 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.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; 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.IBinding;
import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IScope; 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.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; 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.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.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; 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.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil; 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.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; 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 definition;
private IASTName[] declarations; private IASTName[] declarations;
private boolean checked = false; private boolean checked = false;
@ -188,30 +128,16 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
} }
public void checkForDefinition() { public void checkForDefinition() {
if (!checked && definition == null) { // Ambiguity resolution ensures that definitions are resolved.
FindDefinitionAction action = new FindDefinitionAction(); if (!checked) {
IASTNode node = CPPVisitor.getContainingBlockItem(getPhysicalNode()).getParent(); if (definition == null && typeInIndex == null) {
IIndex index= getPhysicalNode().getTranslationUnit().getIndex();
if (node instanceof ICPPASTCompositeTypeSpecifier) if (index != null) {
node = CPPVisitor.getContainingBlockItem(node.getParent()); typeInIndex= (ICPPClassType) index.adaptBinding(this);
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);
}
} }
} }
checked = true;
} }
checked = true;
} }
public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() { public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() {
@ -291,26 +217,30 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
} }
public void addDefinition(IASTNode node) { public void addDefinition(IASTNode node) {
if (node instanceof ICPPASTCompositeTypeSpecifier) if (node instanceof ICPPASTCompositeTypeSpecifier) {
definition = ((ICPPASTCompositeTypeSpecifier)node).getName(); definition = ((ICPPASTCompositeTypeSpecifier)node).getName();
} else {
assert false;
}
} }
public void addDeclaration(IASTNode node) { public void addDeclaration(IASTNode node) {
if (!(node instanceof ICPPASTElaboratedTypeSpecifier)) if (node instanceof ICPPASTElaboratedTypeSpecifier) {
return; IASTName name = ((ICPPASTElaboratedTypeSpecifier) node).getName();
IASTName name = ((ICPPASTElaboratedTypeSpecifier) node).getName(); if (declarations == null) {
declarations = new IASTName[] { name };
return;
}
if (declarations == null) { // Keep the lowest offset declaration in [0]
declarations = new IASTName[] { name }; if (declarations.length > 0 && ((ASTNode)node).getOffset() < ((ASTNode) declarations[0]).getOffset()) {
return; declarations = (IASTName[]) ArrayUtil.prepend(IASTName.class, declarations, name);
} } else {
declarations = (IASTName[]) ArrayUtil.append(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 { } else {
declarations = (IASTName[]) ArrayUtil.append(IASTName.class, declarations, name); assert false;
} }
} }

View file

@ -222,26 +222,29 @@ public class CPPVisitor extends ASTQueries {
IASTNode parent = name.getParent(); IASTNode parent = name.getParent();
IBinding binding = null; IBinding binding = null;
if (parent instanceof IASTNamedTypeSpecifier || if (parent instanceof IASTNamedTypeSpecifier ||
parent instanceof ICPPASTQualifiedName ||
parent instanceof ICPPASTBaseSpecifier || parent instanceof ICPPASTBaseSpecifier ||
parent instanceof ICPPASTConstructorChainInitializer || parent instanceof ICPPASTConstructorChainInitializer ||
name.getPropertyInParent() == ICPPASTNamespaceAlias.MAPPING_NAME) { name.getPropertyInParent() == ICPPASTNamespaceAlias.MAPPING_NAME) {
if (name.getLookupKey().length == 0) if (name.getLookupKey().length == 0)
return null; return null;
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); binding = CPPSemantics.resolveBinding(name);
if (binding instanceof IProblemBinding && parent instanceof ICPPASTQualifiedName && if (binding instanceof IProblemBinding && !(parent instanceof ICPPASTNamespaceAlias)) {
!(parent.getParent() instanceof ICPPASTNamespaceAlias)) { final IASTName[] ns = qname.getNames();
final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) parent; if (ns.length > 1 && ns[ns.length - 2].getBinding() instanceof IProblemBinding)
final IASTName[] ns = qname.getNames(); return binding;
if (ns[ns.length - 1] != name)
return binding;
if (ns.length > 1 && ns[ns.length - 2].getBinding() instanceof IProblemBinding) if (((IProblemBinding) binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND) {
return binding;
parent = parent.getParent();
if (((IProblemBinding) binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND) {
IASTNode node = getContainingBlockItem(name.getParent()); IASTNode node = getContainingBlockItem(name.getParent());
ASTNodeProperty prop= node.getPropertyInParent(); ASTNodeProperty prop= node.getPropertyInParent();
while (prop == ICPPASTTemplateDeclaration.OWNED_DECLARATION) { while (prop == ICPPASTTemplateDeclaration.OWNED_DECLARATION) {
@ -264,8 +267,13 @@ public class CPPVisitor extends ASTQueries {
return binding; return binding;
} }
} else { } else {
if (binding instanceof ICPPClassType && binding instanceof IIndexBinding && name.isDefinition()) { if (parent instanceof IASTCompositeTypeSpecifier) {
parent= parent.getParent(); // need to create an ast binding. if (binding instanceof IIndexBinding) {
// Need to create an AST binding
} else {
ASTInternal.addDefinition(binding, parent);
return binding;
}
} else { } else {
return binding; return binding;
} }
@ -457,21 +465,46 @@ public class CPPVisitor extends ASTQueries {
} }
} }
} }
if (!(binding instanceof ICPPInternalBinding) || !(binding instanceof ICPPClassType) && name.isActive()) { if (binding instanceof ICPPInternalBinding) {
if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) { if (!name.isActive())
if (template) return binding;
binding = new CPPClassTemplate(name);
else if (binding instanceof ICPPClassType) {
binding = new CPPClassType(name, binding); final ICPPInternalBinding ib = (ICPPInternalBinding) binding;
// name may live in a different scope, so make sure to add it to the owner scope, as well. if ((binding instanceof ICPPClassTemplate) == template) {
ASTInternal.addName(scope, elabType.getName()); ib.addDeclaration(elabType);
} return binding;
} else { }
if ((binding instanceof ICPPClassTemplate) == template) { if (CPPSemantics.declaredBefore(binding, name, false)) {
ASTInternal.addDeclaration(binding, elabType); return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION);
} else { }
binding = 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) { } catch (DOMException e) {
binding = e.getProblem(); binding = e.getProblem();
@ -2314,7 +2347,7 @@ public class CPPVisitor extends ASTQueries {
} }
public static IBinding findNameOwner(IASTName name, boolean allowFunction) { public static IBinding findNameOwner(IASTName name, boolean allowFunction) {
IASTNode node= name; IASTNode node= name.getLastName();
while (node instanceof IASTName) { while (node instanceof IASTName) {
if (node instanceof ICPPASTQualifiedName) { if (node instanceof ICPPASTQualifiedName) {
IASTName[] qn= ((ICPPASTQualifiedName) node).getNames(); IASTName[] qn= ((ICPPASTQualifiedName) node).getNames();