Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions compiler/src/dmd/dsymbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import dmd.dscope;
import dmd.dstruct;
import dmd.dtemplate;
import dmd.errors;
import dmd.errorsink;
import dmd.expression;
import dmd.func;
import dmd.globals;
Expand Down Expand Up @@ -122,6 +123,28 @@ struct Ungag
}
}

/**
* Temporarily changes the error sink for a scope.
* When the object goes out of scope, the original error sink is restored.
*/
struct ErrorSinkSwitch
{
ErrorSink oldSink;
Scope* sc;

extern (D) this(Scope* sc, ErrorSink newSink) nothrow @safe
{
this.sc = sc;
this.oldSink = sc.eSink;
sc.eSink = newSink;
}

extern (C++) ~this() nothrow
{
sc.eSink = oldSink;
}
}

struct Visibility
{
///
Expand Down Expand Up @@ -683,6 +706,13 @@ extern (C++) class Dsymbol : ASTNode
return parent.isSpeculative();
}

/**
* Returns an Ungag object that temporarily disables error gagging
* when not in a speculative context.
*
* This is the old implementation that uses global.gag.
* It will be deprecated in favor of ungagSpeculativeWithErrorSink.
*/
final Ungag ungagSpeculative() const
{
const oldgag = global.gag;
Expand All @@ -691,6 +721,19 @@ extern (C++) class Dsymbol : ASTNode
return Ungag(oldgag);
}

/**
* Returns an ErrorSinkSwitch object that temporarily changes the error sink
* to allow errors to be reported when not in a speculative context.
*
* This is the new implementation that uses ErrorSink instead of global.gag.
*/
final ErrorSinkSwitch ungagSpeculativeWithErrorSink(Scope* sc) const
{
if (sc.eSink == global.errorSinkNull && !isSpeculative() && !toParent2().isFuncDeclaration())
return ErrorSinkSwitch(sc, global.errorSink);
return ErrorSinkSwitch(sc, sc.eSink);
}

// kludge for template.isSymbol()
override final DYNCAST dyncast() const
{
Expand Down
30 changes: 15 additions & 15 deletions compiler/src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2919,8 +2919,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}

// Ungag errors when not speculative
Ungag ungag = sd.ungagSpeculative();
// Ungag errors when not speculative using ErrorSink
auto errorSinkSwitch = sd.ungagSpeculativeWithErrorSink(sc);

if (sd.semanticRun == PASS.initial)
{
Expand Down Expand Up @@ -3422,8 +3422,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
tc.sym = cldec;
}

// Ungag errors when not speculative
Ungag ungag = cldec.ungagSpeculative();
// Ungag errors when not speculative using ErrorSink
auto errorSinkSwitch = cldec.ungagSpeculativeWithErrorSink(sc);

if (cldec.semanticRun == PASS.initial)
{
Expand Down Expand Up @@ -4799,9 +4799,11 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
{
printf("Recursive template expansion\n");
}
auto ungag = Ungag(global.gag);
if (!tempinst.gagged)
global.gag = 0;
// Use ErrorSinkSwitch instead of Ungag
auto errorSinkSwitch = sc && sc.eSink == global.errorSinkNull ?
ErrorSinkSwitch(sc, global.errorSink) :
ErrorSinkSwitch(sc, sc.eSink);

.error(tempinst.loc, "%s `%s` recursive template expansion", tempinst.kind, tempinst.toPrettyChars);
if (tempinst.gagged)
tempinst.semanticRun = PASS.initial;
Expand Down Expand Up @@ -5560,14 +5562,12 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
const errors = global.errors;
Type oldtype = ds.type;

// Ungag errors when not instantiated DeclDefs scope alias
auto ungag = Ungag(global.gag);
//printf("%s parent = %s, gag = %d, instantiated = %d\n", ds.toChars(), ds.parent.toChars(), global.gag, ds.isInstantiated() !is null);
if (ds.parent && global.gag && !ds.isInstantiated() && !ds.toParent2().isFuncDeclaration() && (sc.minst || sc.tinst))
{
//printf("%s type = %s\n", ds.toPrettyChars(), ds.type.toChars());
global.gag = 0;
}
// Ungag errors when not instantiated DeclDefs scope alias using ErrorSink
auto errorSinkSwitch = sc && sc.eSink == global.errorSinkNull &&
ds.parent && !ds.isInstantiated() && !ds.toParent2().isFuncDeclaration() &&
(sc.minst || sc.tinst) ?
ErrorSinkSwitch(sc, global.errorSink) :
ErrorSinkSwitch(sc, sc.eSink);

// https://issues.dlang.org/show_bug.cgi?id=18480
// Detect `alias sym = sym;` to prevent creating loops in overload overnext lists.
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dmd/dtemplate.d
Original file line number Diff line number Diff line change
Expand Up @@ -4324,8 +4324,8 @@ extern (C++) class TemplateInstance : ScopeDsymbol
{
if (td._scope)
{
// Try to fix forward reference. Ungag errors while doing so.
Ungag ungag = td.ungagSpeculative();
// Try to fix forward reference. Ungag errors while doing so using ErrorSink.
auto errorSinkSwitch = td.ungagSpeculativeWithErrorSink(td._scope);
td.dsymbolSemantic(td._scope);
}
if (td.semanticRun == PASS.initial)
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dmd/templatesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
if (!fd.isCtorDeclaration &&
fd.semanticRun < PASS.semanticdone)
{
fd.ungagSpeculative();
// Use ErrorSinkSwitch instead of Ungag
auto errorSinkSwitch = fd.ungagSpeculativeWithErrorSink(sc);
fd.dsymbolSemantic(null);
}
if (fd.semanticRun < PASS.semanticdone)
Expand Down Expand Up @@ -2105,8 +2106,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,

if (td.semanticRun == PASS.initial && td._scope)
{
// Try to fix forward reference. Ungag errors while doing so.
td.ungagSpeculative();
// Try to fix forward reference. Ungag errors while doing so using ErrorSink.
auto errorSinkSwitch = td.ungagSpeculativeWithErrorSink(td._scope);
td.dsymbolSemantic(td._scope);
}
if (td.semanticRun == PASS.initial)
Expand Down
Loading