From 291094d65d60d1e90b0cff6c5155db1386f21cd3 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 23 May 2008 13:47:01 +0000 Subject: [PATCH] Name resolution when redeclaring a class after a reference, bug 229571. --- .../tests/IndexCPPBindingResolutionBugs.java | 14 ++ .../core/dom/parser/cpp/CPPClassType.java | 11 +- .../core/dom/parser/cpp/CPPScope.java | 2 +- .../parser/cpp/semantics/CPPSemantics.java | 144 ++++++++++-------- .../dom/parser/cpp/semantics/LookupData.java | 12 +- 5 files changed, 110 insertions(+), 73 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java index 46008e3c122..6b12944bd8b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java @@ -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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index 16ac214a01c..9faf207e688 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java index 62f25c17d03..4029991dd8b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 7f08231ce5a..63a1247df8c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 32a9786828e..0a6c241fefb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -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; }