mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +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);
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -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; j<len; j++) {
|
||||
try {
|
||||
if (!deduceTemplateArgument(map, specArgs[j], args[j])) {
|
||||
return null;
|
||||
}
|
||||
} catch(DOMException de) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -1375,15 +1386,24 @@ public class CPPTemplates {
|
|||
}
|
||||
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);
|
||||
p = getParameterTypeForDeduction(p);
|
||||
a = getArgumentTypeForDeduction(a, pIsAReferenceType);
|
||||
|
||||
if (p instanceof IBasicType) {
|
||||
if (p.isSameType(a) && a instanceof IBasicType) {
|
||||
return expressionsEquivalent(((IBasicType) p).getValue(), ((IBasicType) a).getValue());
|
||||
if(a instanceof IBasicType) {
|
||||
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 {
|
||||
while (p != null) {
|
||||
|
@ -1560,29 +1580,10 @@ public class CPPTemplates {
|
|||
|
||||
ICPPClassTemplatePartialSpecialization bestMatch = null, spec = null;
|
||||
boolean bestMatchIsBest = true;
|
||||
IType[] specArgs = null;
|
||||
for (int i = 0; i < size; i++) {
|
||||
spec = specializations[i];
|
||||
specArgs = spec.getArguments();
|
||||
if (specArgs == null || specArgs.length != args.length) {
|
||||
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) {
|
||||
ObjectMap map= deduceTemplateArguments(spec.getArguments(), args, true);
|
||||
if (map != null) {
|
||||
int compare = orderSpecializations(bestMatch, spec);
|
||||
if (compare == 0) {
|
||||
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
|
||||
//specializations, then the use of the class template is ambiguous and the program is ill-formed.
|
||||
if (!bestMatchIsBest) {
|
||||
//TODO problem
|
||||
return new CPPTemplateDefinition.CPPTemplateProblem(null, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, null);
|
||||
}
|
||||
|
||||
|
@ -1738,19 +1738,7 @@ public class CPPTemplates {
|
|||
pType = (IType) map.get(pType);
|
||||
}
|
||||
|
||||
//14.1s8 function to pointer and array to pointer conversions
|
||||
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) {
|
||||
if(!isNonTypeArgumentConvertible(pType, argument)) {
|
||||
return false;
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
|
@ -1759,6 +1747,29 @@ public class CPPTemplates {
|
|||
}
|
||||
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 {
|
||||
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) {
|
||||
|
|
|
@ -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++ ){
|
||||
|
|
Loading…
Add table
Reference in a new issue