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:
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);
|
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 {
|
// template < class T, template < class X > class U, T *pT > class A {
|
||||||
// };
|
// };
|
||||||
public void testTemplateParameters() throws Exception {
|
public void testTemplateParameters() throws Exception {
|
||||||
|
|
|
@ -148,7 +148,20 @@ public class TemplateArgumentDeduction {
|
||||||
par = SemanticUtil.getNestedType(par, TDEF | REF | CVTYPE);
|
par = SemanticUtil.getNestedType(par, TDEF | REF | CVTYPE);
|
||||||
|
|
||||||
// Check if this is a deduced context.
|
// 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) {
|
if (inner != null) {
|
||||||
final EvalInitList eval = ((InitializerListType) arg).getEvaluation();
|
final EvalInitList eval = ((InitializerListType) arg).getEvaluation();
|
||||||
for (ICPPEvaluation clause : eval.getClauses()) {
|
for (ICPPEvaluation clause : eval.getClauses()) {
|
||||||
|
@ -853,6 +866,35 @@ public class TemplateArgumentDeduction {
|
||||||
&& fromType(p.getTypeValue(), a.getTypeValue(), false, true));
|
&& 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)
|
private boolean fromType(IType p, IType a, boolean allowCVQConversion, boolean verifyNonDeduced)
|
||||||
throws DOMException {
|
throws DOMException {
|
||||||
IType originalArgType = a;
|
IType originalArgType = a;
|
||||||
|
@ -910,25 +952,8 @@ public class TemplateArgumentDeduction {
|
||||||
IArrayType pa = (IArrayType) p;
|
IArrayType pa = (IArrayType) p;
|
||||||
IValue as = aa.getSize();
|
IValue as = aa.getSize();
|
||||||
IValue ps = pa.getSize();
|
IValue ps = pa.getSize();
|
||||||
if (as != ps) {
|
if (!fromArraySize(ps, as))
|
||||||
if (as == null || ps == null)
|
|
||||||
return false;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p = pa.getType();
|
p = pa.getType();
|
||||||
a = aa.getType();
|
a = aa.getType();
|
||||||
} else if (p instanceof IQualifierType) {
|
} else if (p instanceof IQualifierType) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue