1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-10 12:03:16 +02:00

Name resolution for names declared within a template, bug 257186

This commit is contained in:
Markus Schorn 2008-12-02 13:50:57 +00:00
parent 4145150968
commit 9888670468
12 changed files with 120 additions and 83 deletions

View file

@ -3404,7 +3404,7 @@ public class AST2TemplateTests extends AST2BaseTest {
// this->a= 1;
// }
// };
public void _testFieldReference_Bug234321() throws Exception {
public void testFieldReference_Bug257186() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);

View file

@ -1,12 +1,13 @@
/*******************************************************************************
* Copyright (c) 2004, 2005 IBM Corporation and others.
* Copyright (c) 2004, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
@ -17,7 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* @author jcamelon
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTCompositeTypeSpecifier extends
IASTCompositeTypeSpecifier, ICPPASTDeclSpecifier {
@ -141,4 +142,8 @@ public interface ICPPASTCompositeTypeSpecifier extends
*/
public void addBaseSpecifier(ICPPASTBaseSpecifier baseSpec);
/**
* @since 5.1
*/
public ICPPClassScope getScope();
}

View file

@ -6,7 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -14,21 +15,21 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
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.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* @author jcamelon
* c++ specific composite type specifier
*/
public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier
implements ICPPASTCompositeTypeSpecifier, IASTAmbiguityParent {
private int k;
private IASTName n;
private IScope scope;
private ICPPClassScope scope;
public CPPASTCompositeTypeSpecifier() {
@ -97,14 +98,14 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier
private ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier [] baseSpecs = null;
private int baseSpecsPos=-1;
public IScope getScope() {
public ICPPClassScope getScope() {
if( scope == null )
scope = new CPPClassScope( this );
return scope;
}
public void setScope( IScope scope ){
public void setScope(ICPPClassScope scope) {
this.scope = scope;
}

View file

@ -22,7 +22,6 @@ 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;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
@ -31,6 +30,7 @@ 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.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
@ -257,8 +257,8 @@ public class CPPClassSpecialization extends CPPSpecialization
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.ICompositeType#getCompositeScope()
*/
public IScope getCompositeScope() throws DOMException {
final IScope specScope= getSpecializationScope();
public ICPPClassScope getCompositeScope() throws DOMException {
final ICPPClassScope specScope= getSpecializationScope();
if (specScope != null)
return specScope;

View file

@ -23,7 +23,6 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
@ -39,8 +38,11 @@ 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.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
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;
import org.eclipse.cdt.internal.core.index.IIndexType;
@ -106,6 +108,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
}
private ICPPClassTemplatePartialSpecialization[] partialSpecializations = null;
private ICPPDeferredClassInstance fDeferredInstance;
public CPPClassTemplate(IASTName name) {
super(name);
@ -143,7 +146,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
return null;
}
public IScope getCompositeScope() {
public ICPPScope getCompositeScope() {
if (definition == null) {
checkForDefinition();
}
@ -254,4 +257,16 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
public boolean isAnonymous() {
return false;
}
public ICPPDeferredClassInstance asDeferredInstance() throws DOMException {
if (fDeferredInstance == null) {
fDeferredInstance= createDeferredInstance();
}
return fDeferredInstance;
}
protected ICPPDeferredClassInstance createDeferredInstance() throws DOMException {
ICPPTemplateArgument[] args = CPPTemplates.templateParametersAsArguments(getTemplateParameters());
return new CPPDeferredClassInstance(this, args, getCompositeScope());
}
}

View file

@ -62,6 +62,11 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate
return CPPTemplateParameterMap.EMPTY;
}
}
@Override
protected ICPPDeferredClassInstance createDeferredInstance() throws DOMException {
return new CPPDeferredClassInstance(this, getTemplateArguments(), getCompositeScope());
}
@Override
public String toString() {

View file

@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
/**
* Represents a specialization of a class-template
@ -31,6 +32,7 @@ public class CPPClassTemplateSpecialization extends CPPClassSpecialization
implements ICPPClassTemplate, ICPPInternalClassTemplate {
private ObjectMap instances = null;
private ICPPDeferredClassInstance fDeferredInstance;
public CPPClassTemplateSpecialization(ICPPClassTemplate orig, ICPPClassType owner, ICPPTemplateParameterMap argumentMap) {
super(orig, owner, argumentMap);
@ -100,4 +102,12 @@ public class CPPClassTemplateSpecialization extends CPPClassSpecialization
public IBinding resolveTemplateParameter(ICPPTemplateParameter param) {
return param;
}
public ICPPDeferredClassInstance asDeferredInstance() throws DOMException {
if (fDeferredInstance == null) {
ICPPTemplateArgument[] args = CPPTemplates.templateParametersAsArguments(getTemplateParameters());
fDeferredInstance= new CPPDeferredClassInstance(this, args, getCompositeScope());
}
return fDeferredInstance;
}
}

View file

@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.parser.util.ObjectMap;
@ -31,12 +32,17 @@ public class CPPDeferredClassInstance extends CPPUnknownClass implements ICPPDef
private final ICPPTemplateArgument[] fArguments;
private final ICPPClassTemplate fClassTemplate;
private final ICPPScope fLookupScope;
public CPPDeferredClassInstance(ICPPClassTemplate template, ICPPTemplateArgument[] arguments) throws DOMException {
public CPPDeferredClassInstance(ICPPClassTemplate template, ICPPTemplateArgument[] arguments, ICPPScope lookupScope) throws DOMException {
super(template.getOwner(), new CPPASTName(template.getNameCharArray()));
fArguments= arguments;
fClassTemplate= template;
fLookupScope= lookupScope;
}
public CPPDeferredClassInstance(ICPPClassTemplate template, ICPPTemplateArgument[] arguments) throws DOMException {
this(template, arguments, null);
}
public ICPPClassTemplate getClassTemplate() {
@ -103,6 +109,14 @@ public class CPPDeferredClassInstance extends CPPUnknownClass implements ICPPDef
public IScope getScope() throws DOMException {
return fClassTemplate.getScope();
}
@Override
public ICPPScope getUnknownScope() throws DOMException {
if (fLookupScope != null)
return fLookupScope;
return super.getUnknownScope();
}
@Override
public String toString() {

View file

@ -6,16 +6,22 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Andrew Niefer (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
/**
* @author aniefer
*
* Interface for class templates used in the AST.
*/
public interface ICPPInternalClassTemplate extends ICPPInternalTemplate {
public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec);
/**
* Returns a deferred instance that allows lookups within this class template.
*/
public ICPPDeferredClassInstance asDeferredInstance() throws DOMException;
}

View file

@ -148,6 +148,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
@ -282,6 +283,16 @@ public class CPPSemantics {
}
}
}
} else if (binding instanceof ICPPDeferredClassInstance) {
// try to replace binding by the one pointing to the enclosing template declaration.
ICPPDeferredClassInstance dcl= (ICPPDeferredClassInstance) binding;
IBinding usedHere= CPPTemplates.isUsedInClassTemplateScope(dcl.getClassTemplate(), data.astName);
if (usedHere instanceof ICPPDeferredClassInstance) {
ICPPDeferredClassInstance alt= (ICPPDeferredClassInstance) usedHere;
if (CPPTemplates.areSameArguments(alt.getTemplateArguments(), dcl.getTemplateArguments())) {
binding= alt;
}
}
}
if (binding instanceof ICPPClassType && data.considerConstructors) {

View file

@ -50,6 +50,7 @@ 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.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
@ -228,7 +229,14 @@ public class CPPTemplates {
static IBinding isUsedInClassTemplateScope(ICPPClassTemplate ct, IASTName name) {
try {
IScope scope= CPPVisitor.getContainingScope(name);
IASTName start= name;
ICPPASTFunctionDefinition func= CPPVisitor.findEnclosingFunctionDefinition(name);
if (func != null) {
start= CPPVisitor.findInnermostDeclarator(func.getDeclarator()).getName();
start= start.getLastName();
}
IScope scope= CPPVisitor.getContainingScope(start);
while (scope instanceof IASTInternalScope) {
final IASTInternalScope internalScope = (IASTInternalScope) scope;
if (scope instanceof ICPPClassScope) {
@ -411,23 +419,16 @@ public class CPPTemplates {
* Instantiates the template for usage within its own body. May return <code>null</code>.
*/
public static ICPPClassType instantiateWithinClassTemplate(ICPPClassTemplate template) throws DOMException {
if (template instanceof ICPPInternalClassTemplate) {
return ((ICPPInternalClassTemplate) template).asDeferredInstance();
}
ICPPTemplateArgument[] args;
if (template instanceof ICPPClassTemplatePartialSpecialization) {
args= ((ICPPClassTemplatePartialSpecialization) template).getTemplateArguments();
} else {
ICPPTemplateParameter[] templateParameters = template.getTemplateParameters();
args = new ICPPTemplateArgument[templateParameters.length];
for (int i = 0; i < templateParameters.length; i++) {
final ICPPTemplateParameter tp = templateParameters[i];
if (tp instanceof IType) {
args[i] = new CPPTemplateArgument((IType) tp);
} else if (tp instanceof ICPPTemplateNonTypeParameter) {
final ICPPTemplateNonTypeParameter nttp = (ICPPTemplateNonTypeParameter) tp;
args[i] = new CPPTemplateArgument(Value.create(nttp), nttp.getType());
} else {
assert false;
}
}
args = templateParametersAsArguments(templateParameters);
}
IBinding result = deferredInstance(template, args);
if (result instanceof ICPPClassType)
@ -436,6 +437,24 @@ public class CPPTemplates {
return template;
}
public static ICPPTemplateArgument[] templateParametersAsArguments(
ICPPTemplateParameter[] templateParameters) throws DOMException {
ICPPTemplateArgument[] args;
args = new ICPPTemplateArgument[templateParameters.length];
for (int i = 0; i < templateParameters.length; i++) {
final ICPPTemplateParameter tp = templateParameters[i];
if (tp instanceof IType) {
args[i] = new CPPTemplateArgument((IType) tp);
} else if (tp instanceof ICPPTemplateNonTypeParameter) {
final ICPPTemplateNonTypeParameter nttp = (ICPPTemplateNonTypeParameter) tp;
args[i] = new CPPTemplateArgument(Value.create(nttp), nttp.getType());
} else {
assert false;
}
}
return args;
}
/**
* Extracts the IASTName of a template parameter.
*/

View file

@ -121,7 +121,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
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.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
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.ICPPFunction;
@ -133,8 +132,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
@ -180,7 +177,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable;
import org.eclipse.cdt.internal.core.dom.parser.cpp.GPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.GPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.GPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
@ -946,11 +942,7 @@ public class CPPVisitor extends ASTQueries {
boolean done= true;
IScope scope= null;
if (binding instanceof ICPPClassType) {
if (binding instanceof ICPPDeferredClassInstance) {
scope= checkForSpecializedScope((ICPPDeferredClassInstance) binding, qname);
}
if (scope == null)
scope= ((ICPPClassType)binding).getCompositeScope();
scope= ((ICPPClassType)binding).getCompositeScope();
} else if (binding instanceof ICPPNamespace) {
scope= ((ICPPNamespace)binding).getNamespaceScope();
} else if (binding instanceof ICPPUnknownBinding) {
@ -996,47 +988,6 @@ public class CPPVisitor extends ASTQueries {
return getContainingScope(parent);
}
/**
* Checks whether the scope for a deferred instance should be a specialized variant of
* the class-template.
*/
private static IScope checkForSpecializedScope(ICPPDeferredClassInstance dcli, final ICPPASTQualifiedName qname)
throws DOMException {
ICPPClassTemplate ct = dcli.getClassTemplate();
ICPPTemplateArgument[] args = dcli.getTemplateArguments();
IASTName start= qname;
ICPPASTFunctionDefinition func= findEnclosingFunctionDefinition(qname);
if (func != null) {
start= findInnermostDeclarator(func.getDeclarator()).getName();
if (start == qname)
return null;
start= start.getLastName();
}
IScope lookupScope= getContainingNonTemplateScope(start);
while (lookupScope != null) {
if (lookupScope instanceof ICPPClassScope) {
ICPPClassScope clscope= (ICPPClassScope) lookupScope;
ICPPClassType ctype = clscope.getClassType();
if (ctype instanceof ICPPClassTemplatePartialSpecialization) {
ICPPTemplateArgument[] args1 = ((ICPPClassTemplatePartialSpecialization) ctype).getTemplateArguments();
if (CPPTemplates.areSameArguments(args, args1))
return lookupScope;
} else if (ctype instanceof ICPPTemplateInstance) {
ICPPTemplateArgument[] args1 = ((ICPPTemplateInstance) ctype).getTemplateArguments();
if (CPPTemplates.areSameArguments(args, args1))
return lookupScope;
} else if (ctype instanceof ICPPClassTemplate) {
if (ct.isSameType(ctype) &&
CPPTemplates.argsAreTrivial(ct.getTemplateParameters(), args)) {
return lookupScope;
}
}
}
lookupScope= lookupScope.getParent();
}
return null;
}
public static IScope getContainingScope(IASTStatement statement) {
IASTNode parent = statement.getParent();
IScope scope = null;