Permalink
Browse files

Merge pull request #1539 from 9rnsr/fix6538

Issue 6538 - ICE(mangle.c) Invalid template constraints
  • Loading branch information...
2 parents 5eaf2e1 + d31dd28 commit f795e1b816e6a1dcc5667aecad0e1f937a3ddb12 @WalterBright WalterBright committed Jan 23, 2013
Showing with 187 additions and 1 deletion.
  1. +1 −0 src/declaration.c
  2. +2 −0 src/expression.c
  3. +49 −1 src/template.c
  4. +92 −0 test/fail_compilation/ice6538.d
  5. +21 −0 test/runnable/template9.d
  6. +22 −0 test/runnable/test11.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
@@ -3387,6 +3387,8 @@ Expression *SuperExp::semantic(Scope *sc)
s = fd->toParent();
while (s && s->isTemplateInstance())
s = s->toParent();
+ if (s->isTemplateDeclaration()) // allow inside template constraint
+ s = s->toParent();
assert(s);
cd = s->isClassDeclaration();
//printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
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,92 @@
+
+
+/**************************************/
+// 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);
+}
+
+/**************************************/
+// 9361
+
+template Sym(alias A)
+{
+ enum Sym = true;
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice6538.d(63): Error: cannot take a not yet instantiated symbol 'this' inside template constraint
+fail_compilation/ice6538.d(69): Error: template ice6538.S.foo does not match any function template declaration. Candidates are:
+fail_compilation/ice6538.d(63): ice6538.S.foo()() if (Sym!(this))
+fail_compilation/ice6538.d(69): Error: template ice6538.S.foo()() if (Sym!(this)) cannot deduce template function from argument types !()()
+---
+*/
+struct S
+{
+ void foo()() if (Sym!(this)) {}
+ void bar()() { static assert(Sym!(this)); } // OK
+}
+void test9361a()
+{
+ S s;
+ s.foo(); // fail
+ s.bar(); // OK
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice6538.d(85): Error: cannot take a not yet instantiated symbol 'super' inside template constraint
+fail_compilation/ice6538.d(90): Error: template ice6538.D.foo does not match any function template declaration. Candidates are:
+fail_compilation/ice6538.d(85): ice6538.D.foo()() if (Sym!(super))
+fail_compilation/ice6538.d(90): Error: template ice6538.D.foo()() if (Sym!(super)) cannot deduce template function from argument types !()()
+---
+*/
+class C {}
+class D : C
+{
+ void foo()() if (Sym!(super)) {}
+}
+void test9361b()
+{
+ auto d = new D();
+ d.foo();
+}
+
View
@@ -1917,6 +1917,27 @@ void test9266()
Bar9266!() a, b;
}
+/**********************************/
+// 9361
+
+struct Unit9361(A)
+{
+ void butPleaseDontUseMe()()
+ if (is(unitType9361!((this)))) // !
+ {}
+
+}
+template isUnit9361(alias T) if ( is(T)) {}
+template isUnit9361(alias T) if (!is(T)) {}
+
+template unitType9361(alias T) if (isUnit9361!T) {}
+
+void test9361()
+{
+ Unit9361!int u;
+ static assert(!__traits(compiles, u.butPleaseDontUseMe())); // crashes
+}
+
/**********************************/
int main()
View
@@ -1317,6 +1317,27 @@ void test8809()
assert(c.test3Dy() == 'D');
}
+/**************************************/
+// 9734
+
+void test9734()
+{
+ class C {}
+ class D : C
+ {
+ static bool test(C) { return true; }
+
+ void foo()() if (is(typeof(test(super)))) {}
+ void bar()() if (is(typeof(super) == C)) {}
+ }
+ void baz()() if (is(typeof(super))) {}
+
+ auto d = new D();
+ d.foo();
+ d.bar();
+ static assert(!__traits(compiles, baz()));
+}
+
/**************************************/
int main(string[] argv)
@@ -1384,6 +1405,7 @@ int main(string[] argv)
test64();
test65();
test8809();
+ test9734();
printf("Success\n");
return 0;

0 comments on commit f795e1b

Please sign in to comment.