1
0
Fork 0
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:
Andrew Ferguson 2008-06-20 13:19:02 +00:00
parent 901a511d5d
commit 525c3124a7
4 changed files with 105 additions and 96 deletions

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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) {

View file

@ -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++ ){