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:
parent
e290bc4877
commit
9adfab7918
9 changed files with 164 additions and 310 deletions
|
@ -9526,4 +9526,16 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
ICPPClassType c= bh.assertNonProblem("A", 1);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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 ICPPASTQualifiedName &&
|
||||
!(parent.getParent() instanceof ICPPASTNamespaceAlias)) {
|
||||
final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) parent;
|
||||
final IASTName[] ns = qname.getNames();
|
||||
if (ns[ns.length - 1] != name)
|
||||
return binding;
|
||||
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 (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) {
|
||||
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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue