diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index f980f5a5e68..d5c0ea77faf 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -2940,4 +2940,34 @@ public class AST2TemplateTests extends AST2BaseTest { ICPPClassType clazz= ba.assertNonProblem("That()", 4, ICPPClassType.class); ICPPConstructor ctor= ba.assertNonProblem("That()", 7, ICPPConstructor.class); } + + // template + // class C {}; + // + // template + // class C {}; + // + // class A {}; + // + // C ca5L; + public void testIntegralConversionInPartialSpecializationMatching_237914() throws Exception { + BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); + ICPPTemplateInstance ctps= ba.assertNonProblem("C", 7, ICPPTemplateInstance.class, ICPPClassType.class); + assertInstance(ctps.getTemplateDefinition(), ICPPClassTemplatePartialSpecialization.class); + } + + // template + // class C {}; + // + // class A {}; + // + // template<> + // class C {}; + // + // C ca5L; + public void testIntegralConversionInSpecializationMatching_237914() throws Exception { + BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); + ICPPSpecialization ctps= ba.assertNonProblem("C", 7, ICPPSpecialization.class, ICPPClassType.class); + assertFalse(ctps instanceof ICPPTemplateInstance); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java index de315559d79..e34b00991c8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java @@ -66,29 +66,9 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate impl return instance; } - IType [] specArgs = getArguments(); - if( specArgs.length != args.length ){ - return null; - } - - boolean argsContainDependentType= false; - ObjectMap argMap = new ObjectMap( specArgs.length ); - int numSpecArgs = specArgs.length; - for( int i = 0; i < numSpecArgs; i++ ){ - IType spec = specArgs[i]; - IType arg = args[i]; - - argsContainDependentType= argsContainDependentType || CPPTemplates.isDependentType(arg); - try { - if( !CPPTemplates.deduceTemplateArgument( argMap, spec, arg ) ) - return null; - } catch (DOMException e) { - return null; - } - } - - if (argsContainDependentType) { - return deferredInstance( argMap, args ); + ObjectMap argMap= CPPTemplates.deduceTemplateArguments(getArguments(), args, true); + if (CPPTemplates.containsDependentArg(argMap)) { + return deferredInstance(argMap, args); } ICPPTemplateParameter [] params = getTemplateParameters(); 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 9f6f82da42c..86c862d1fbd 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 @@ -1098,7 +1098,7 @@ public class CPPTemplates { // TODO - we should normalize template arguments // rather than check their original expressions // are equivalent. - return argA.isSameType(argB) && expressionsEquivalent(eA, eB); + return isNonTypeArgumentConvertible(argA, argB) && expressionsEquivalent(eA, eB); } } catch(DOMException de) { CCorePlugin.log(de); @@ -1272,25 +1272,36 @@ public class CPPTemplates { */ static private ObjectMap deduceTemplateArguments(ICPPFunctionTemplate template, IType[] arguments) throws DOMException{ ICPPFunction function = (ICPPFunction) template; - IParameter[] functionParameters = null; + IType[] functionParameters = null; try { - functionParameters = function.getParameters(); + functionParameters = function.getType().getParameterTypes(); } catch (DOMException e) { return null; } - if (arguments == null /*|| functionParameters.length != arguments.length*/) { + return deduceTemplateArguments(functionParameters, arguments, false); + } + + /** + * @param specArgs + * @param args + * @param all whether to match all arguments + * @return the mapping required to pairwise match the specified arguments, or null if no mapping exists + */ + public static ObjectMap deduceTemplateArguments(final IType[] specArgs, final IType[] args, final boolean all) { + if (specArgs == null || (all && specArgs.length != args.length)) { return null; } - - int numParams = functionParameters.length; - int numArgs = arguments.length; - ObjectMap map = new ObjectMap(numParams); - for (int i = 0; i < numArgs && i < numParams; i++) { - if (!deduceTemplateArgument(map, functionParameters[i].getType(), arguments[i])) { + ObjectMap map= new ObjectMap(specArgs.length); + int len= all ? specArgs.length : Math.min(specArgs.length, args.length); + for (int j=0; jarg can be converted to + * the same type as paramType using the rules specified in 14.3.2.5. + * @param paramType + * @param arg + * @return + * @throws DOMException + */ + private static boolean isNonTypeArgumentConvertible(IType paramType, IType arg) throws DOMException { + //14.1s8 function to pointer and array to pointer conversions + if (paramType instanceof IFunctionType) { + paramType = new CPPPointerType(paramType); + } else if (paramType instanceof IArrayType) { + try { + paramType = new CPPPointerType(((IArrayType) paramType).getType()); + } catch (DOMException e) { + paramType = e.getProblem(); + } + } + Cost cost = Conversions.checkStandardConversionSequence(arg, paramType, false); + return cost != null && cost.rank != Cost.NO_MATCH_RANK; + } public static IBinding instantiateWithinClassTemplate(ICPPClassTemplate template) throws DOMException { IType[] args = null; @@ -1788,6 +1799,14 @@ public class CPPTemplates { t = SemanticUtil.getUltimateType(t, false); return t instanceof ICPPUnknownBinding; } + + public static boolean containsDependentArg(ObjectMap argMap) { + for(Object arg : argMap.valueArray()) { + if(isDependentType((IType)arg)) + return true; + } + return false; + } public static IBinding instantiateTemplate(ICPPTemplateDefinition template, IType[] arguments, ObjectMap specializedArgs) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassTemplatePartialSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassTemplatePartialSpecialization.java index 32bebdcc37f..3b006228097 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassTemplatePartialSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassTemplatePartialSpecialization.java @@ -176,31 +176,11 @@ class PDOMCPPClassTemplatePartialSpecialization extends return instance; } - IType [] specArgs = getArguments(); - if( specArgs.length != args.length ){ - return null; + ObjectMap argMap= CPPTemplates.deduceTemplateArguments(getArguments(), args, true); + if (CPPTemplates.containsDependentArg(argMap)) { + return deferredInstance(argMap, args); } - boolean argsContainDependentType= false; - ObjectMap argMap = new ObjectMap( specArgs.length ); - int numSpecArgs = specArgs.length; - for( int i = 0; i < numSpecArgs; i++ ){ - IType spec = specArgs[i]; - IType arg = args[i]; - - argsContainDependentType= argsContainDependentType || CPPTemplates.isDependentType(arg); - try { - if( !CPPTemplates.deduceTemplateArgument( argMap, spec, arg ) ) - return null; - } catch (DOMException e) { - return null; - } - } - - if (argsContainDependentType) { - return deferredInstance( argMap, args ); - } - ICPPTemplateParameter [] params = getTemplateParameters(); int numParams = params.length; for( int i = 0; i < numParams; i++ ){