diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java index db6cbddda0b..82c6b0cdc4a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java @@ -4603,7 +4603,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { // ip = a.operator int*(); // explicit call to template operator // // A::operator int*() // } - public void _test14_5_2s5() throws Exception { + public void test14_5_2s5() throws Exception { parse(getAboveComment(), ParserLanguage.CPP, true, 0); } 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 4451c6238a3..252a7b82bf2 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 @@ -6984,4 +6984,24 @@ public class AST2CPPTests extends AST2BaseTest { parseAndCheckBindings(code, ParserLanguage.CPP); } + + // namespace ns { + // struct S { + // int a; + // }; + // } + // class A { + // public: + // operator ns::S*(){return 0;}; + // }; + // namespace ns { + // void bla() { + // A a; + // a.operator S *(); + // } + // } + public void testLookupScopeForConversionNames_267221() throws Exception { + final String code = getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } 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 10a0021dea4..c27896f7c1d 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 @@ -1116,4 +1116,24 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas buf.append('}'); return buf.toString(); } + + // namespace ns { + // struct S { + // int a; + // }; + // } + // class A { + // public: + // template operator T*(){return 0;}; + // }; + + // namespace ns { + // void bla() { + // A a; + // a.operator S *(); + // } + // } + public void testLookupScopeForConversionNames_267221() throws Exception { + getBindingFromASTName("operator S *", 12, ICPPMethod.class); + } } 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 69b8a392789..ef43c5f6687 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 @@ -2007,12 +2007,12 @@ public class CPPSemantics { return resolveTargetedFunction(data, fns); } - if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { - CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName); + if (data.astName instanceof ICPPASTConversionName) { + return resolveUserDefinedConversion(data, fns); } - if (data.astName instanceof ICPPASTConversionName) { - return resolveUserDefinedConversion((ICPPASTConversionName) data.astName, fns); + if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { + CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName); } // Reduce our set of candidate functions to only those who have the right number of parameters @@ -2240,11 +2240,16 @@ public class CPPSemantics { return implicitType; } - private static IBinding resolveUserDefinedConversion(ICPPASTConversionName astName, IFunction[] fns) { + private static IBinding resolveUserDefinedConversion(LookupData data, IFunction[] fns) { + ICPPASTConversionName astName= (ICPPASTConversionName) data.astName; IType t= CPPVisitor.createType(astName.getTypeId()); if (t == null) { return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE); } + if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { + CPPTemplates.instantiateConversionTemplates(fns, t, data.astName); + } + IFunction unknown= null; for (IFunction function : fns) { if (function != null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index bfe4f2b4dfd..590bbd55e12 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -621,6 +621,7 @@ public class CPPTemplates { /** * Deduce arguments for a template function from the template id + the template function parameters. + * 14.8.2.1 */ static private ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate template, ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, CPPTemplateParameterMap map) throws DOMException { @@ -657,6 +658,31 @@ public class CPPTemplates { return result; } + /** + * Deduce arguments for a user defined conversion template + * 14.8.2.3 + */ + static private ICPPTemplateArgument[] deduceTemplateConversionArguments(ICPPFunctionTemplate template, + IType conversionType, CPPTemplateParameterMap map) throws DOMException { + final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters(); + final int length = tmplParams.length; + + ICPPTemplateArgument[] result = new ICPPTemplateArgument[length]; + if (!deduceTemplateParameterMap(template.getType().getReturnType(), conversionType, map)) { + return null; + } + + for (int i = 0; i < length; i++) { + if (result[i] == null) { + ICPPTemplateArgument deducedArg= map.getArgument(tmplParams[i]); + if (deducedArg == null) + return null; + result[i]= deducedArg; + } + } + return result; + } + public static ICPPTemplateInstance createInstance(IBinding owner, ICPPTemplateDefinition template, CPPTemplateParameterMap tpMap, ICPPTemplateArgument[] args) { if (owner instanceof ICPPSpecialization) { @@ -1354,6 +1380,42 @@ public class CPPTemplates { } } + static protected void instantiateConversionTemplates(IFunction[] functions, IType conversionType, IASTName name) { + boolean checkedForDependentType= false; + for (int i = 0; i < functions.length; i++) { + IFunction func = functions[i]; + if (func instanceof ICPPFunctionTemplate) { + ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; + functions[i]= null; + + // extract template arguments and parameter types. + if (!checkedForDependentType) { + try { + if (isDependentType(conversionType)) { + functions[i]= CPPUnknownFunction.createForSample(template, name); + return; + } + checkedForDependentType= true; + } catch (DOMException e) { + return; + } + } + CPPTemplateParameterMap map= new CPPTemplateParameterMap(1); + try { + ICPPTemplateArgument[] args= deduceTemplateConversionArguments(template, conversionType, map); + if (args != null) { + IBinding instance= instantiateFunctionTemplate(template, args); + if (instance instanceof IFunction) { + functions[i]= (IFunction) instance; + } + } + } catch (DOMException e) { + // try next candidate + } + } + } + } + /** * Deduces the mapping for the template parameters from the function parameters, * returns false if there is no mapping. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 981ffcd3bdc..b50235cda27 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -786,8 +786,9 @@ public class CPPVisitor extends ASTQueries { } else if (node instanceof IASTStatement) { return getContainingScope((IASTStatement) node); } else if (node instanceof IASTTypeId) { - if (node.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) { - node= node.getParent(); // template-id + ASTNodeProperty prop = node.getPropertyInParent(); + if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT || prop == ICPPASTConversionName.TYPE_ID) { + node= node.getParent(); // template-id or conversion name while (node instanceof IASTName) { node= node.getParent(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java index c108010c40c..e291c0ec329 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 QNX Software Systems and others. + * Copyright (c) 2005, 2009 QNX Software Systems 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 @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.IPDOMNode; import org.eclipse.cdt.core.dom.IPDOMVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; @@ -27,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -37,10 +39,13 @@ import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; +import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.util.CharArrayMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; +import org.eclipse.cdt.internal.core.index.DeclaredBindingsFilter; import org.eclipse.cdt.internal.core.index.IIndexScope; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.dom.BindingCollector; @@ -51,6 +56,15 @@ import org.eclipse.core.runtime.CoreException; * Represents the class scope for a class stored in the index. */ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { + private static final IndexFilter CONVERSION_FILTER = new DeclaredBindingsFilter(ILinkage.CPP_LINKAGE_ID, true, false) { + @Override + public boolean acceptBinding(IBinding binding) throws CoreException { + return binding instanceof ICPPMethod && + SemanticUtil.isConversionOperator(((ICPPMethod) binding)) && + super.acceptBinding(binding); + } + }; + private IPDOMCPPClassType fBinding; public PDOMCPPClassScope(IPDOMCPPClassType binding) { @@ -101,8 +115,13 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { } public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) throws DOMException { - IBinding[] result = null; try { + if (name instanceof ICPPASTConversionName) { + BindingCollector visitor = new BindingCollector(fBinding.getLinkage(), Keywords.cOPERATOR, CONVERSION_FILTER, true, true); + acceptViaCache(fBinding, visitor, true); + return visitor.getBindings(); + } + final char[] nameChars = name.getSimpleID(); if (!prefixLookup) { if (CharArrayUtils.equals(fBinding.getNameCharArray(), nameChars)) { @@ -121,11 +140,11 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { visitor.visit((IPDOMNode) getClassNameBinding()); } acceptViaCache(fBinding, visitor, true); - result= visitor.getBindings(); + return visitor.getBindings(); } catch (CoreException e) { CCorePlugin.log(e); } - return result; + return null; } public static IBinding[] getBindingsViaCache(IPDOMCPPClassType ct, final char[] name, IndexFilter filter) throws CoreException {