mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-14 19:55:45 +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:
parent
1cd0e1df35
commit
2734b7ae82
2 changed files with 102 additions and 20 deletions
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue