1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-15 04:05:38 +02:00

Bug 545040 - make array size inference work with initializer lists

Resolution for DR1591 clarified that initializer list size could be used
to deduce array size (if it is a template parameter).

Change-Id: Ic3617e31b125083f1205f91383eb27f5e5a29041
Signed-off-by: Davin McCall <davmac@davmac.org>
This commit is contained in:
Davin McCall 2019-05-19 20:02:34 +10:00 committed by Nathan Ridge
parent 1cd0e1df35
commit 2734b7ae82
2 changed files with 102 additions and 20 deletions

View file

@ -425,6 +425,63 @@ public class AST2TemplateTests extends AST2CPPTestBase {
assertEquals(f.getID(), IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
}
// template < int N > void f(const int (&v)[N]);
// void main() {
// f({1,2,3});
// }
public void test_dr1591_DeduceArrayFromInitializerList_a() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP);
NameCollector col = new NameCollector();
tu.accept(col);
ICPPFunctionTemplate f = (ICPPFunctionTemplate) col.getName(1).resolveBinding();
assertEquals("f", col.getName(5).toString());
IBinding fCall = col.getName(5).resolveBinding();
assertInstance(fCall, IFunction.class);
IFunction f2 = (IFunction) fCall;
assertInstance(f2, ICPPTemplateInstance.class);
assertSame(f, ((ICPPTemplateInstance) f2).getTemplateDefinition());
}
// template < typename T, int N > void f(const T (&v)[N]);
// void main() {
// f({1,2,3});
// }
public void test_dr1591_DeduceArrayFromInitializerList_b() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP);
NameCollector col = new NameCollector();
tu.accept(col);
ICPPFunctionTemplate f = (ICPPFunctionTemplate) col.getName(2).resolveBinding();
assertEquals("f", col.getName(7).toString());
IBinding fCall = col.getName(7).resolveBinding();
assertInstance(fCall, IFunction.class);
IFunction f2 = (IFunction) fCall;
assertInstance(f2, ICPPTemplateInstance.class);
assertSame(f, ((ICPPTemplateInstance) f2).getTemplateDefinition());
}
// template < typename T, int N > void f(const T (&v)[N]);
// void main() {
// f({1,2.0,3});
// }
public void test_dr1591_DeduceArrayFromInitializerList_c() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP);
NameCollector col = new NameCollector();
tu.accept(col);
ICPPFunctionTemplate f = (ICPPFunctionTemplate) col.getName(2).resolveBinding();
assertEquals("f", col.getName(7).toString());
IBinding fCall = col.getName(7).resolveBinding();
assertInstance(fCall, IProblemBinding.class);
IProblemBinding fCallPB = (IProblemBinding) fCall;
assertEquals(IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fCallPB.getID());
}
// template < class T, template < class X > class U, T *pT > class A {
// };
public void testTemplateParameters() throws Exception {

View file

@ -148,7 +148,20 @@ public class TemplateArgumentDeduction {
par = SemanticUtil.getNestedType(par, TDEF | REF | CVTYPE);
// Check if this is a deduced context.
IType inner = Conversions.getInitListType(par);
IType inner = null;
if (par instanceof IArrayType) {
// As per DR1591, if an initializer list is given as an argument for parameter type P[N],
// we can deduce N from the size of the initializer list (and potentially deduce P from
// the elements in the list).
inner = ((IArrayType) par).getType();
IValue as = IntegralValue
.create(((InitializerListType) arg).getEvaluation().getClauses().length);
IValue ps = ((IArrayType) par).getSize();
if (!deduct.fromArraySize(ps, as))
return false;
} else {
inner = Conversions.getInitListType(par);
}
if (inner != null) {
final EvalInitList eval = ((InitializerListType) arg).getEvaluation();
for (ICPPEvaluation clause : eval.getClauses()) {
@ -853,6 +866,35 @@ public class TemplateArgumentDeduction {
&& fromType(p.getTypeValue(), a.getTypeValue(), false, true));
}
/**
* Deduce a parameter array size from an argument array size.
* @param ps the parameter size (may refer to template parameter)
* @param as the argument array or initializer list size
* @return false if deduction encountered an error, true otherwise
*/
private boolean fromArraySize(IValue ps, IValue as) {
if (as != ps) {
if (as == null || ps == null)
return false;
int parID = IntegralValue.isTemplateParameter(ps);
if (parID >= 0) {
ICPPTemplateArgument old = fDeducedArgs.getArgument(parID, fPackOffset);
if (old == null) {
if (!deduce(parID, new CPPTemplateNonTypeArgument(as, new TypeOfValueDeducedFromArraySize()))) {
return false;
}
} else if (!as.equals(old.getNonTypeValue())) {
return false;
}
} else if (!as.equals(ps)) {
return false;
}
}
return true;
}
private boolean fromType(IType p, IType a, boolean allowCVQConversion, boolean verifyNonDeduced)
throws DOMException {
IType originalArgType = a;
@ -910,25 +952,8 @@ public class TemplateArgumentDeduction {
IArrayType pa = (IArrayType) p;
IValue as = aa.getSize();
IValue ps = pa.getSize();
if (as != ps) {
if (as == null || ps == null)
return false;
int parID = IntegralValue.isTemplateParameter(ps);
if (parID >= 0) {
ICPPTemplateArgument old = fDeducedArgs.getArgument(parID, fPackOffset);
if (old == null) {
if (!deduce(parID,
new CPPTemplateNonTypeArgument(as, new TypeOfValueDeducedFromArraySize()))) {
return false;
}
} else if (!as.equals(old.getNonTypeValue())) {
return false;
}
} else if (!as.equals(as)) {
return false;
}
}
if (!fromArraySize(ps, as))
return false;
p = pa.getType();
a = aa.getType();
} else if (p instanceof IQualifierType) {