mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-26 02:15:31 +02:00
237914: have non-type template argument conversions taken into account when selecting specializations/partial-specializations
This commit is contained in:
parent
901a511d5d
commit
525c3124a7
4 changed files with 105 additions and 96 deletions
|
@ -2940,4 +2940,34 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
ICPPClassType clazz= ba.assertNonProblem("That<I>()", 4, ICPPClassType.class);
|
ICPPClassType clazz= ba.assertNonProblem("That<I>()", 4, ICPPClassType.class);
|
||||||
ICPPConstructor ctor= ba.assertNonProblem("That<I>()", 7, ICPPConstructor.class);
|
ICPPConstructor ctor= ba.assertNonProblem("That<I>()", 7, ICPPConstructor.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template<typename T, int I>
|
||||||
|
// class C {};
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// class C<T, 5> {};
|
||||||
|
//
|
||||||
|
// class A {};
|
||||||
|
//
|
||||||
|
// C<A,5L> ca5L;
|
||||||
|
public void testIntegralConversionInPartialSpecializationMatching_237914() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ICPPTemplateInstance ctps= ba.assertNonProblem("C<A,5L>", 7, ICPPTemplateInstance.class, ICPPClassType.class);
|
||||||
|
assertInstance(ctps.getTemplateDefinition(), ICPPClassTemplatePartialSpecialization.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<typename T, int I>
|
||||||
|
// class C {};
|
||||||
|
//
|
||||||
|
// class A {};
|
||||||
|
//
|
||||||
|
// template<>
|
||||||
|
// class C<A, 5> {};
|
||||||
|
//
|
||||||
|
// C<A,5L> ca5L;
|
||||||
|
public void testIntegralConversionInSpecializationMatching_237914() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ICPPSpecialization ctps= ba.assertNonProblem("C<A,5L>", 7, ICPPSpecialization.class, ICPPClassType.class);
|
||||||
|
assertFalse(ctps instanceof ICPPTemplateInstance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,29 +66,9 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate impl
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
IType [] specArgs = getArguments();
|
ObjectMap argMap= CPPTemplates.deduceTemplateArguments(getArguments(), args, true);
|
||||||
if( specArgs.length != args.length ){
|
if (CPPTemplates.containsDependentArg(argMap)) {
|
||||||
return null;
|
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();
|
ICPPTemplateParameter [] params = getTemplateParameters();
|
||||||
|
|
|
@ -1098,7 +1098,7 @@ public class CPPTemplates {
|
||||||
// TODO - we should normalize template arguments
|
// TODO - we should normalize template arguments
|
||||||
// rather than check their original expressions
|
// rather than check their original expressions
|
||||||
// are equivalent.
|
// are equivalent.
|
||||||
return argA.isSameType(argB) && expressionsEquivalent(eA, eB);
|
return isNonTypeArgumentConvertible(argA, argB) && expressionsEquivalent(eA, eB);
|
||||||
}
|
}
|
||||||
} catch(DOMException de) {
|
} catch(DOMException de) {
|
||||||
CCorePlugin.log(de);
|
CCorePlugin.log(de);
|
||||||
|
@ -1272,25 +1272,36 @@ public class CPPTemplates {
|
||||||
*/
|
*/
|
||||||
static private ObjectMap deduceTemplateArguments(ICPPFunctionTemplate template, IType[] arguments) throws DOMException{
|
static private ObjectMap deduceTemplateArguments(ICPPFunctionTemplate template, IType[] arguments) throws DOMException{
|
||||||
ICPPFunction function = (ICPPFunction) template;
|
ICPPFunction function = (ICPPFunction) template;
|
||||||
IParameter[] functionParameters = null;
|
IType[] functionParameters = null;
|
||||||
try {
|
try {
|
||||||
functionParameters = function.getParameters();
|
functionParameters = function.getType().getParameterTypes();
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
return null;
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
ObjectMap map= new ObjectMap(specArgs.length);
|
||||||
int numParams = functionParameters.length;
|
int len= all ? specArgs.length : Math.min(specArgs.length, args.length);
|
||||||
int numArgs = arguments.length;
|
for (int j=0; j<len; j++) {
|
||||||
ObjectMap map = new ObjectMap(numParams);
|
try {
|
||||||
for (int i = 0; i < numArgs && i < numParams; i++) {
|
if (!deduceTemplateArgument(map, specArgs[j], args[j])) {
|
||||||
if (!deduceTemplateArgument(map, functionParameters[i].getType(), arguments[i])) {
|
return null;
|
||||||
|
}
|
||||||
|
} catch(DOMException de) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1375,15 +1386,24 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public boolean deduceTemplateArgument(ObjectMap map, IType p, IType a) throws DOMException {
|
private static boolean deduceTemplateArgument(ObjectMap map, IType p, IType a) throws DOMException {
|
||||||
boolean pIsAReferenceType = (p instanceof ICPPReferenceType);
|
boolean pIsAReferenceType = (p instanceof ICPPReferenceType);
|
||||||
p = getParameterTypeForDeduction(p);
|
p = getParameterTypeForDeduction(p);
|
||||||
a = getArgumentTypeForDeduction(a, pIsAReferenceType);
|
a = getArgumentTypeForDeduction(a, pIsAReferenceType);
|
||||||
|
|
||||||
if (p instanceof IBasicType) {
|
if (p instanceof IBasicType) {
|
||||||
if (p.isSameType(a) && a instanceof IBasicType) {
|
if(a instanceof IBasicType) {
|
||||||
return expressionsEquivalent(((IBasicType) p).getValue(), ((IBasicType) a).getValue());
|
IBasicType pbt= (IBasicType) p, abt= (IBasicType) a;
|
||||||
|
|
||||||
|
// non-type argument comparison
|
||||||
|
if(pbt.getValue() != null && abt.getValue() != null) {
|
||||||
|
return isNonTypeArgumentConvertible(p, a)
|
||||||
|
&& expressionsEquivalent(pbt.getValue(), abt.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// type argument comparison
|
||||||
|
return p.isSameType(a);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (p != null) {
|
while (p != null) {
|
||||||
|
@ -1560,29 +1580,10 @@ public class CPPTemplates {
|
||||||
|
|
||||||
ICPPClassTemplatePartialSpecialization bestMatch = null, spec = null;
|
ICPPClassTemplatePartialSpecialization bestMatch = null, spec = null;
|
||||||
boolean bestMatchIsBest = true;
|
boolean bestMatchIsBest = true;
|
||||||
IType[] specArgs = null;
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
spec = specializations[i];
|
spec = specializations[i];
|
||||||
specArgs = spec.getArguments();
|
ObjectMap map= deduceTemplateArguments(spec.getArguments(), args, true);
|
||||||
if (specArgs == null || specArgs.length != args.length) {
|
if (map != null) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int specArgsSize = specArgs.length;
|
|
||||||
ObjectMap map = new ObjectMap(specArgsSize);
|
|
||||||
IType t1 = null, t2 = null;
|
|
||||||
|
|
||||||
boolean match = true;
|
|
||||||
for (int j = 0; j < specArgsSize; j++) {
|
|
||||||
t1 = specArgs[j];
|
|
||||||
t2 = args[j];
|
|
||||||
|
|
||||||
if (!deduceTemplateArgument(map, t1, t2)) {
|
|
||||||
match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match) {
|
|
||||||
int compare = orderSpecializations(bestMatch, spec);
|
int compare = orderSpecializations(bestMatch, spec);
|
||||||
if (compare == 0) {
|
if (compare == 0) {
|
||||||
bestMatchIsBest = false;
|
bestMatchIsBest = false;
|
||||||
|
@ -1596,7 +1597,6 @@ public class CPPTemplates {
|
||||||
//14.5.4.1 If none of the specializations is more specialized than all the other matching
|
//14.5.4.1 If none of the specializations is more specialized than all the other matching
|
||||||
//specializations, then the use of the class template is ambiguous and the program is ill-formed.
|
//specializations, then the use of the class template is ambiguous and the program is ill-formed.
|
||||||
if (!bestMatchIsBest) {
|
if (!bestMatchIsBest) {
|
||||||
//TODO problem
|
|
||||||
return new CPPTemplateDefinition.CPPTemplateProblem(null, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, null);
|
return new CPPTemplateDefinition.CPPTemplateProblem(null, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1738,19 +1738,7 @@ public class CPPTemplates {
|
||||||
pType = (IType) map.get(pType);
|
pType = (IType) map.get(pType);
|
||||||
}
|
}
|
||||||
|
|
||||||
//14.1s8 function to pointer and array to pointer conversions
|
if(!isNonTypeArgumentConvertible(pType, argument)) {
|
||||||
if (pType instanceof IFunctionType) {
|
|
||||||
pType = new CPPPointerType(pType);
|
|
||||||
} else if (pType instanceof IArrayType) {
|
|
||||||
try {
|
|
||||||
pType = new CPPPointerType(((IArrayType) pType).getType());
|
|
||||||
} catch (DOMException e) {
|
|
||||||
pType = e.getProblem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Cost cost = Conversions.checkStandardConversionSequence(argument, pType, false);
|
|
||||||
|
|
||||||
if (cost == null || cost.rank == Cost.NO_MATCH_RANK) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
|
@ -1759,6 +1747,29 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the template argument <code>arg</code> can be converted to
|
||||||
|
* the same type as <code>paramType</code> 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 {
|
public static IBinding instantiateWithinClassTemplate(ICPPClassTemplate template) throws DOMException {
|
||||||
IType[] args = null;
|
IType[] args = null;
|
||||||
|
@ -1788,6 +1799,14 @@ public class CPPTemplates {
|
||||||
t = SemanticUtil.getUltimateType(t, false);
|
t = SemanticUtil.getUltimateType(t, false);
|
||||||
return t instanceof ICPPUnknownBinding;
|
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,
|
public static IBinding instantiateTemplate(ICPPTemplateDefinition template, IType[] arguments,
|
||||||
ObjectMap specializedArgs) {
|
ObjectMap specializedArgs) {
|
||||||
|
|
|
@ -176,31 +176,11 @@ class PDOMCPPClassTemplatePartialSpecialization extends
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
IType [] specArgs = getArguments();
|
ObjectMap argMap= CPPTemplates.deduceTemplateArguments(getArguments(), args, true);
|
||||||
if( specArgs.length != args.length ){
|
if (CPPTemplates.containsDependentArg(argMap)) {
|
||||||
return null;
|
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();
|
ICPPTemplateParameter [] params = getTemplateParameters();
|
||||||
int numParams = params.length;
|
int numParams = params.length;
|
||||||
for( int i = 0; i < numParams; i++ ){
|
for( int i = 0; i < numParams; i++ ){
|
||||||
|
|
Loading…
Add table
Reference in a new issue