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 0c2f2caeb45..e027262e19e 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 @@ -6719,4 +6719,20 @@ public class AST2CPPTests extends AST2BaseTest { String code= getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); } + + // template class range { + // public: + // template range(const Range& r) {} + // }; + // void onRange(const range& r) {} + // void test() { + // range ir(0); + // onRange(ir); + // } + public void testConstructorTemplateInImplicitConversion_264314() throws Exception { + final String code = getAboveComment(); + BindingAssertionHelper ba= new BindingAssertionHelper(code, true); + ba.assertNonProblem("onRange(ir)", 7); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java index 7ccb1b78135..c573c58e418 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java @@ -162,8 +162,8 @@ public class CPPASTUnaryExpression extends ASTNode implements } catch (DOMException e) { return e.getProblem(); } - return new CPPPointerToMemberType(type, (ICPPClassType) nestedType, - thisType.isConst(), thisType.isVolatile()); + return new CPPPointerToMemberType(type, nestedType, thisType.isConst(), thisType + .isVolatile()); } } return new CPPPointerType(type); 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 87f621cb66a..a9f105a2c34 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 @@ -1651,13 +1651,10 @@ public class CPPSemantics { final boolean indexBased= data.tu != null && data.tu.getIndex() != null; @SuppressWarnings("unchecked") ObjectSet fns= ObjectSet.EMPTY_SET; - @SuppressWarnings("unchecked") - ObjectSet templateFns= ObjectSet.EMPTY_SET; IBinding type = null; IBinding obj = null; IBinding temp = null; boolean fnsFromAST= false; - boolean fnTmplsFromAST= false; Object[] items = (Object[]) data.foundItems; for (int i = 0; i < items.length && items[i] != null; i++) { @@ -1713,36 +1710,19 @@ public class CPPSemantics { } IFunction function= (IFunction) temp; - if (function instanceof ICPPFunctionTemplate) { - if (templateFns == ObjectSet.EMPTY_SET) - templateFns = new ObjectSet(2); - if (isFromIndex(function)) { - // accept bindings from index only, in case we have none in the AST - if (!fnTmplsFromAST) { - templateFns.put(function); - } - } else { - if (!fnTmplsFromAST) { - templateFns.clear(); - fnTmplsFromAST= true; - } - templateFns.put(function); - } - } else { - if (fns == ObjectSet.EMPTY_SET) - fns = new ObjectSet(2); - if (isFromIndex(function)) { - // accept bindings from index only, in case we have none in the AST - if (!fnsFromAST) { - fns.put(function); - } - } else { - if (!fnsFromAST) { - fns.clear(); - fnsFromAST= true; - } + if (fns == ObjectSet.EMPTY_SET) + fns = new ObjectSet(2); + if (isFromIndex(function)) { + // accept bindings from index only, in case we have none in the AST + if (!fnsFromAST) { fns.put(function); } + } else { + if (!fnsFromAST) { + fns.clear(); + fnsFromAST= true; + } + fns.put(function); } } else if (temp instanceof IType) { // specializations are selected during instantiation @@ -1804,46 +1784,31 @@ public class CPPSemantics { // if (fns == null) return type; bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, type); bindings = (IBinding[]) ArrayUtil.addAll(IBinding.class, bindings, fns.keyArray()); - bindings = (IBinding[]) ArrayUtil.addAll(IBinding.class, bindings, templateFns.keyArray()); } bindings = (IBinding[]) ArrayUtil.trim(IBinding.class, bindings); ICPPUsingDeclaration composite = new CPPUsingDeclaration(data.astName, bindings); return composite; } - int numTemplateFns = templateFns.size(); - if (numTemplateFns > 0) { - if (data.functionParameters != null && - (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization())) { - IFunction[] fs = CPPTemplates.selectTemplateFunctions(templateFns, data.functionParameters, data.astName); - if (fs != null && fs.length > 0) { - if (fns == ObjectSet.EMPTY_SET) - fns = new ObjectSet(fs.length); - fns.addAll(fs); - } - } else { - if (fns == ObjectSet.EMPTY_SET) - fns = templateFns; - else - fns.addAll(templateFns); - } - } - int numFns = fns.size(); - if (type != null) { - if (data.typesOnly || (obj == null && numFns == 0)) + if (data.typesOnly) { + if (type != null) return type; + if (obj instanceof ICPPNamespace) + return obj; + return null; } - + + int numFns = fns.size(); if (numFns > 0) { if (obj != null) return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); - return resolveFunction(data, fns.keyArray(IFunction.class)); + return resolveFunction(data, fns.keyArray(IFunction.class), true); } - if (data.typesOnly && obj instanceof ICPPNamespace == false) { - return null; + if (obj != null) { + return obj; } - return obj; + return type; } private static boolean isFromIndex(IBinding binding) { @@ -1878,12 +1843,14 @@ public class CPPSemantics { // Trim the list down to the set of viable functions IFunction function = null; int size = functions.length; - for (int i = 0; i < size && functions[i] != null; i++) { + for (int i = 0; i < size; i++) { function = (IFunction) functions[i]; + if (function == null) + continue; if (function instanceof IProblemBinding) { functions[i]= null; continue; - } + } if (function instanceof ICPPUnknownBinding) { if (def) { functions[i]= null; @@ -1978,7 +1945,7 @@ public class CPPSemantics { return result; } - static IBinding resolveFunction(LookupData data, IFunction[] fns) throws DOMException { + static IBinding resolveFunction(LookupData data, IFunction[] fns, boolean allowUDC) throws DOMException { fns= (IFunction[]) ArrayUtil.trim(IFunction.class, fns); if (fns == null || fns.length == 0) return null; @@ -1987,14 +1954,19 @@ public class CPPSemantics { return new CPPUsingDeclaration(data.astName, fns); } - if (data.astName instanceof ICPPASTConversionName) { - return resolveUserDefinedConversion((ICPPASTConversionName) data.astName, fns); - } - // We don't have any arguments with which to resolve the function if (data.functionParameters == null) { return resolveTargetedFunction(data, fns); } + + if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { + CPPTemplates.instantiateFunctionTemplates(fns, data.functionParameters, data.astName); + } + + if (data.astName instanceof ICPPASTConversionName) { + return resolveUserDefinedConversion((ICPPASTConversionName) data.astName, fns); + } + // Reduce our set of candidate functions to only those who have the right number of parameters reduceToViable(data, fns); @@ -2060,7 +2032,6 @@ public class CPPSemantics { currFnCost= new Cost[sourceLen]; } - comparison = 0; boolean varArgs = false; boolean isImpliedObject= false; for (int j = 0; j < sourceLen; j++) { @@ -2097,8 +2068,8 @@ public class CPPSemantics { cost = new Cost(source, target); cost.rank = Cost.IDENTITY_RANK; // exact match, no cost } else { - cost= Conversions.checkImplicitConversionSequence(!data.forUserDefinedConversion, - sourceExp, source, target, isImpliedObject); + cost= Conversions.checkImplicitConversionSequence(sourceExp, + source, target, allowUDC, isImpliedObject); } if (cost.rank < 0) 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 ff38d362010..95de08cb786 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 @@ -85,7 +85,6 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArraySet; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectMap; -import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; @@ -1332,50 +1331,50 @@ public class CPPTemplates { return result; } - static protected IFunction[] selectTemplateFunctions(ObjectSet templates, + static protected void instantiateFunctionTemplates(IFunction[] functions, Object[] functionArguments, IASTName name) { - - if (templates == null || templates.size() == 0) - return null; - - ICPPTemplateArgument[] templateArguments = ICPPTemplateArgument.EMPTY_ARGUMENTS; - final IType[] fnArgs= createTypeArray(functionArguments); - try { - if (containsDependentType(fnArgs)) - return new IFunction[] {CPPUnknownFunction.createForSample(templates.keyAt(0), name)}; - - if (name instanceof ICPPASTTemplateId) { - templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name); - if (hasDependentArgument(templateArguments)) - return new IFunction[] {CPPUnknownFunction.createForSample(templates.keyAt(0), name)}; - } - } catch (DOMException e) { - return new IFunction[0]; - } - - IFunction[] instances= null; - final int size = templates.size(); - for (int idx = 0; idx < size; idx++) { - ICPPFunctionTemplate template = (ICPPFunctionTemplate) templates.keyAt(idx); - CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length); - try { - ICPPTemplateArgument[] useArgs = templateArguments; - if (template instanceof ICPPConstructor) - useArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS; + ICPPTemplateArgument[] templateArguments= null; + IType[] fnArgs= null; + for (int i = 0; i < functions.length; i++) { + IFunction func = functions[i]; + if (func instanceof ICPPFunctionTemplate) { + ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; + functions[i]= null; - ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, useArgs, fnArgs, map); - if (args != null) { - IBinding temp= instantiateFunctionTemplate(template, args); - if (temp instanceof IFunction) { - instances = (IFunction[]) ArrayUtil.append(IFunction.class, instances, temp); + // extract template arguments and parameter types. + if (templateArguments == null || fnArgs == null) { + templateArguments = ICPPTemplateArgument.EMPTY_ARGUMENTS; + fnArgs= createTypeArray(functionArguments); + try { + if (containsDependentType(fnArgs)) { + functions[i]= CPPUnknownFunction.createForSample(template, name); + return; + } + if (name instanceof ICPPASTTemplateId && !(template instanceof ICPPConstructor)) { + templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name); + if (hasDependentArgument(templateArguments)) { + functions[i]= CPPUnknownFunction.createForSample(template, name); + return; + } + } + } catch (DOMException e) { + return; } } - } catch (DOMException e) { - // try next candidate - } + CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length); + try { + ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, templateArguments, fnArgs, map); + if (args != null) { + IBinding instance= instantiateFunctionTemplate(template, args); + if (instance instanceof IFunction) { + functions[i]= (IFunction) instance; + } + } + } catch (DOMException e) { + // try next candidate + } + } } - - return (IFunction[]) ArrayUtil.trim(IFunction.class, instances); } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 58f3d9db2c6..85734bb0c30 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -52,17 +52,17 @@ public class Conversions { /** * Computes the cost of an implicit conversion sequence * [over.best.ics] 13.3.3.1 - * - * @param allowUDC whether a user-defined conversion is allowed during the sequence * @param sourceExp the expression behind the source type * @param source the source (argument) type * @param target the target (parameter) type + * @param allowUDC whether a user-defined conversion is allowed during the sequence * @param isImpliedObject + * * @return the cost of converting from source to target * @throws DOMException */ - public static Cost checkImplicitConversionSequence(boolean allowUDC, IASTExpression sourceExp, - IType source, IType target, boolean isImpliedObject) throws DOMException { + public static Cost checkImplicitConversionSequence(IASTExpression sourceExp, IType source, + IType target, boolean allowUDC, boolean isImpliedObject) throws DOMException { allowUDC &= !isImpliedObject; target= getNestedType(target, TYPEDEFS); source= getNestedType(source, TYPEDEFS); @@ -166,26 +166,20 @@ public class Conversions { // We must do a non-reference initialization if (!illformed) { - Cost cost= checkStandardConversionSequence(source, cv1T1, isImpliedObject); - // 12.3-4 At most one user-defined conversion is implicitly applied to - // a single value. (also prevents infinite loop) - if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK || - cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) { - Cost temp = checkUserDefinedConversionSequence(source, cv1T1); - if (temp != null) { - cost = temp; - } - } - return cost; + return nonReferenceConversion(source, cv1T1, allowUDC, isImpliedObject); } } return new Cost(source, cv1T1); } // Non-reference binding + return nonReferenceConversion(source, target, allowUDC, isImpliedObject); + } + + private static Cost nonReferenceConversion(IType source, IType target, boolean allowUDC, + boolean isImpliedObject) throws DOMException { Cost cost= checkStandardConversionSequence(source, target, isImpliedObject); - if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK || - cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) { + if (allowUDC && cost.rank == Cost.NO_MATCH_RANK) { Cost temp = checkUserDefinedConversionSequence(source, target); if (temp != null) { cost = temp; @@ -349,19 +343,23 @@ public class Conversions { //constructors if (t instanceof ICPPClassType) { - ICPPConstructor [] constructors= ((ICPPClassType) t).getConstructors(); - if (constructors.length > 0 && !(constructors[0] instanceof IProblemBinding)) { + ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors(); + // select converting constructors + int j= 0; + ICPPConstructor[] convertingCtors= new ICPPConstructor[ctors.length]; + for (int i = 0; i < ctors.length; i++) { + ICPPConstructor ctor= ctors[i]; + if (!(ctor instanceof IProblemBinding) && !ctor.isExplicit()) + convertingCtors[j++]= ctor; + } + if (j > 0) { LookupData data= new LookupData(); - data.forUserDefinedConversion= true; data.functionParameters= new IType [] { source }; - IBinding binding = CPPSemantics.resolveFunction(data, constructors); - if (binding instanceof ICPPConstructor) { - ICPPConstructor constructor= (ICPPConstructor) binding; - if (!constructor.isExplicit()) { - constructorCost = checkStandardConversionSequence(t, target, false); - if (constructorCost.rank == Cost.NO_MATCH_RANK) { - constructorCost= null; - } + IBinding binding = CPPSemantics.resolveFunction(data, convertingCtors, false); + if (binding instanceof ICPPConstructor && !(binding instanceof IProblemBinding)) { + constructorCost = checkStandardConversionSequence(t, target, false); + if (constructorCost.rank == Cost.NO_MATCH_RANK) { + constructorCost= null; } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java index ba962f1d6e1..971c1a59ea6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java @@ -37,7 +37,6 @@ class Cost { public static final int DERIVED_TO_BASE_CONVERSION = 3; public static final int USERDEFINED_CONVERSION_RANK = 4; public static final int ELLIPSIS_CONVERSION = 5; - public static final int FUZZY_TEMPLATE_PARAMETERS = 6; public IType source; public IType target; 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 11eb0dd6596..0d5d3f779e3 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 @@ -93,7 +93,6 @@ public class LookupData { public boolean ignoreUsingDirectives = false; public boolean usingDirectivesOnly = false; public boolean forceQualified = false; - public boolean forUserDefinedConversion = false; public boolean forAssociatedScopes = false; public boolean contentAssist = false; public boolean prefixLookup = false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index 64a282e2b62..1c1fd0accad 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -29,7 +29,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; -import org.eclipse.cdt.core.model.ITypeDef; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArraySet; @@ -284,7 +283,7 @@ public class SemanticUtil { return new CPPFunctionType(ret, params, ((ICPPFunctionType) type).getThisType()); } - if (type instanceof ITypeDef) { + if (type instanceof ITypedef) { IType t= ((ITypedef) type).getType(); if (t != null) return getSimplifiedType(t);