Permalink
Browse files

fix Issue 6538 - ICE(mangle.c) Invalid template constraints

  • Loading branch information...
1 parent c683f3b commit b950009c4a24f34e9dda4a52092f633cff59f940 @9rnsr 9rnsr committed Jan 23, 2013
Showing with 93 additions and 1 deletion.
  1. +1 −0 src/declaration.c
  2. +49 −1 src/template.c
  3. +43 −0 test/fail_compilation/ice6538.d
View
@@ -1087,6 +1087,7 @@ void VarDeclaration::semantic(Scope *sc)
(*exps)[i] = e;
}
TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
+ v2->parent = this->parent;
v2->isexp = 1;
aliassym = v2;
return;
View
@@ -693,7 +693,7 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E
if (!paramscope->insert(v))
error("parameter %s.%s is already defined", toChars(), v->toChars());
else
- v->parent = this;
+ v->parent = fd;
}
}
}
@@ -3989,6 +3989,45 @@ int TemplateAliasParameter::overloadMatch(TemplateParameter *tp)
return 0;
}
+/* Bugzilla 6538: In template constraint, each function parameters, 'this',
+ * and 'super' is *pseudo* symbol. If it is passed to other template through
+ * alias/tuple parameter, it will cause an error. Because such symbol
+ * does not have the actual entity yet.
+ *
+ * Example:
+ * template Sym(alias A) { enum Sym = true; }
+ * struct S {
+ * void foo() if (Sym!(this)) {} // Sym!(this) always make an error,
+ * } // because Sym template cannot
+ * void main() { S s; s.foo(); } // access to the valid 'this' symbol.
+ */
+bool isPseudoDsymbol(Object *o)
+{
+ Dsymbol *s = isDsymbol(o);
+ Expression *e = isExpression(o);
+ if (e && e->op == TOKvar) s = ((VarExp *)e)->var->isVarDeclaration();
+ if (e && e->op == TOKthis) s = ((ThisExp *)e)->var->isThisDeclaration();
+ if (e && e->op == TOKsuper) s = ((SuperExp *)e)->var->isThisDeclaration();
+
+ if (s && s->parent)
+ {
+ s = s->toAlias();
+ VarDeclaration *v = s->isVarDeclaration();
+ TupleDeclaration *t = s->isTupleDeclaration();
+ if (v || t)
+ {
+ FuncDeclaration *fd = s->parent->isFuncDeclaration();
+ if (fd && fd->parent && fd->parent->isTemplateDeclaration())
+ {
+ const char *str = (e && e->op == TOKsuper) ? "super" : s->toChars();
+ ::error(s->loc, "cannot take a not yet instantiated symbol '%s' inside template constraint", str);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam)
@@ -5303,6 +5342,10 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
ea = new ErrorExp();
}
//printf("-[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
+ if (!flags && isPseudoDsymbol(ea))
+ { (*tiargs)[j] = new ErrorExp();
+ continue;
+ }
if (ea->op == TOKtuple)
{ // Expand tuple
TupleExp *te = (TupleExp *)ea;
@@ -5362,6 +5405,11 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
else if (sa)
{
Ldsym:
+ //printf("dsym %s %s\n", sa->kind(), sa->toChars());
+ if (!flags && isPseudoDsymbol(sa))
+ { (*tiargs)[j] = new ErrorExp();
+ continue;
+ }
TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
if (d)
{ // Expand tuple
@@ -0,0 +1,43 @@
+
+
+/**************************************/
+// 6538
+
+template allSatisfy(alias F, T...) { enum bool allSatisfy = true; }
+template isIntegral(T) { enum bool isIntegral = true; }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice6538.d(18): Error: cannot take a not yet instantiated symbol 'sizes' inside template constraint
+fail_compilation/ice6538.d(23): Error: template ice6538.foo does not match any function template declaration. Candidates are:
+fail_compilation/ice6538.d(18): ice6538.foo(I...)(I sizes) if (allSatisfy!(isIntegral, sizes))
+fail_compilation/ice6538.d(23): Error: template ice6538.foo(I...)(I sizes) if (allSatisfy!(isIntegral, sizes)) cannot deduce template function from argument types !()(int,int)
+---
+*/
+void foo(I...)(I sizes)
+if (allSatisfy!(isIntegral, sizes)) {}
+
+void test6538a()
+{
+ foo(42, 86);
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice6538.d(36): Error: cannot take a not yet instantiated symbol 't1' inside template constraint
+fail_compilation/ice6538.d(36): Error: cannot take a not yet instantiated symbol 't2' inside template constraint
+fail_compilation/ice6538.d(41): Error: template ice6538.bar does not match any function template declaration. Candidates are:
+fail_compilation/ice6538.d(36): ice6538.bar(T1, T2)(T1 t1, T2 t2) if (allSatisfy!(isIntegral, t1, t2))
+fail_compilation/ice6538.d(41): Error: template ice6538.bar(T1, T2)(T1 t1, T2 t2) if (allSatisfy!(isIntegral, t1, t2)) cannot deduce template function from argument types !()(int,int)
+---
+*/
+void bar(T1, T2)(T1 t1, T2 t2)
+if (allSatisfy!(isIntegral, t1, t2)) {}
+
+void test6538b()
+{
+ bar(42, 86);
+}
+

0 comments on commit b950009

Please sign in to comment.