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

Name resolution when redeclaring a class after a reference, bug 229571.

This commit is contained in:
Markus Schorn 2008-05-23 13:47:01 +00:00
parent 781549e222
commit 291094d65d
5 changed files with 110 additions and 73 deletions

View file

@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
@ -800,4 +801,17 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
public void testEndlessLoopWithUsingDeclaration_Bug209813() throws DOMException {
getProblemFromASTName("x;", 1);
}
// class MyClass {};
// void test(MyClass* ptr);
// class MyClass;
public void testClassRedeclarationAfterReference_Bug229571() throws Exception {
IBinding cl= getBindingFromASTName("MyClass;", 7);
IFunction fn= getBindingFromASTName("test(", 4, IFunction.class);
IType type= fn.getType().getParameterTypes()[0];
assertInstance(type, IPointerType.class);
type= ((IPointerType) type).getType();
assertSame(type, cl);
}
}

View file

@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
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;
@ -44,6 +45,7 @@ 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.ICPPFunctionScope;
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;
@ -225,8 +227,15 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
definition = action.result;
if( definition == null ){
node.getTranslationUnit().accept( action );
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;
}

View file

@ -134,7 +134,7 @@ abstract public class CPPScope implements ICPPScope, IASTInternalScope {
public IBinding getBinding(IASTName name, boolean forceResolve, IIndexFileSet fileSet) throws DOMException {
IBinding binding= getBindingInAST(name, forceResolve);
if (binding == null) {
if (binding == null && forceResolve) {
final IASTTranslationUnit tu = name.getTranslationUnit();
IIndex index = tu.getIndex();
if (index != null) {

View file

@ -53,6 +53,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IFunction;
@ -128,8 +129,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitTypedef;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
@ -610,19 +609,26 @@ public class CPPSemantics {
return resultMap;
}
static protected void lookup(LookupData data, Object start) throws DOMException{
IASTNode node = data.astName;
IIndexFileSet fileSet= IIndexFileSet.EMPTY;
boolean isIndexBased= false;
private static IIndexFileSet getIndexFileSet(LookupData data) {
if (data.tu != null) {
final IIndexFileSet fs= data.tu.getIndexFileSet();
if (fs != null) {
fileSet= fs;
isIndexBased= true;
}
if (fs != null)
return fs;
}
return IIndexFileSet.EMPTY;
}
/**
* Perform a lookup with the given data starting in the given scope, considering bases and parent scopes.
* @param data the lookup data created off a name
* @param start either a scope or a name.
*/
static protected void lookup(LookupData data, Object start) throws DOMException{
final IIndexFileSet fileSet= getIndexFileSet(data);
final boolean isIndexBased= fileSet != IIndexFileSet.EMPTY;
IASTNode node = data.astName;
ICPPScope scope = null;
if (start instanceof ICPPScope)
scope = (ICPPScope) start;
@ -631,6 +637,9 @@ public class CPPSemantics {
else
return;
if (data.astName == null)
return;
boolean friendInLocalClass = false;
if (scope instanceof ICPPClassScope && data.forFriendship()) {
try {
@ -647,55 +656,35 @@ public class CPPSemantics {
IASTNode blockItem = CPPVisitor.getContainingBlockItem(node);
if (!data.usingDirectivesOnly) {
if (ASTInternal.isFullyCached(scope)) {
if (!data.contentAssist && data.astName != null) {
IBinding binding = scope.getBinding(data.astName, true, fileSet);
if (data.contentAssist) {
if (!ASTInternal.isFullyCached(scope)) {
lookupInScope(data, scope, blockItem);
}
// now scope is fully cached.
final IBinding[] bindings = scope.getBindings(data.astName, true, data.prefixLookup, fileSet);
mergeResults(data, bindings, true);
}
else {
boolean done= false;
if (!ASTInternal.isFullyCached(scope)) {
final IASTName[] names= lookupInScope(data, scope, blockItem);
if (names != null) {
mergeResults(data, names, true);
done= true;
}
}
if (!done) {
// now scope is fully cached.
final IBinding binding = scope.getBinding(data.astName, true, fileSet);
if (binding != null &&
(CPPSemantics.declaredBefore(binding, data.astName, isIndexBased) ||
(scope instanceof ICPPClassScope && data.checkWholeClassScope)))
{
(CPPSemantics.declaredBefore(binding, data.astName, isIndexBased) ||
(scope instanceof ICPPClassScope && data.checkWholeClassScope))) {
mergeResults(data, binding, true);
}
} else if (data.astName != null) {
IBinding[] bindings = scope.getBindings(data.astName, true, data.prefixLookup, fileSet);
mergeResults(data, bindings, true);
}
} else if (data.astName != null) {
IBinding[] b = null;
if (!data.contentAssist) {
IBinding binding = scope.getBinding(data.astName, false, fileSet);
if (binding instanceof CPPImplicitFunction || binding instanceof CPPImplicitTypedef)
mergeResults(data, binding, true);
else if (binding != null)
b = new IBinding[] { binding };
} else {
b = scope.getBindings(data.astName, false, data.prefixLookup, fileSet);
}
IASTName[] inScope = lookupInScope(data, scope, blockItem);
if (inScope != null) {
if (data.contentAssist) {
Object[] objs = ArrayUtil.addAll(Object.class, null, inScope);
if (b != null) {
for (IBinding element : b) {
if (isFromIndex(element))
objs = ArrayUtil.append(Object.class, objs, element);
}
}
mergeResults(data, objs, true);
} else {
mergeResults(data, inScope, true);
}
} else if (!data.contentAssist) {
if (b != null && isFromIndex(b[0])) {
mergeResults(data, b, true);
}
} else if (b != null) {
mergeResults(data, b, true);
}
}
// store using-directives found in this block or namespace for later use.
if ((!data.hasResults() || !data.qualified() || data.contentAssist) && scope instanceof ICPPNamespaceScope) {
final ICPPNamespaceScope blockScope= (ICPPNamespaceScope) scope;
@ -1514,10 +1503,24 @@ public class CPPSemantics {
if (bindings == null || bindings.length == 0) {
return null;
} else if (bindings.length == 1) {
if (bindings[0] instanceof IBinding)
return (IBinding) bindings[0];
else if (bindings[0] instanceof IASTName && ((IASTName) bindings[0]).getBinding() != null)
return ((IASTName) bindings[0]).getBinding();
// if (bindings[0] instanceof IBinding)
// return (IBinding) bindings[0];
// else if (bindings[0] instanceof IASTName && ((IASTName) bindings[0]).getBinding() != null)
// return ((IASTName) bindings[0]).getBinding();
IBinding candidate= null;
if (bindings[0] instanceof IBinding) {
candidate= (IBinding) bindings[0];
} else if (bindings[0] instanceof IASTName) {
candidate= ((IASTName) bindings[0]).getBinding();
}
if (candidate != null) {
if (candidate instanceof IType == false && candidate instanceof ICPPNamespace == false
&& LookupData.typesOnly(name)) {
return null;
}
return candidate;
}
}
if (name.getPropertyInParent() != STRING_LOOKUP_PROPERTY) {
@ -1558,15 +1561,23 @@ public class CPPSemantics {
// are likely to be redeclared we need to assume that there is a declaration
// in one of the headers.
if (indexBased) {
if (cpp instanceof ICPPNamespace || cpp instanceof ICPPFunction || cpp instanceof ICPPVariable) {
try {
try {
if (cpp instanceof ICPPNamespace || cpp instanceof ICPPFunction || cpp instanceof ICPPVariable) {
IScope scope= cpp.getScope();
if (!(scope instanceof ICPPBlockScope) && scope instanceof ICPPNamespaceScope) {
if (scope instanceof ICPPBlockScope == false && scope instanceof ICPPNamespaceScope) {
return true;
}
} catch (DOMException e) {
}
}
} else if (cpp instanceof ICompositeType || cpp instanceof IEnumeration) {
IScope scope= cpp.getScope();
if (scope instanceof ICPPBlockScope == false && scope instanceof ICPPNamespaceScope) {
// if this is not the definition, it may be found in a header. (bug 229571)
if (cpp.getDefinition() == null) {
return true;
}
}
}
} catch (DOMException e) {
}
}
IASTNode[] n = cpp.getDeclarations();
if (n != null && n.length > 0) {
@ -1765,6 +1776,9 @@ public class CPPSemantics {
return resolveFunction(data, fns.keyArray(IFunction.class));
}
if (data.typesOnly && obj instanceof ICPPNamespace == false) {
return null;
}
return obj;
}

View file

@ -105,7 +105,7 @@ class LookupData {
public LookupData(IASTName n) {
astName = n;
tu= (CPPASTTranslationUnit) astName.getTranslationUnit();
typesOnly = typesOnly();
typesOnly = typesOnly(astName);
considerConstructors = considerConstructors();
checkWholeClassScope = checkWholeClassScope();
}
@ -131,16 +131,16 @@ class LookupData {
return false;
}
private boolean typesOnly() {
if (astName == null) return false;
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
IASTNode parent = astName.getParent();
static boolean typesOnly(IASTName name) {
if (name == null) return false;
if (name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
IASTNode parent = name.getParent();
if (parent instanceof ICPPASTBaseSpecifier || parent instanceof ICPPASTElaboratedTypeSpecifier ||
parent instanceof ICPPASTCompositeTypeSpecifier)
return true;
if (parent instanceof ICPPASTQualifiedName) {
IASTName[] ns = ((ICPPASTQualifiedName)parent).getNames();
return (astName != ns[ns.length -1]);
return (name != ns[ns.length -1]);
}
return false;
}