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:
parent
781549e222
commit
291094d65d
5 changed files with 110 additions and 73 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue