Skip to main content
summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorDavin McCall2019-05-19 06:02:34 -0400
committerNathan Ridge2019-05-21 12:59:00 -0400
commit2734b7ae8295dd4dde0d4383b2bcf7dc708a072a (patch)
tree9ee6032116c6fb1fc165279001fbc02b09878bcc /core
parent1cd0e1df35696e143697533ad3b1b35171d0670a (diff)
downloadorg.eclipse.cdt-2734b7ae8295dd4dde0d4383b2bcf7dc708a072a.tar.gz
org.eclipse.cdt-2734b7ae8295dd4dde0d4383b2bcf7dc708a072a.tar.xz
org.eclipse.cdt-2734b7ae8295dd4dde0d4383b2bcf7dc708a072a.zip
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>
Diffstat (limited to 'core')
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java57
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java65
2 files changed, 102 insertions, 20 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
index c53ccaa951..c42ac4dd8c 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
@@ -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 {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
index 9cf6aee19a..1ceb1694fc 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
@@ -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) {

Back to the top