1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 15:05:36 +02:00

Resolution for dependent names, bug 265926.

This commit is contained in:
Markus Schorn 2009-02-26 16:04:27 +00:00
parent 10042ec8df
commit 35f45ec13f
5 changed files with 143 additions and 17 deletions

View file

@ -3897,7 +3897,7 @@ public class AST2TemplateTests extends AST2BaseTest {
// g(t);
// }
// template <typename T> void g(T t) {}
public void testDependentNameReferencingLaterDeclaration_265926() throws Exception {
public void testDependentNameReferencingLaterDeclaration_265926a() throws Exception {
final String code = getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
IFunction gref= bh.assertNonProblem("g(t)", 1);
@ -3906,4 +3906,25 @@ public class AST2TemplateTests extends AST2BaseTest {
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// class C;
// C* c(void*) {return 0;}
//
// template <typename T> class XT {
// void m();
// C* ptr() {return 0;}
// };
//
// template <typename T> void XT<T>::m() {
// c(this)->a();
// ptr()->a();
// };
//
// class C {
// void a() {};
// };
public void testDependentNameReferencingLaterDeclaration_265926b() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
}

View file

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Set;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
@ -46,6 +47,7 @@ import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
@ -56,6 +58,8 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
@ -88,6 +92,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
@ -569,7 +574,7 @@ public class CPPSemantics {
return (ICPPNamespaceScope) scope;
}
static private ICPPScope getLookupScope(IASTName name) throws DOMException {
static private ICPPScope getLookupScope(IASTName name, LookupData data) throws DOMException {
IASTNode parent = name.getParent();
IScope scope = null;
if (parent instanceof ICPPASTBaseSpecifier) {
@ -586,7 +591,7 @@ public class CPPSemantics {
if (!(binding instanceof IProblemBinding))
scope = binding.getScope();
} else {
scope = CPPVisitor.getContainingScope(name);
scope = CPPVisitor.getContainingScope(name, data);
}
if (scope instanceof ICPPScope) {
return (ICPPScope)scope;
@ -688,15 +693,14 @@ public class CPPSemantics {
*/
static protected void lookup(LookupData data, Object start) throws DOMException {
final IIndexFileSet fileSet= getIndexFileSet(data);
IASTNode blockItem= data.astName;
if (blockItem == null)
if (data.astName == null)
return;
ICPPScope nextScope= null;
if (start instanceof ICPPScope) {
nextScope= (ICPPScope) start;
} else if (start instanceof IASTName) {
nextScope= getLookupScope((IASTName) start);
nextScope= getLookupScope((IASTName) start, data);
}
if (nextScope == null)
return;
@ -717,6 +721,12 @@ public class CPPSemantics {
} else {
nextTmplScope= enclosingTemplateScope(data.astName);
}
if (!data.usesEnclosingScope && nextTmplScope != null) {
nextTmplScope= null;
if (dependsOnTemplateFieldReference(data.astName)) {
data.checkPointOfDecl= false;
}
}
while (nextScope != null || nextTmplScope != null) {
// when the non-template scope is no longer contained within the first template scope,
@ -735,7 +745,6 @@ public class CPPSemantics {
if (scope instanceof IIndexScope && data.tu != null) {
scope= (ICPPScope) data.tu.mapToASTScope(((IIndexScope) scope));
}
blockItem = CPPVisitor.getContainingBlockItem(blockItem);
if (!data.usingDirectivesOnly) {
IBinding[] bindings= getBindingsFromScope(scope, fileSet, data);
@ -800,7 +809,95 @@ public class CPPSemantics {
}
}
private static IBinding[] getBindingsFromScope(ICPPScope scope, final IIndexFileSet fileSet, LookupData data) throws DOMException {
/**
* Checks whether the name directly or indirectly depends on the this pointer.
*/
private static boolean dependsOnTemplateFieldReference(IASTName astName) {
if (astName.getPropertyInParent() != IASTFieldReference.FIELD_NAME)
return false;
final boolean[] result= {false};
final IASTExpression fieldOwner = ((IASTFieldReference)astName.getParent()).getFieldOwner();
fieldOwner.accept(new ASTVisitor(){
{
shouldVisitNames= true;
shouldVisitExpressions= true;
}
@Override
public int visit(IASTName name) {
IBinding b= name.resolvePreBinding();
if (b instanceof ICPPUnknownBinding || b instanceof ICPPTemplateDefinition) {
result[0]= true;
return PROCESS_ABORT;
}
if (b instanceof ICPPMember) {
ICPPMember mem= (ICPPMember) b;
try {
if (!mem.isStatic()) {
ICPPClassType owner= mem.getClassOwner();
if (owner instanceof ICPPUnknownBinding || owner instanceof ICPPTemplateDefinition) {
result[0]= true;
return PROCESS_ABORT;
}
}
} catch (DOMException e) {
}
}
if (name instanceof ICPPASTTemplateId)
return PROCESS_SKIP;
return PROCESS_CONTINUE;
}
@Override
public int visit(IASTExpression expression) {
if (expression instanceof IASTLiteralExpression) {
if (((IASTLiteralExpression) expression).getKind() == IASTLiteralExpression.lk_this) {
final IType thisType = SemanticUtil.getNestedType(expression.getExpressionType(), TDEF | CVQ | PTR | ARRAY | MPTR | REF);
if (thisType instanceof ICPPUnknownBinding || thisType instanceof ICPPTemplateDefinition) {
result[0]= true;
return PROCESS_ABORT;
}
}
}
if (expression instanceof IASTUnaryExpression) {
switch (((IASTUnaryExpression) expression).getOperator()) {
case IASTUnaryExpression.op_sizeof:
case IASTUnaryExpression.op_typeid:
case IASTUnaryExpression.op_throw:
return PROCESS_SKIP;
}
} else if (expression instanceof IASTTypeIdExpression) {
switch (((IASTTypeIdExpression) expression).getOperator()) {
case IASTTypeIdExpression.op_sizeof:
case IASTTypeIdExpression.op_typeid:
return PROCESS_SKIP;
}
} else if (expression instanceof IASTCastExpression) {
if (!((IASTCastExpression) expression).getTypeId().accept(this)) {
return PROCESS_ABORT;
}
return PROCESS_SKIP;
} else if (expression instanceof ICPPASTNewExpression) {
if (!((ICPPASTNewExpression) expression).getTypeId().accept(this)) {
return PROCESS_ABORT;
}
return PROCESS_SKIP;
} else if (expression instanceof ICPPASTSimpleTypeConstructorExpression) {
return PROCESS_SKIP;
} else if (expression instanceof IASTTypeIdInitializerExpression) {
if (!((IASTTypeIdInitializerExpression) expression).getTypeId().accept(this)) {
return PROCESS_ABORT;
}
return PROCESS_SKIP;
}
return PROCESS_CONTINUE;
}
});
return result[0];
}
private static IBinding[] getBindingsFromScope(ICPPScope scope, final IIndexFileSet fileSet, LookupData data) throws DOMException {
IBinding[] bindings;
if (scope instanceof ICPPASTInternalScope) {
bindings= ((ICPPASTInternalScope) scope).getBindings(data.astName, true, data.prefixLookup, fileSet, data.checkPointOfDecl);

View file

@ -890,7 +890,11 @@ public class CPPVisitor extends ASTQueries {
}
public static IScope getContainingScope(IASTName name) {
IScope scope= getContainingScopeOrNull(name);
return getContainingScope(name, null);
}
public static IScope getContainingScope(IASTName name, LookupData data) {
IScope scope= getContainingScopeOrNull(name, data);
if (scope == null) {
return new CPPScope.CPPScopeProblem(name, IProblemBinding.SEMANTIC_BAD_SCOPE);
}
@ -898,7 +902,7 @@ public class CPPVisitor extends ASTQueries {
return scope;
}
private static IScope getContainingScopeOrNull(IASTName name) {
private static IScope getContainingScopeOrNull(IASTName name, LookupData data) {
if (name == null) {
return null;
}
@ -922,6 +926,9 @@ public class CPPVisitor extends ASTQueries {
}
}
if (i > 0) {
if (data != null) {
data.usesEnclosingScope= false;
}
IBinding binding = names[i - 1].resolveBinding();
while (binding instanceof ITypedef) {
IType t = ((ITypedef) binding).getType();
@ -954,6 +961,9 @@ public class CPPVisitor extends ASTQueries {
}
}
} else if (parent instanceof ICPPASTFieldReference) {
if (data != null) {
data.usesEnclosingScope= false;
}
final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference) parent;
IType type = CPPSemantics.getChainedMemberAccessOperatorReturnType(fieldReference);
if (fieldReference.isPointerDereference()) {

View file

@ -14,13 +14,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVQ;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.PTR_CVQ;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.addQualifiers;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
@ -43,6 +37,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
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.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
@ -805,6 +800,8 @@ public class Conversions {
*/
private static final boolean isCompleteType(IType type) {
type= getUltimateType(type, false);
if (type instanceof ICPPTemplateInstance)
return true;
if (type instanceof ICPPClassType) {
if (type instanceof IIndexFragmentBinding) {
try {

View file

@ -101,6 +101,7 @@ public class LookupData {
public boolean typesOnly = false;
public boolean considerConstructors = false;
public boolean checkPointOfDecl= true; // for lookup of unknown bindings the point of declaration can be reversed.
public boolean usesEnclosingScope= true; // for field references or qualified names, enclosing template declarations are ignored.
public ICPPClassType skippedScope;
public Object foundItems = null;