Skip to content

Commit

Permalink
Remove global.gag check in DsymbolExp.resolve()
Browse files Browse the repository at this point in the history
When an instance that will be converted to a constant exists,
the instance representation "foo!tiargs" is treated like a
variable name, and its recursive appearance check (note that
it's equivalent with a recursive instantiation of foo) is done
separately from the circular initialization check for the
eponymous enum variable declaration.

By the approach, we can remove problematic `global.gag` check in
`DsymbolExp::semantic()` without breaking `fail_compilation/diag10141.d`.
  • Loading branch information
9rnsr committed Sep 28, 2015
1 parent a3f7a55 commit d2c161c
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 16 deletions.
3 changes: 2 additions & 1 deletion src/dtemplate.d
Original file line number Diff line number Diff line change
Expand Up @@ -5417,7 +5417,8 @@ public:
Dsymbol aliasdecl; // !=null if instance is an alias for its sole member
TemplateInstance inst; // refer to existing instance
ScopeDsymbol argsym; // argument symbol table
int nest; // for recursion detection
int inuse; // for recursive expansion detection
int nest; // for recursive pretty printing detection
bool semantictiargsdone; // has semanticTiargs() been done?
bool havetempdecl; // if used second constructor
bool gagged; // if the instantiation is done with error gagging
Expand Down
72 changes: 67 additions & 5 deletions src/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -3732,14 +3732,12 @@ public:
//printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
if (!v.type)
{
.error(loc, "forward reference of %s %s", s.kind(), s.toChars());
.error(loc, "forward reference of %s %s", v.kind(), v.toChars());
return new ErrorExp();
}
if ((v.storage_class & STCmanifest) && v._init)
{
// Detect recursive initializers.
// BUG: The check for speculative gagging is not correct
if (v.inuse && !global.gag)
if (v.inuse)
{
.error(loc, "circular initialization of %s", v.toChars());
return new ErrorExp();
Expand All @@ -3751,6 +3749,7 @@ public:
v._scope = null;
v.inuse--;
}

e = v._init.toExpression(v.type);
if (!e)
{
Expand All @@ -3759,7 +3758,10 @@ public:
}
e = e.copy();
e.loc = loc; // for better error message

v.inuse++;
e = e.semantic(sc);
v.inuse--;
return e;
}
e = new VarExp(loc, v);
Expand Down Expand Up @@ -5191,7 +5193,7 @@ public:
{
static if (LOGSEMANTIC)
{
printf("+ScopeExp::semantic('%s')\n", toChars());
printf("+ScopeExp::semantic(%p '%s')\n", this, toChars());
}
//if (type == Type::tvoid)
// return this;
Expand Down Expand Up @@ -5255,6 +5257,66 @@ public:
continue;
}

if (auto v = s.isVarDeclaration())
{
if ((!v.type || !v.type.deco) && v._scope)
v.semantic(v._scope);

if (!v.type)
{
error("forward reference of %s %s", v.kind(), v.toChars());
return new ErrorExp();
}
if ((v.storage_class & STCmanifest) && v._init)
{
/* When an instance that will be converted to a constant exists,
* the instance representation "foo!tiargs" is treated like a
* variable name, and its recursive appearance check (note that
* it's equivalent with a recursive instantiation of foo) is done
* separately from the circular initialization check for the
* eponymous enum variable declaration.
*
* template foo(T) {
* enum bool foo = foo; // recursive definition check (v.inuse)
* }
* template bar(T) {
* enum bool bar = bar!T; // recursive instantiation check (ti.inuse)
* }
*/
if (ti.inuse)
{
error("recursive expansion of %s '%s'", ti.kind(), ti.toPrettyChars());
return new ErrorExp();
}
//if (v.inuse) // This is the point.
//{
// .error(loc, "circular initialization of %s", v.toChars());
// return new ErrorExp();
//}
if (v._scope)
{
v.inuse++;
v._init = v._init.semantic(v._scope, v.type, INITinterpret);
v._scope = null;
v.inuse--;
}

auto e = v._init.toExpression(v.type);
if (!e)
{
error("cannot make expression out of initializer for %s", v.toChars());
return new ErrorExp();
}
e = e.copy();
e.loc = loc; // for better error message

ti.inuse++;
e = e.semantic(sc);
ti.inuse--;
return e;
}
}

//printf("s = %s, '%s'\n", s.kind(), s.toChars());
auto e = DsymbolExp.resolve(loc, sc, s, s.hasOverloads());
//printf("-1ScopeExp::semantic()\n");
Expand Down
3 changes: 2 additions & 1 deletion src/template.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ class TemplateInstance : public ScopeDsymbol
Dsymbol *aliasdecl; // !=NULL if instance is an alias for its sole member
TemplateInstance *inst; // refer to existing instance
ScopeDsymbol *argsym; // argument symbol table
int nest; // for recursion detection
int inuse; // for recursive expansion detection
int nest; // for recursive pretty printing detection
bool semantictiargsdone; // has semanticTiargs() been done?
bool havetempdecl; // if used second constructor
bool gagged; // if the instantiation is done with error gagging
Expand Down
12 changes: 3 additions & 9 deletions test/fail_compilation/test8556.d
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/test8556.d(33): Error: circular initialization of isSliceable
fail_compilation/test8556.d(34): Error: circular initialization of isSliceable
fail_compilation/test8556.d(47): Error: template test8556.grabExactly cannot deduce function from argument types !()(Circle!(uint[])), candidates are:
fail_compilation/test8556.d(33): test8556.grabExactly(R)(R range) if (!isSliceable!R)
fail_compilation/test8556.d(34): test8556.grabExactly(R)(R range) if (isSliceable!R)
fail_compilation/test8556.d(22): Error: template instance test8556.isSliceable!(Circle!(uint[])) error instantiating
fail_compilation/test8556.d(27): while looking for match for Grab!(Circle!(uint[]))
fail_compilation/test8556.d(58): Error: template instance test8556.grab!(Circle!(uint[])) error instantiating
fail_compilation/test8556.d(61): Error: no [] operator overload for type Circle!(uint[])
fail_compilation/test8556.d(21): Error: template instance test8556.Grab!(Circle!(uint[])) does not match template declaration Grab(Range) if (!isSliceable!Range)
fail_compilation/test8556.d(52): Error: template instance test8556.grab!(Circle!(uint[])) error instantiating
---
*/

extern(C) int printf(const char*, ...);

template isSliceable(R)
Expand Down

0 comments on commit d2c161c

Please sign in to comment.