diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index cda250c6009..06c24742e42 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 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 @@ -7985,5 +7985,30 @@ public class AST2CPPTests extends AST2BaseTest { String code= getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); } + + // namespace ns { + // struct A{}; + // void f(ns::A, char) {} + // } + // void f(ns::A, int) {} + // + // ns::A a; + // void test() { + // f(a, '1'); // calls ns::f(ns::A, char) + // f(a, 1); // calls ns::f(ns::A, char) + // } + public void testADL_299101() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IFunction inns= bh.assertNonProblem("f(ns::A, char)", 1); + IFunction glob= bh.assertNonProblem("f(ns::A, int)", 1); + + IBinding b= bh.assertNonProblem("f(a, '1')", 1); + assertSame(b, inns); + + b= bh.assertNonProblem("f(a, 1)", 1); + assertSame(b, glob); + } } 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 df280a77b4b..4ff3ba461ba 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 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 @@ -53,9 +53,12 @@ import org.eclipse.core.runtime.NullProgressMonitor; abstract public class CPPScope implements ICPPASTInternalScope { protected static final char[] CONSTRUCTOR_KEY = "!!!CTOR!!!".toCharArray(); //$NON-NLS-1$ private static final IProgressMonitor NPM = new NullProgressMonitor(); + private static final ICPPNamespace UNINITIALIZED = new CPPNamespace.CPPNamespaceProblem(null, 0, null); + private IASTNode physicalNode; private boolean isCached = false; protected CharArrayObjectMap bindings = null; + private ICPPNamespace fIndexNamespace= UNINITIALIZED; public static class CPPScopeProblem extends ProblemBinding implements ICPPScope { public CPPScopeProblem(IASTNode node, int id, char[] arg) { @@ -162,14 +165,9 @@ abstract public class CPPScope implements ICPPASTInternalScope { CCorePlugin.log(e); } } else if (physicalNode instanceof ICPPASTNamespaceDefinition) { - ICPPASTNamespaceDefinition nsdef = (ICPPASTNamespaceDefinition)physicalNode; - IASTName nsname = nsdef.getName(); - IBinding nsbinding= nsname.resolveBinding(); - if (nsbinding instanceof ICPPNamespace) { - ICPPNamespace nsbindingAdapted = (ICPPNamespace) index.adaptBinding(nsbinding); - if (nsbindingAdapted!=null) { - return nsbindingAdapted.getNamespaceScope().getBinding(name, forceResolve, fileSet); - } + ICPPNamespace nsbinding= getNamespaceIndexBinding((ICPPASTNamespaceDefinition)physicalNode, index); + if (nsbinding != null) { + return nsbinding.getNamespaceScope().getBinding(name, forceResolve, fileSet); } } } @@ -177,6 +175,18 @@ abstract public class CPPScope implements ICPPASTInternalScope { return binding; } + private ICPPNamespace getNamespaceIndexBinding(ICPPASTNamespaceDefinition nsdef, IIndex index) { + if (fIndexNamespace == UNINITIALIZED) { + fIndexNamespace= null; + IASTName nsname = nsdef.getName(); + IBinding nsbinding= nsname.resolveBinding(); + if (nsbinding != null) { + fIndexNamespace= (ICPPNamespace) index.adaptBinding(nsbinding); + } + } + return fIndexNamespace; + } + public IBinding getBindingInAST(IASTName name, boolean forceResolve) throws DOMException { IBinding[] bs= getBindingsInAST(name, forceResolve, false, false, true); return CPPSemantics.resolveAmbiguities(name, bs); 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 1338fdd8b56..9bc8c88a757 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 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 @@ -230,14 +230,19 @@ public class CPPSemantics { try { // 2: lookup - lookup(data, name); + lookup(data, null); + + // Perform argument dependent lookup + if (data.checkAssociatedScopes() && !data.hasTypeOrMemberFunctionResult()) { + doKoenigLookup(data); + } } catch (DOMException e) { data.problem = (ProblemBinding) e.getProblem(); } - if (data.problem != null) return data.problem; - + + // 3: resolve ambiguities IBinding binding; try { @@ -263,29 +268,6 @@ public class CPPSemantics { } private static IBinding postResolution(IBinding binding, LookupData data) { - // If the normal lookup of the unqualified name finds a class member function, then ADL does not occur - if (data.checkAssociatedScopes() && !data.hasMemberFunctionResult()) { - // 3.4.2 argument dependent name lookup, aka Koenig lookup - try { - boolean doKoenig= true; - if (binding != null) { - if (binding.getOwner() instanceof ICPPClassType) - doKoenig= false; - else if (binding instanceof ICPPClassType && data.considerConstructors) - doKoenig= false; - } - if (doKoenig) { - int count= data.getFoundItemCount(); - doKoenigLookup(data); - if (data.getFoundItemCount() > count) { - binding = resolveAmbiguities(data, data.astName); - } - } - } catch (DOMException e) { - binding = e.getProblem(); - } - } - if (binding instanceof IProblemBinding) return binding; @@ -508,9 +490,9 @@ public class CPPSemantics { private static void doKoenigLookup(LookupData data) throws DOMException { data.ignoreUsingDirectives = true; data.forceQualified = true; - ObjectSet associated = getAssociatedScopes(data); + ObjectSet associated = getAssociatedScopes(data); for (int i = 0; i < associated.size(); i++) { - final IScope scope = associated.keyAt(i); + final ICPPScope scope = associated.keyAt(i); if (!data.visited.containsKey(scope)) { lookup(data, scope); } @@ -602,12 +584,12 @@ public class CPPSemantics { return data; } - static private ObjectSet getAssociatedScopes(LookupData data) { + static private ObjectSet getAssociatedScopes(LookupData data) { if (!data.hasArgumentTypes()) return ObjectSet.emptySet(); IType[] ps = data.getFunctionArgumentTypes(); - ObjectSet namespaces = new ObjectSet(2); + ObjectSet namespaces = new ObjectSet(2); ObjectSet classes = new ObjectSet(2); for (IType p : ps) { p = getUltimateType(p, true); @@ -619,14 +601,14 @@ public class CPPSemantics { return namespaces; } - static private void getAssociatedScopes(IType t, ObjectSet namespaces, + static private void getAssociatedScopes(IType t, ObjectSet namespaces, ObjectSet classes, CPPASTTranslationUnit tu) throws DOMException { // 3.4.2-2 if (t instanceof ICPPClassType) { ICPPClassType ct= (ICPPClassType) t; if (!classes.containsKey(ct)) { classes.put(ct); - IScope scope = getContainingNamespaceScope((IBinding) t, tu); + ICPPScope scope = getContainingNamespaceScope((IBinding) t, tu); if (scope != null) namespaces.put(scope); @@ -641,7 +623,7 @@ public class CPPSemantics { } } } else if (t instanceof IEnumeration) { - IScope scope = getContainingNamespaceScope((IBinding) t, tu); + ICPPScope scope = getContainingNamespaceScope((IBinding) t, tu); if (scope!=null) namespaces.put(scope); } else if (t instanceof IFunctionType) { @@ -780,16 +762,30 @@ public class CPPSemantics { * @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 { + static protected void lookup(LookupData data, IScope start) throws DOMException { final IIndexFileSet fileSet= getIndexFileSet(data); if (data.astName == null) return; ICPPScope nextScope= null; + ICPPTemplateScope nextTmplScope= null; if (start instanceof ICPPScope) { nextScope= (ICPPScope) start; - } else if (start instanceof IASTName) { - nextScope= getLookupScope((IASTName) start, data); + } else { + nextScope= getLookupScope(data.astName, data); + + if (nextScope instanceof ICPPTemplateScope) { + nextTmplScope= (ICPPTemplateScope) nextScope; + nextScope= getParentScope(nextScope, data.tu); + } else { + nextTmplScope= enclosingTemplateScope(data.astName); + } + if (!data.usesEnclosingScope && nextTmplScope != null) { + nextTmplScope= null; + if (dependsOnTemplateFieldReference(data.astName)) { + data.checkPointOfDecl= false; + } + } } if (nextScope == null) return; @@ -803,20 +799,6 @@ public class CPPSemantics { } } - ICPPTemplateScope nextTmplScope; - if (nextScope instanceof ICPPTemplateScope) { - nextTmplScope= (ICPPTemplateScope) nextScope; - nextScope= getParentScope(nextScope, data.tu); - } 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, // we use the template scope for the next iteration. @@ -884,7 +866,7 @@ public class CPPSemantics { // if still not found, loop and check our containing scope if (data.qualified() && !(scope instanceof ICPPTemplateScope)) { - if (data.usingDirectives.isEmpty()) + if (data.ignoreUsingDirectives || data.usingDirectives.isEmpty()) break; data.usingDirectivesOnly = true; } @@ -2470,7 +2452,7 @@ public class CPPSemantics { IASTName name = idExp.getName(); LookupData data = createLookupData(name, false); try { - lookup(data, name); + lookup(data, null); } catch (DOMException e) { return null; } @@ -2957,10 +2939,10 @@ public class CPPSemantics { data.prefixLookup = prefixLookup; data.foundItems = new CharArrayObjectMap(2); - return contentAssistLookup(data, name); + return contentAssistLookup(data, null); } - private static IBinding[] contentAssistLookup(LookupData data, Object start) { + private static IBinding[] contentAssistLookup(LookupData data, IScope start) { try { lookup(data, start); } catch (DOMException e) { @@ -2999,7 +2981,7 @@ public class CPPSemantics { return ArrayUtil.trim(result); } - private static IBinding[] standardLookup(LookupData data, Object start) { + private static IBinding[] standardLookup(LookupData data, IScope start) { try { lookup(data, start); } catch (DOMException e) { 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 1311cbb2f77..d992d1944a2 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 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 @@ -374,12 +374,12 @@ public class LookupData { return false; } - public boolean hasMemberFunctionResult() { + public boolean hasTypeOrMemberFunctionResult() { if(foundItems == null) return false; if(foundItems instanceof Object[]) { for(Object item : (Object[])foundItems) { - if(item instanceof ICPPMethod) { + if(item instanceof ICPPMethod || item instanceof IType) { return true; } }