From 328c7a9828fc098181ce0bed3991a06b95899285 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Thu, 7 Mar 2019 11:12:57 +0100 Subject: [PATCH 01/15] TEMP --- src/dmd/errors.d | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 064115e64d3f..2136127357a2 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -21,6 +21,32 @@ import dmd.root.outbuffer; import dmd.root.rmem; import dmd.console; +/// Diagnostic severity. +enum Severity +{ + /// An error occurred. + error, + + /// A warning occurred. + warning, + + /// A deprecation occurred. + deprecation +} + +/// A single diagnostic message. +immutable struct Diagnostic +{ + /// The location of where the diagnostic occurred. + Loc loc; + + /// The severity of the diagnostic. + Severity severity; + + /// The message. + string message; +} + /** * Color highlighting to classify messages */ From 6de4a068ce9e25f3f4133537111a6204c31fae72 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Tue, 12 Mar 2019 21:05:23 +0100 Subject: [PATCH 02/15] TEMP 2 --- src/dmd/errors.d | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 2136127357a2..d3370a0ed3b7 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -35,16 +35,32 @@ enum Severity } /// A single diagnostic message. -immutable struct Diagnostic +abstract class Diagnostic { /// The location of where the diagnostic occurred. - Loc loc; + const Loc loc; /// The severity of the diagnostic. - Severity severity; + const Severity severity; /// The message. - string message; + abstract string message(); + + this(const ref Loc loc, const Severity severity) + { + this.loc = loc; + this.severity = severity; + } +} + +class FormattedDiagnostic(Args...) : Diagnostic +{ + private Args args; + + override string message() + { + + } } /** From d2b8c669094e9207637a610781e4abf39911b6f4 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Mon, 18 Mar 2019 20:53:21 +0100 Subject: [PATCH 03/15] TEMP 3 --- src/dmd/errors.d | 21 ++++++++++++++++++--- src/dmd/globals.d | 9 +++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index d3370a0ed3b7..d699ca94edff 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -44,7 +44,7 @@ abstract class Diagnostic const Severity severity; /// The message. - abstract string message(); + abstract string message() const nothrow; this(const ref Loc loc, const Severity severity) { @@ -55,11 +55,26 @@ abstract class Diagnostic class FormattedDiagnostic(Args...) : Diagnostic { - private Args args; + private const string formatString; + private const Args args; - override string message() + this(const ref Loc loc, const Severity severity, const string formatString, + const Args args) { + super(loc, severity); + this.formatString = formatString; + this.args = args; + } + + override string message() const nothrow + { + OutBuffer buffer; + + loc.toChars(buffer); + buffer.writestring(": "); + buffer.printf(formatString, args); + return cast(string) buffer.extractSlice(); } } diff --git a/src/dmd/globals.d b/src/dmd/globals.d index f2853bbd5756..6cf4d83baa1c 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -492,9 +492,8 @@ nothrow: this.filename = filename; } - extern (C++) const(char)* toChars() const + extern (C++) void toChars(ref OutBuffer buffer) const { - OutBuffer buf; if (filename) { buf.writestring(filename); @@ -510,6 +509,12 @@ nothrow: } buf.writeByte(')'); } + } + + extern (C++) const(char)* toChars() const + { + OutBuffer buf; + toChars(buffer); return buf.extractString(); } From 47cfcf58db74cd978b509c9c3bf08152f5f7a959 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Mon, 18 Mar 2019 20:55:36 +0100 Subject: [PATCH 04/15] Rename dmd.globals.Diagnostic to DiagnosticReporting --- src/dmd/errors.d | 14 +++++++------- src/dmd/globals.d | 6 +++--- src/dmd/lexer.d | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index d699ca94edff..29c19e58a120 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -379,12 +379,12 @@ extern (C++) void verrorSupplemental(const ref Loc loc, const(char)* format, va_ */ extern (C++) void vwarning(const ref Loc loc, const(char)* format, va_list ap) { - if (global.params.warnings != Diagnostic.off) + if (global.params.warnings != DiagnosticReporting.off) { if (!global.gag) { verrorPrint(loc, Classification.warning, "Warning: ", format, ap); - if (global.params.warnings == Diagnostic.error) + if (global.params.warnings == DiagnosticReporting.error) global.warnings++; } else @@ -403,7 +403,7 @@ extern (C++) void vwarning(const ref Loc loc, const(char)* format, va_list ap) */ extern (C++) void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap) { - if (global.params.warnings != Diagnostic.off && !global.gag) + if (global.params.warnings != DiagnosticReporting.off && !global.gag) verrorPrint(loc, Classification.warning, " ", format, ap); } @@ -419,9 +419,9 @@ extern (C++) void vwarningSupplemental(const ref Loc loc, const(char)* format, v extern (C++) void vdeprecation(const ref Loc loc, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) { __gshared const(char)* header = "Deprecation: "; - if (global.params.useDeprecated == Diagnostic.error) + if (global.params.useDeprecated == DiagnosticReporting.error) verror(loc, format, ap, p1, p2, header); - else if (global.params.useDeprecated == Diagnostic.inform) + else if (global.params.useDeprecated == DiagnosticReporting.inform) { if (!global.gag) { @@ -465,9 +465,9 @@ extern (C++) void vmessage(const ref Loc loc, const(char)* format, va_list ap) */ extern (C++) void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap) { - if (global.params.useDeprecated == Diagnostic.error) + if (global.params.useDeprecated == DiagnosticReporting.error) verrorSupplemental(loc, format, ap); - else if (global.params.useDeprecated == Diagnostic.inform && !global.gag) + else if (global.params.useDeprecated == DiagnosticReporting.inform && !global.gag) verrorPrint(loc, Classification.deprecation, " ", format, ap); } diff --git a/src/dmd/globals.d b/src/dmd/globals.d index 6cf4d83baa1c..c23d967e9e53 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -34,7 +34,7 @@ enum TARGET : bool DragonFlyBSD = xversion!`DragonFlyBSD`, } -enum Diagnostic : ubyte +enum DiagnosticReporting : ubyte { error, // generate an error inform, // generate a warning @@ -132,7 +132,7 @@ struct Param bool isSolaris; // generate code for Solaris bool hasObjectiveC; // target supports Objective-C bool mscoff = false; // for Win32: write MsCoff object files instead of OMF - Diagnostic useDeprecated = Diagnostic.inform; // how use of deprecated features are handled + DiagnosticReporting useDeprecated = DiagnosticReporting.inform; // how use of deprecated features are handled bool stackstomp; // add stack stomping code bool useUnitTests; // generate unittest code bool useInline = false; // inline expand functions @@ -140,7 +140,7 @@ struct Param bool noDIP25; // revert to pre-DIP25 behavior bool release; // build release version bool preservePaths; // true means don't strip path from source file - Diagnostic warnings = Diagnostic.off; // how compiler warnings are handled + DiagnosticReporting warnings = DiagnosticReporting.off; // how compiler warnings are handled bool pic; // generate position-independent-code for shared libs bool color; // use ANSI colors in console output bool cov; // generate code coverage data diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 2ad44e72223c..491402b737c1 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -333,7 +333,7 @@ This is usually the default diagnostic reporter. */ final class StderrDiagnosticReporter : DiagnosticReporter { - private const Diagnostic useDeprecated; + private const DiagnosticReporting useDeprecated; private int errorCount_; private int warningCount_; @@ -346,7 +346,7 @@ final class StderrDiagnosticReporter : DiagnosticReporter useDeprecated = indicates how deprecation diagnostics should be handled */ - this(Diagnostic useDeprecated) + this(DiagnosticReporting useDeprecated) { this.useDeprecated = useDeprecated; } From 223368ff825fc0aab071e29eaeb5f079b7e946ea Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Mon, 18 Mar 2019 20:56:02 +0100 Subject: [PATCH 05/15] fixup! TEMP 3 --- src/dmd/globals.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dmd/globals.d b/src/dmd/globals.d index c23d967e9e53..c6a720b13484 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -492,7 +492,7 @@ nothrow: this.filename = filename; } - extern (C++) void toChars(ref OutBuffer buffer) const + extern (C++) void toChars(ref OutBuffer buf) const { if (filename) { @@ -514,7 +514,7 @@ nothrow: extern (C++) const(char)* toChars() const { OutBuffer buf; - toChars(buffer); + toChars(buf); return buf.extractString(); } From f5131fa8fef619d7c77bb56a3b1baea216e87143 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Mon, 18 Mar 2019 20:57:03 +0100 Subject: [PATCH 06/15] fixup! Rename dmd.globals.Diagnostic to DiagnosticReporting --- src/dmd/dsymbol.d | 2 +- src/dmd/expressionsem.d | 4 ++-- src/dmd/lexer.d | 2 +- src/dmd/mars.d | 10 +++++----- src/dmd/semantic3.d | 2 +- src/dmd/sideeffect.d | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dmd/dsymbol.d b/src/dmd/dsymbol.d index afc5cf3d9ab6..5685a869c517 100644 --- a/src/dmd/dsymbol.d +++ b/src/dmd/dsymbol.d @@ -349,7 +349,7 @@ extern (C++) class Dsymbol : ASTNode final bool checkDeprecated(const ref Loc loc, Scope* sc) { - if (global.params.useDeprecated != Diagnostic.off && isDeprecated()) + if (global.params.useDeprecated != DiagnosticReporting.off && isDeprecated()) { // Don't complain if we're inside a deprecated symbol's scope if (sc.isDeprecated()) diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d index a4933bd82824..dbecc6e07c64 100644 --- a/src/dmd/expressionsem.d +++ b/src/dmd/expressionsem.d @@ -8530,7 +8530,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - if (0 && global.params.warnings != Diagnostic.off && !global.gag && exp.op == TOK.assign && + if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign && e2x.op != TOK.slice && e2x.op != TOK.assign && e2x.op != TOK.arrayLiteral && e2x.op != TOK.string_ && !(e2x.op == TOK.add || e2x.op == TOK.min || @@ -8594,7 +8594,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - if (0 && global.params.warnings != Diagnostic.off && !global.gag && exp.op == TOK.assign && + if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign && t1.ty == Tarray && t2.ty == Tsarray && e2x.op != TOK.slice && t2.implicitConvTo(t1)) diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 491402b737c1..97a7ae03fe3a 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -392,7 +392,7 @@ final class StderrDiagnosticReporter : DiagnosticReporter { vdeprecation(loc, format, args); - if (useDeprecated == Diagnostic.error) + if (useDeprecated == DiagnosticReporting.error) errorCount_++; else deprecationCount_++; diff --git a/src/dmd/mars.d b/src/dmd/mars.d index 3de3ba1f478c..3fa37daeb9ea 100644 --- a/src/dmd/mars.d +++ b/src/dmd/mars.d @@ -1573,11 +1573,11 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param if (arg == "-allinst") // https://dlang.org/dmd.html#switch-allinst params.allInst = true; else if (arg == "-de") // https://dlang.org/dmd.html#switch-de - params.useDeprecated = Diagnostic.error; + params.useDeprecated = DiagnosticReporting.error; else if (arg == "-d") // https://dlang.org/dmd.html#switch-d - params.useDeprecated = Diagnostic.off; + params.useDeprecated = DiagnosticReporting.off; else if (arg == "-dw") // https://dlang.org/dmd.html#switch-dw - params.useDeprecated = Diagnostic.inform; + params.useDeprecated = DiagnosticReporting.inform; else if (arg == "-c") // https://dlang.org/dmd.html#switch-c params.link = false; else if (startsWith(p + 1, "checkaction")) // https://dlang.org/dmd.html#switch-checkaction @@ -2009,9 +2009,9 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param params.useDIP25 = false; } else if (arg == "-w") // https://dlang.org/dmd.html#switch-w - params.warnings = Diagnostic.error; + params.warnings = DiagnosticReporting.error; else if (arg == "-wi") // https://dlang.org/dmd.html#switch-wi - params.warnings = Diagnostic.inform; + params.warnings = DiagnosticReporting.inform; else if (arg == "-O") // https://dlang.org/dmd.html#switch-O params.optimize = true; else if (p[1] == 'o') diff --git a/src/dmd/semantic3.d b/src/dmd/semantic3.d index dedfd6c858a2..0bc6b1870d5e 100644 --- a/src/dmd/semantic3.d +++ b/src/dmd/semantic3.d @@ -1384,7 +1384,7 @@ private extern(C++) final class Semantic3Visitor : Visitor // don't do it for unused deprecated types // or error ypes - if (!ad.getRTInfo && Type.rtinfo && (!ad.isDeprecated() || global.params.useDeprecated != Diagnostic.error) && (ad.type && ad.type.ty != Terror)) + if (!ad.getRTInfo && Type.rtinfo && (!ad.isDeprecated() || global.params.useDeprecated != DiagnosticReporting.error) && (ad.type && ad.type.ty != Terror)) { // Evaluate: RTinfo!type auto tiargs = new Objects(); diff --git a/src/dmd/sideeffect.d b/src/dmd/sideeffect.d index 98108ca223c4..f9e321512e9b 100644 --- a/src/dmd/sideeffect.d +++ b/src/dmd/sideeffect.d @@ -251,7 +251,7 @@ bool discardValue(Expression e) } case TOK.call: /* Issue 3882: */ - if (global.params.warnings != Diagnostic.off && !global.gag) + if (global.params.warnings != DiagnosticReporting.off && !global.gag) { CallExp ce = cast(CallExp)e; if (e.type.ty == Tvoid) From f5104ff1139275df4bb714fd4c15c371110062e4 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Tue, 19 Mar 2019 12:38:46 +0100 Subject: [PATCH 07/15] Use DiagnosticSet in lexer instead of printing error directly --- src/dmd/errors.d | 98 ++++++++++++++++++++++++-- src/dmd/lexer.d | 179 ++++++++++++++++++++++++----------------------- src/dmd/parse.d | 12 ++++ 3 files changed, 196 insertions(+), 93 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 29c19e58a120..c59a5224f542 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -21,6 +21,34 @@ import dmd.root.outbuffer; import dmd.root.rmem; import dmd.console; +auto toStringzThen(alias func)(const(char)[] str) +{ + import core.stdc.stdlib: malloc, free; + + if (str.length == 0) + return func("".ptr); + + char[1024] staticBuffer; + const newLength = str.length + 1; + char[] buffer; + + if (str.length >= buffer.length) + buffer = (cast(char*) malloc(newLength * char.sizeof))[0 .. newLength]; + else + buffer = staticBuffer[0 .. newLength]; + + scope (exit) + { + if (&buffer[0] != &staticBuffer[0]) + free(&buffer[0]); + } + + buffer[0 .. $ - 1] = str; + buffer[$ - 1] = '\0'; + + return func(&buffer[0]); +} + /// Diagnostic severity. enum Severity { @@ -31,7 +59,52 @@ enum Severity warning, /// A deprecation occurred. - deprecation + deprecation, +} + +struct DiagnosticSet +{ + private Diagnostic[] _diagnostics; + + void add(Diagnostic diagnostic) pure nothrow @safe + { + _diagnostics ~= diagnostic; + } + + void add(DiagnosticSet set) pure nothrow @safe + { + _diagnostics ~= set._diagnostics; + } + + void addSupplemental(const Diagnostic diagnostic) pure nothrow @safe + { + _diagnostics[$ - 1].addSupplementalDiagnostic(diagnostic); + } + + const(Diagnostic) front() const pure nothrow @nogc @safe + { + return _diagnostics[0]; + } + + void popFront() pure nothrow @nogc @safe + { + _diagnostics = _diagnostics[1 .. $]; + } + + bool empty() const pure nothrow @nogc @safe + { + return _diagnostics.length == 0; + } + + size_t length() const pure nothrow @nogc @safe + { + return _diagnostics.length; + } + + const(Diagnostic) opIndex(size_t index) const pure nothrow @nogc @safe + { + return _diagnostics[index]; + } } /// A single diagnostic message. @@ -46,11 +119,28 @@ abstract class Diagnostic /// The message. abstract string message() const nothrow; - this(const ref Loc loc, const Severity severity) + private const(Diagnostic)[] _supplementalDiagnostics; + + this(const ref Loc loc, const Severity severity) pure nothrow @nogc @safe { this.loc = loc; this.severity = severity; } + + final const(Diagnostic[]) supplementalDiagnostics() const pure nothrow @nogc @safe + { + return _supplementalDiagnostics; + } + + private final void addSupplementalDiagnostic(const Diagnostic diagnostic) pure nothrow @safe + in + { + assert(diagnostic.severity == severity); + } + body + { + _supplementalDiagnostics ~= diagnostic; + } } class FormattedDiagnostic(Args...) : Diagnostic @@ -59,7 +149,7 @@ class FormattedDiagnostic(Args...) : Diagnostic private const Args args; this(const ref Loc loc, const Severity severity, const string formatString, - const Args args) + const Args args) pure nothrow @nogc @safe { super(loc, severity); this.formatString = formatString; @@ -72,7 +162,7 @@ class FormattedDiagnostic(Args...) : Diagnostic loc.toChars(buffer); buffer.writestring(": "); - buffer.printf(formatString, args); + formatString.toStringzThen!(str => buffer.printf(str, args)); return cast(string) buffer.extractSlice(); } diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 97a7ae03fe3a..50a9d9fa86ad 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -430,6 +430,7 @@ class Lexer DiagnosticReporter diagnosticReporter; Token* tokenFreelist; + DiagnosticSet diagnosticSet; } /********************* @@ -495,7 +496,11 @@ class Lexer /// Returns: `true` if any errors occurred during lexing or parsing. final bool errors() { - return diagnosticReporter.errorCount > 0; + foreach (diagnostic; diagnosticSet) + if (diagnostic.severity == Severity.error) + return true; + + return false; } /// Returns: a newly allocated `Token`. @@ -518,7 +523,7 @@ class Lexer tokenFreelist = token; } - final TOK nextToken() + final TOK nextToken(out DiagnosticSet set) { prevloc = token.loc; if (token.next) @@ -532,6 +537,7 @@ class Lexer scan(&token); } //printf(token.toChars()); + set = diagnosticSet; return token.value; } @@ -554,9 +560,14 @@ class Lexer /**************************** * Turn next token in buffer into a token. + * + * Returns: a set of diagnostic that occurred when scanning the token */ - final void scan(Token* t) + final DiagnosticSet scan(Token* t) { + scope (exit) + diagnosticSet = DiagnosticSet(); + const lastLine = scanloc.linnum; Loc startLoc; t.blockComment = null; @@ -573,7 +584,7 @@ class Lexer case 0x1A: t.value = TOK.endOfFile; // end of file // Intentionally not advancing `p`, such that subsequent calls keep returning TOK.endOfFile. - return; + return diagnosticSet; case ' ': case '\t': case '\v': @@ -595,7 +606,7 @@ class Lexer ++p; t.unsvalue = 0; t.value = TOK.int32Literal; - return; + return diagnosticSet; } goto Lnumber; @@ -605,11 +616,11 @@ class Lexer t.unsvalue = *p - '0'; ++p; t.value = TOK.int32Literal; - return; + return diagnosticSet; } Lnumber: t.value = number(t); - return; + return diagnosticSet; case '\'': if (issinglechar(p[1]) && p[2] == '\'') @@ -620,7 +631,7 @@ class Lexer } else t.value = charConstant(t); - return; + return diagnosticSet; case 'r': if (p[1] != '"') goto case_ident; @@ -628,32 +639,32 @@ class Lexer goto case '`'; case '`': wysiwygStringConstant(t); - return; + return diagnosticSet; case 'x': if (p[1] != '"') goto case_ident; p++; t.value = hexStringConstant(t); deprecation("Built-in hex string literals are deprecated, use `std.conv.hexString` instead."); - return; + return diagnosticSet; case 'q': if (p[1] == '"') { p++; delimitedStringConstant(t); - return; + return diagnosticSet; } else if (p[1] == '{') { p++; tokenStringConstant(t); - return; + return diagnosticSet; } else goto case_ident; case '"': escapeStringConstant(t); - return; + return diagnosticSet; case 'a': case 'b': case 'c': @@ -782,7 +793,7 @@ class Lexer } } //printf("t.value = %d\n",t.value); - return; + return diagnosticSet; } case '/': p++; @@ -791,7 +802,7 @@ class Lexer case '=': p++; t.value = TOK.divAssign; - return; + return diagnosticSet; case '*': p++; startLoc = loc(); @@ -819,7 +830,7 @@ class Lexer p = end; t.loc = loc(); t.value = TOK.endOfFile; - return; + return diagnosticSet; default: if (c & 0x80) { @@ -840,7 +851,7 @@ class Lexer { t.loc = startLoc; t.value = TOK.comment; - return; + return diagnosticSet; } else if (doDocComment && t.ptr[2] == '*' && p - 4 != t.ptr) { @@ -869,7 +880,7 @@ class Lexer p = end; t.loc = startLoc; t.value = TOK.comment; - return; + return diagnosticSet; } if (doDocComment && t.ptr[2] == '/') { @@ -879,7 +890,7 @@ class Lexer p = end; t.loc = loc(); t.value = TOK.endOfFile; - return; + return diagnosticSet; default: if (c & 0x80) { @@ -897,7 +908,7 @@ class Lexer endOfLine(); t.loc = startLoc; t.value = TOK.comment; - return; + return diagnosticSet; } if (doDocComment && t.ptr[2] == '/') { @@ -950,7 +961,7 @@ class Lexer p = end; t.loc = loc(); t.value = TOK.endOfFile; - return; + return diagnosticSet; default: if (c & 0x80) { @@ -967,7 +978,7 @@ class Lexer { t.loc = startLoc; t.value = TOK.comment; - return; + return diagnosticSet; } if (doDocComment && t.ptr[2] == '+' && p - 4 != t.ptr) { @@ -981,7 +992,7 @@ class Lexer break; } t.value = TOK.div; - return; + return diagnosticSet; case '.': p++; if (isdigit(*p)) @@ -1007,7 +1018,7 @@ class Lexer } else t.value = TOK.dot; - return; + return diagnosticSet; case '&': p++; if (*p == '=') @@ -1022,7 +1033,7 @@ class Lexer } else t.value = TOK.and; - return; + return diagnosticSet; case '|': p++; if (*p == '=') @@ -1037,7 +1048,7 @@ class Lexer } else t.value = TOK.or; - return; + return diagnosticSet; case '-': p++; if (*p == '=') @@ -1052,7 +1063,7 @@ class Lexer } else t.value = TOK.min; - return; + return diagnosticSet; case '+': p++; if (*p == '=') @@ -1067,7 +1078,7 @@ class Lexer } else t.value = TOK.add; - return; + return diagnosticSet; case '<': p++; if (*p == '=') @@ -1088,7 +1099,7 @@ class Lexer } else t.value = TOK.lessThan; // < - return; + return diagnosticSet; case '>': p++; if (*p == '=') @@ -1120,7 +1131,7 @@ class Lexer } else t.value = TOK.greaterThan; // > - return; + return diagnosticSet; case '!': p++; if (*p == '=') @@ -1130,7 +1141,7 @@ class Lexer } else t.value = TOK.not; // ! - return; + return diagnosticSet; case '=': p++; if (*p == '=') @@ -1145,7 +1156,7 @@ class Lexer } else t.value = TOK.assign; // = - return; + return diagnosticSet; case '~': p++; if (*p == '=') @@ -1155,7 +1166,7 @@ class Lexer } else t.value = TOK.tilde; // ~ - return; + return diagnosticSet; case '^': p++; if (*p == '^') @@ -1176,55 +1187,55 @@ class Lexer } else t.value = TOK.xor; // ^ - return; + return diagnosticSet; case '(': p++; t.value = TOK.leftParentheses; - return; + return diagnosticSet; case ')': p++; t.value = TOK.rightParentheses; - return; + return diagnosticSet; case '[': p++; t.value = TOK.leftBracket; - return; + return diagnosticSet; case ']': p++; t.value = TOK.rightBracket; - return; + return diagnosticSet; case '{': p++; t.value = TOK.leftCurly; - return; + return diagnosticSet; case '}': p++; t.value = TOK.rightCurly; - return; + return diagnosticSet; case '?': p++; t.value = TOK.question; - return; + return diagnosticSet; case ',': p++; t.value = TOK.comma; - return; + return diagnosticSet; case ';': p++; t.value = TOK.semicolon; - return; + return diagnosticSet; case ':': p++; t.value = TOK.colon; - return; + return diagnosticSet; case '$': p++; t.value = TOK.dollar; - return; + return diagnosticSet; case '@': p++; t.value = TOK.at; - return; + return diagnosticSet; case '*': p++; if (*p == '=') @@ -1234,7 +1245,7 @@ class Lexer } else t.value = TOK.mul; - return; + return diagnosticSet; case '%': p++; if (*p == '=') @@ -1244,7 +1255,7 @@ class Lexer } else t.value = TOK.mod; - return; + return diagnosticSet; case '#': { p++; @@ -1268,7 +1279,7 @@ class Lexer error("C preprocessor directive `#if` is not supported, use `version` or `static if`"); } t.value = TOK.pound; - return; + return diagnosticSet; } default: { @@ -1295,6 +1306,8 @@ class Lexer } } } + + return diagnosticSet; } final Token* peek(Token* ct) @@ -2484,68 +2497,56 @@ class Lexer return scanloc; } - final void error(const(char)* format, ...) + void error(Args...)(string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.error(token.loc, format, args); - va_end(args); + error(token.loc, format, args); } - final void error(const ref Loc loc, const(char)* format, ...) + void error(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.error(loc, format, args); - va_end(args); + diagnosticSet.add( + new FormattedDiagnostic!(Args)(loc, Severity.error, format, args) + ); } - final void errorSupplemental(const ref Loc loc, const(char)* format, ...) + void errorSupplemental(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.errorSupplemental(loc, format, args); - va_end(args); + diagnosticSet.addSupplemental( + new FormattedDiagnostic!(Args)(loc, Severity.error, format, args) + ); } - final void warning(const ref Loc loc, const(char)* format, ...) + void warning(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.warning(loc, format, args); - va_end(args); + diagnosticSet.add( + new FormattedDiagnostic!(Args)(loc, Severity.warning, format, args) + ); } - final void warningSupplemental(const ref Loc loc, const(char)* format, ...) + void warningSupplemental(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.warningSupplemental(loc, format, args); - va_end(args); + diagnosticSet.addSupplemental( + new FormattedDiagnostic!(Args)(loc, Severity.warning, format, args) + ); } - final void deprecation(const(char)* format, ...) + void deprecation(Args...)(string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.deprecation(token.loc, format, args); - va_end(args); + deprecation(token.loc, format, args); } - final void deprecation(const ref Loc loc, const(char)* format, ...) + void deprecation(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.deprecation(loc, format, args); - va_end(args); + diagnosticSet.add( + new FormattedDiagnostic!(Args)(loc, Severity.deprecation, format, args) + ); } - final void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) + void deprecationSupplemental(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - va_list args; - va_start(args, format); - diagnosticReporter.deprecationSupplemental(loc, format, args); - va_end(args); + diagnosticSet.addSupplemental( + new FormattedDiagnostic!(Args)(loc, Severity.deprecation, format, args) + ); } /********************************************* diff --git a/src/dmd/parse.d b/src/dmd/parse.d index c0a7c3d0178e..aa79a35a0b2f 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -278,6 +278,7 @@ final class Parser(AST) : Lexer Loc endloc; // set to location of last right curly int inBrackets; // inside [] of array index or slice Loc lookingForElse; // location of lonely if looking for an else + DiagnosticSet diagnosticSet; } /********************* @@ -318,6 +319,17 @@ final class Parser(AST) : Lexer //nextToken(); // start up the scanner } + alias nextToken = typeof(super).nextToken; + + TOK nextToken() + { + DiagnosticSet set; + auto result = nextToken(set); + diagnosticSet.add(set); + + return result; + } + AST.Dsymbols* parseModule() { const comment = token.blockComment; From d410fc39fd08a87615d360606a974064ccb7ddb7 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Thu, 21 Mar 2019 12:30:29 +0100 Subject: [PATCH 08/15] TEMP --- src/dmd/errors.d | 41 +++++++++++++++++++++++++++++++++++++++++ src/dmd/lexer.d | 36 ++++++++++++++++++++---------------- src/dmd/parse.d | 11 ----------- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index c59a5224f542..cde2a7a5989b 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -49,6 +49,37 @@ auto toStringzThen(alias func)(const(char)[] str) return func(&buffer[0]); } +struct Diagnosed(T) +{ + T value; + DiagnosticSet diagnosticSet; + + T unwrap(ref DiagnosticSet diagnosticSet) + { + diagnosticSet.add(this.diagnosticSet); + return value; + } +} + +Diagnosed!T diagnosed(T)(T value, DiagnosticSet diagnosticSet) +{ + return Diagnosed!(T)(value, diagnosticSet); +} + +auto map(alias func, T)(Diagnosed!T diagnosed) +{ + return .diagnosed(func(diagnosed.value), diagnosed.diagnosticSet); +} + +auto chainedMap(alias func, T)(Diagnosed!T diagnosed) +{ + auto diagnosedResult = func(diagnosed.value); + auto originalSet = diagnosed.diagnosticSet; + auto resultSet = diagnosedResult.diagnosticSet; + + return .diagnosed(diagnosedResult.value, originalSet ~ resultSet); +} + /// Diagnostic severity. enum Severity { @@ -76,6 +107,16 @@ struct DiagnosticSet _diagnostics ~= set._diagnostics; } + DiagnosticSet opBinary(string op)(DiagnosticSet set) + if (op == "~") + { + DiagnosticSet newSet; + newSet.add(this); + newSet.add(set); + + return newSet; + } + void addSupplemental(const Diagnostic diagnostic) pure nothrow @safe { _diagnostics[$ - 1].addSupplementalDiagnostic(diagnostic); diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 50a9d9fa86ad..ae21340fc71f 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -523,8 +523,9 @@ class Lexer tokenFreelist = token; } - final TOK nextToken(out DiagnosticSet set) + final Diagnosed!TOK nextToken() { + DiagnosticSet set; prevloc = token.loc; if (token.next) { @@ -534,28 +535,28 @@ class Lexer } else { - scan(&token); + set = scan(&token); } //printf(token.toChars()); - set = diagnosticSet; - return token.value; + return diagnosed(token.value, set); } /*********************** * Look ahead at next token's value. */ - final TOK peekNext() + final Diagnosed!TOK peekNext() { - return peek(&token).value; + return peek(&token).map!(v => v.value); } /*********************** * Look 2 tokens ahead at value. */ - final TOK peekNext2() + final Diagnosed!TOK peekNext2() { - Token* t = peek(&token); - return peek(t).value; + return peek(&token) + .chainedMap!(t => peek(t)) + .map!(t => t.value); } /**************************** @@ -1310,32 +1311,35 @@ class Lexer return diagnosticSet; } - final Token* peek(Token* ct) + final Diagnosed!(Token*) peek(Token* ct) { Token* t; + DiagnosticSet set; if (ct.next) t = ct.next; else { t = allocateToken(); - scan(t); + set = scan(t); ct.next = t; } - return t; + return diagnosed(t, set); } /********************************* * tk is on the opening (. * Look ahead and return token that is past the closing ). */ - final Token* peekPastParen(Token* tk) + final Diagnosed!(Token*) peekPastParen(Token* tk) { //printf("peekPastParen()\n"); int parens = 1; int curlynest = 0; + DiagnosticSet set; + while (1) { - tk = peek(tk); + tk = peek(tk).unwrap(set); //tk.print(); switch (tk.value) { @@ -1346,7 +1350,7 @@ class Lexer --parens; if (parens) continue; - tk = peek(tk); + tk = peek(tk).unwrap(set); break; case TOK.leftCurly: curlynest++; @@ -1364,7 +1368,7 @@ class Lexer default: continue; } - return tk; + return diagnosed(tk, set); } } diff --git a/src/dmd/parse.d b/src/dmd/parse.d index aa79a35a0b2f..61a0a9b7334e 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -319,17 +319,6 @@ final class Parser(AST) : Lexer //nextToken(); // start up the scanner } - alias nextToken = typeof(super).nextToken; - - TOK nextToken() - { - DiagnosticSet set; - auto result = nextToken(set); - diagnosticSet.add(set); - - return result; - } - AST.Dsymbols* parseModule() { const comment = token.blockComment; From 295efed539ae3453ef85f09532e41e6b4f9bbe91 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Fri, 22 Mar 2019 20:17:56 +0100 Subject: [PATCH 09/15] Print forwarded diagnostics --- src/dmd/parse.d | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/dmd/parse.d b/src/dmd/parse.d index 61a0a9b7334e..dec3cb2b15e2 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -319,6 +319,82 @@ final class Parser(AST) : Lexer //nextToken(); // start up the scanner } + private void printDiagnostics(DiagnosticSet set) + { + static void printMessage(alias diagnosticFunc)(const Diagnostic diagnostic) + { + const message = diagnostic.message; + + diagnosticFunc(diagnostic.loc, "%.*s", + cast(int) message.length, message.ptr); + } + + static void printSupplementalMessages(alias diagnosticFunc) + (const Diagnostic[] diagnostics) + { + foreach (diagnostic; diagnostics) + printMessage!diagnosticFunc(diagnostic); + } + + foreach (diagnostic; set) + { + const message = diagnostic.message; + + with (Severity) final switch (diagnostic.severity) + { + case deprecation: + printMessage!(.deprecation)(diagnostic); + printSupplementalMessages!(.deprecationSupplemental) + (diagnostic.supplementalDiagnostics); + break; + + case error: + printMessage!(.error)(diagnostic); + printSupplementalMessages!(.errorSupplemental) + (diagnostic.supplementalDiagnostics); + break; + + case warning: + printMessage!(.warning)(diagnostic); + printSupplementalMessages!(.warningSupplemental) + (diagnostic.supplementalDiagnostics); + break; + } + } + } + + private auto forwardDiagnosedFunction(T)(lazy T value) + { + auto diagnosed = value; + printDiagnostics(diagnosed.diagnosticSet); + return diagnosed.value; + } + + TOK nextToken() + { + return forwardDiagnosedFunction(super.nextToken); + } + + TOK peekNext() + { + return forwardDiagnosedFunction(super.peekNext); + } + + TOK peekNext2() + { + return forwardDiagnosedFunction(super.peekNext2); + } + + Token* peek(Token* ct) + { + return forwardDiagnosedFunction(super.peek(ct)); + } + + Token* peekPastParen(Token* tk) + { + return forwardDiagnosedFunction(super.peekPastParen(tk)); + } + AST.Dsymbols* parseModule() { const comment = token.blockComment; From 7fc9d4118ff51b10af3e741284b688fd2268810d Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Fri, 22 Mar 2019 20:39:31 +0100 Subject: [PATCH 10/15] Fix --- src/dmd/errors.d | 3 --- src/dmd/lexer.d | 3 ++- src/dmd/parse.d | 27 +++++++++++++++++++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index cde2a7a5989b..6cb95129fb0e 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -200,9 +200,6 @@ class FormattedDiagnostic(Args...) : Diagnostic override string message() const nothrow { OutBuffer buffer; - - loc.toChars(buffer); - buffer.writestring(": "); formatString.toStringzThen!(str => buffer.printf(str, args)); return cast(string) buffer.extractSlice(); diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index ae21340fc71f..45d2cb085c53 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -416,6 +416,8 @@ class Lexer const(char)* p; // current character Token token; + // should be made private when the parser has its own DiagnosticSet + protected DiagnosticSet diagnosticSet; private { @@ -430,7 +432,6 @@ class Lexer DiagnosticReporter diagnosticReporter; Token* tokenFreelist; - DiagnosticSet diagnosticSet; } /********************* diff --git a/src/dmd/parse.d b/src/dmd/parse.d index dec3cb2b15e2..51b076a7e47e 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -278,7 +278,6 @@ final class Parser(AST) : Lexer Loc endloc; // set to location of last right curly int inBrackets; // inside [] of array index or slice Loc lookingForElse; // location of lonely if looking for an else - DiagnosticSet diagnosticSet; } /********************* @@ -319,8 +318,11 @@ final class Parser(AST) : Lexer //nextToken(); // start up the scanner } - private void printDiagnostics(DiagnosticSet set) + private void printDiagnostics(ref DiagnosticSet set) { + scope (exit) + set = DiagnosticSet(); + static void printMessage(alias diagnosticFunc)(const Diagnostic diagnostic) { const message = diagnostic.message; @@ -397,6 +399,9 @@ final class Parser(AST) : Lexer AST.Dsymbols* parseModule() { + scope (exit) + printDiagnostics(diagnosticSet); + const comment = token.blockComment; bool isdeprecated = false; AST.Expression msg = null; @@ -539,6 +544,9 @@ final class Parser(AST) : Lexer AST.Dsymbols* parseDeclDefs(int once, AST.Dsymbol* pLastDecl = null, PrefixAttributes!AST* pAttrs = null) { + scope (exit) + printDiagnostics(diagnosticSet); + AST.Dsymbol lastDecl = null; // used to link unittest to its previous declaration if (!pLastDecl) pLastDecl = &lastDecl; @@ -5422,6 +5430,9 @@ final class Parser(AST) : Lexer */ AST.Statement parseStatement(int flags, const(char)** endPtr = null, Loc* pEndloc = null) { + scope (exit) + printDiagnostics(diagnosticSet); + AST.Statement s; AST.Condition cond; AST.Statement ifbody; @@ -6755,6 +6766,9 @@ final class Parser(AST) : Lexer void check(TOK value) { + scope (exit) + printDiagnostics(diagnosticSet); + check(token.loc, value); } @@ -7609,6 +7623,9 @@ final class Parser(AST) : Lexer AST.Expression parseExpression() { + scope (exit) + printDiagnostics(diagnosticSet); + auto loc = token.loc; //printf("Parser::parseExpression() loc = %d\n", loc.linnum); @@ -7627,6 +7644,9 @@ final class Parser(AST) : Lexer AST.Expression parsePrimaryExp() { + scope (exit) + printDiagnostics(diagnosticSet); + AST.Expression e; AST.Type t; Identifier id; @@ -8833,6 +8853,9 @@ final class Parser(AST) : Lexer AST.Expression parseAssignExp() { + scope (exit) + printDiagnostics(diagnosticSet); + AST.Expression e; e = parseCondExp(); if (e is null) From 70ab9201a6e7c193e9e05775979ca3f72bd57190 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Fri, 22 Mar 2019 21:16:05 +0100 Subject: [PATCH 11/15] Fix some more errors --- src/dmd/errors.d | 50 +++++++++++++++++++++++++++ src/dmd/lexer.d | 14 ++++---- src/dmd/parse.d | 41 +--------------------- test/unit/lexer/diagnostic_reporter.d | 5 +-- 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 6cb95129fb0e..49c099a6f917 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -59,6 +59,12 @@ struct Diagnosed(T) diagnosticSet.add(this.diagnosticSet); return value; } + + T unwrap(alias func)() + { + func(diagnosticSet); + return value; + } } Diagnosed!T diagnosed(T)(T value, DiagnosticSet diagnosticSet) @@ -206,6 +212,50 @@ class FormattedDiagnostic(Args...) : Diagnostic } } +void printDiagnostics(DiagnosticSet set) +{ + static void printMessage(alias diagnosticFunc)(const Diagnostic diagnostic) + { + const message = diagnostic.message; + + diagnosticFunc(diagnostic.loc, "%.*s", + cast(int) message.length, message.ptr); + } + + static void printSupplementalMessages(alias diagnosticFunc) + (const Diagnostic[] diagnostics) + { + foreach (diagnostic; diagnostics) + printMessage!diagnosticFunc(diagnostic); + } + + foreach (diagnostic; set) + { + const message = diagnostic.message; + + final switch (diagnostic.severity) + { + case Severity.deprecation: + printMessage!deprecation(diagnostic); + printSupplementalMessages!deprecationSupplemental + (diagnostic.supplementalDiagnostics); + break; + + case Severity.error: + printMessage!error(diagnostic); + printSupplementalMessages!errorSupplemental + (diagnostic.supplementalDiagnostics); + break; + + case Severity.warning: + printMessage!warning(diagnostic); + printSupplementalMessages!warningSupplemental + (diagnostic.supplementalDiagnostics); + break; + } + } +} + /** * Color highlighting to classify messages */ diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 45d2cb085c53..1bdacec6f490 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -152,14 +152,14 @@ unittest scope diagnosticReporter = new StderrDiagnosticReporter(global.params.useDeprecated); scope Lexer lex1 = new Lexer(null, text.ptr, 0, text.length, 0, 0, diagnosticReporter); TOK tok; - tok = lex1.nextToken(); + tok = lex1.nextToken().unwrap!printDiagnostics; //printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOK.int32); assert(tok == TOK.int32); - tok = lex1.nextToken(); + tok = lex1.nextToken().unwrap!printDiagnostics; assert(tok == TOK.endOfFile); - tok = lex1.nextToken(); + tok = lex1.nextToken().unwrap!printDiagnostics; assert(tok == TOK.endOfFile); - tok = lex1.nextToken(); + tok = lex1.nextToken().unwrap!printDiagnostics; assert(tok == TOK.endOfFile); } @@ -187,14 +187,14 @@ unittest { scope diagnosticReporter = new StderrDiagnosticReporter(global.params.useDeprecated); scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, 0, 0, diagnosticReporter); - TOK tok = lex2.nextToken(); + TOK tok = lex2.nextToken().unwrap!printDiagnostics; size_t iterations = 1; while ((tok != TOK.endOfFile) && (iterations++ < testcase.length)) { - tok = lex2.nextToken(); + tok = lex2.nextToken().unwrap!printDiagnostics; } assert(tok == TOK.endOfFile); - tok = lex2.nextToken(); + tok = lex2.nextToken().unwrap!printDiagnostics; assert(tok == TOK.endOfFile); } } diff --git a/src/dmd/parse.d b/src/dmd/parse.d index 51b076a7e47e..b5e8d7cf8260 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -323,46 +323,7 @@ final class Parser(AST) : Lexer scope (exit) set = DiagnosticSet(); - static void printMessage(alias diagnosticFunc)(const Diagnostic diagnostic) - { - const message = diagnostic.message; - - diagnosticFunc(diagnostic.loc, "%.*s", - cast(int) message.length, message.ptr); - } - - static void printSupplementalMessages(alias diagnosticFunc) - (const Diagnostic[] diagnostics) - { - foreach (diagnostic; diagnostics) - printMessage!diagnosticFunc(diagnostic); - } - - foreach (diagnostic; set) - { - const message = diagnostic.message; - - with (Severity) final switch (diagnostic.severity) - { - case deprecation: - printMessage!(.deprecation)(diagnostic); - printSupplementalMessages!(.deprecationSupplemental) - (diagnostic.supplementalDiagnostics); - break; - - case error: - printMessage!(.error)(diagnostic); - printSupplementalMessages!(.errorSupplemental) - (diagnostic.supplementalDiagnostics); - break; - - case warning: - printMessage!(.warning)(diagnostic); - printSupplementalMessages!(.warningSupplemental) - (diagnostic.supplementalDiagnostics); - break; - } - } + .printDiagnostics(set); } private auto forwardDiagnosedFunction(T)(lazy T value) diff --git a/test/unit/lexer/diagnostic_reporter.d b/test/unit/lexer/diagnostic_reporter.d index 0a9a91db8e94..494b3328f964 100644 --- a/test/unit/lexer/diagnostic_reporter.d +++ b/test/unit/lexer/diagnostic_reporter.d @@ -72,11 +72,12 @@ unittest private void lexUntilEndOfFile(string code, DiagnosticReporter reporter) { + import dmd.errors : printDiagnostics; import dmd.lexer : Lexer; import dmd.tokens : TOK; scope lexer = new Lexer("test", code.ptr, 0, code.length, 0, 0, reporter); - lexer.nextToken; + lexer.nextToken.unwrap!printDiagnostics; - while (lexer.nextToken != TOK.endOfFile) {} + while (lexer.nextToken.unwrap!printDiagnostics != TOK.endOfFile) {} } From d19e4115abea5274163e96fe6b28955b0f9e56ab Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Sat, 23 Mar 2019 14:37:33 +0100 Subject: [PATCH 12/15] Move DiagnosticReporter to errors module --- src/dmd/doc.d | 4 +- src/dmd/errors.d | 262 +++++++++++++++++++--- src/dmd/frontend.d | 4 +- src/dmd/iasmgcc.d | 2 +- src/dmd/lexer.d | 307 +++----------------------- src/dmd/parse.d | 9 +- test/unit/lexer/diagnostic_reporter.d | 11 +- test/unit/support.d | 2 +- 8 files changed, 288 insertions(+), 313 deletions(-) diff --git a/src/dmd/doc.d b/src/dmd/doc.d index dbf58e2a1ab0..97d5c438a455 100644 --- a/src/dmd/doc.d +++ b/src/dmd/doc.d @@ -4482,7 +4482,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, OutBuffer* buf, size_t offse { uint errorsave = global.startGagging(); scope diagnosticReporter = new StderrDiagnosticReporter(global.params.useDeprecated); - scope Lexer lex = new Lexer(null, cast(char*)buf.data, 0, buf.offset - 1, 0, 1, diagnosticReporter); + scope Lexer lex = new Lexer(null, cast(char*)buf.data, 0, buf.offset - 1, 0, 1); OutBuffer res; const(char)* lastp = cast(char*)buf.data; //printf("highlightCode2('%.*s')\n", cast(int)(buf.offset - 1), buf.data); @@ -4490,7 +4490,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, OutBuffer* buf, size_t offse while (1) { Token tok; - lex.scan(&tok); + lex.scan(&tok).printDiagnostics(diagnosticReporter); highlightCode3(sc, &res, lastp, tok.ptr); const(char)* highlight = null; switch (tok.value) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 49c099a6f917..11f88412abed 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -53,18 +53,18 @@ struct Diagnosed(T) { T value; DiagnosticSet diagnosticSet; +} - T unwrap(ref DiagnosticSet diagnosticSet) - { - diagnosticSet.add(this.diagnosticSet); - return value; - } +T unwrap(T)(Diagnosed!T diagnosed, ref DiagnosticSet diagnosticSet) +{ + diagnosticSet.add(diagnosed.diagnosticSet); + return diagnosed.value; +} - T unwrap(alias func)() - { - func(diagnosticSet); - return value; - } +T unwrap(alias func, T)(Diagnosed!T diagnosed) +{ + func(diagnosed.diagnosticSet); + return diagnosed.value; } Diagnosed!T diagnosed(T)(T value, DiagnosticSet diagnosticSet) @@ -212,9 +212,13 @@ class FormattedDiagnostic(Args...) : Diagnostic } } -void printDiagnostics(DiagnosticSet set) +void printDiagnostics(DiagnosticSet set, DiagnosticReporter reporter) { - static void printMessage(alias diagnosticFunc)(const Diagnostic diagnostic) + alias DiagnosticFunction = void delegate( + ref const(Loc) loc, const(char)* format, ...); + + static void printMessage(const Diagnostic diagnostic, + DiagnosticFunction diagnosticFunc) { const message = diagnostic.message; @@ -222,11 +226,11 @@ void printDiagnostics(DiagnosticSet set) cast(int) message.length, message.ptr); } - static void printSupplementalMessages(alias diagnosticFunc) - (const Diagnostic[] diagnostics) + static void printSupplementalMessages(const Diagnostic[] diagnostics, + DiagnosticFunction diagnosticFunc) { foreach (diagnostic; diagnostics) - printMessage!diagnosticFunc(diagnostic); + printMessage(diagnostic, diagnosticFunc); } foreach (diagnostic; set) @@ -236,26 +240,231 @@ void printDiagnostics(DiagnosticSet set) final switch (diagnostic.severity) { case Severity.deprecation: - printMessage!deprecation(diagnostic); - printSupplementalMessages!deprecationSupplemental - (diagnostic.supplementalDiagnostics); + printMessage(diagnostic, &reporter.deprecation); + printSupplementalMessages(diagnostic.supplementalDiagnostics, + &reporter.deprecationSupplemental); break; case Severity.error: - printMessage!error(diagnostic); - printSupplementalMessages!errorSupplemental - (diagnostic.supplementalDiagnostics); + printMessage(diagnostic, &reporter.error); + printSupplementalMessages(diagnostic.supplementalDiagnostics, + &reporter.errorSupplemental); break; case Severity.warning: - printMessage!warning(diagnostic); - printSupplementalMessages!warningSupplemental - (diagnostic.supplementalDiagnostics); + printMessage(diagnostic, &reporter.warning); + printSupplementalMessages(diagnostic.supplementalDiagnostics, + &reporter.warningSupplemental); break; } } } +/// Interface for diagnostic reporting. +abstract class DiagnosticReporter +{ + /// Returns: the number of errors that occurred during lexing or parsing. + abstract int errorCount(); + + /// Returns: the number of warnings that occurred during lexing or parsing. + abstract int warningCount(); + + /// Returns: the number of deprecations that occurred during lexing or parsing. + abstract int deprecationCount(); + + /** + Reports an error message. + + Params: + loc = Location of error + format = format string for error + ... = format string arguments + */ + final void error(const ref Loc loc, const(char)* format, ...) + { + va_list args; + va_start(args, format); + error(loc, format, args); + va_end(args); + } + + /// ditto + abstract void error(const ref Loc loc, const(char)* format, va_list args); + + /** + Reports additional details about an error message. + + Params: + loc = Location of error + format = format string for supplemental message + ... = format string arguments + */ + final void errorSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list args; + va_start(args, format); + errorSupplemental(loc, format, args); + va_end(args); + } + + /// ditto + abstract void errorSupplemental(const ref Loc loc, const(char)* format, va_list); + + /** + Reports a warning message. + + Params: + loc = Location of warning + format = format string for warning + ... = format string arguments + */ + final void warning(const ref Loc loc, const(char)* format, ...) + { + va_list args; + va_start(args, format); + warning(loc, format, args); + va_end(args); + } + + /// ditto + abstract void warning(const ref Loc loc, const(char)* format, va_list args); + + /** + Reports additional details about a warning message. + + Params: + loc = Location of warning + format = format string for supplemental message + ... = format string arguments + */ + final void warningSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list args; + va_start(args, format); + warningSupplemental(loc, format, args); + va_end(args); + } + + /// ditto + abstract void warningSupplemental(const ref Loc loc, const(char)* format, va_list); + + /** + Reports a deprecation message. + + Params: + loc = Location of the deprecation + format = format string for the deprecation + ... = format string arguments + */ + final void deprecation(const ref Loc loc, const(char)* format, ...) + { + va_list args; + va_start(args, format); + deprecation(loc, format, args); + va_end(args); + } + + /// ditto + abstract void deprecation(const ref Loc loc, const(char)* format, va_list args); + + /** + Reports additional details about a deprecation message. + + Params: + loc = Location of deprecation + format = format string for supplemental message + ... = format string arguments + */ + final void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list args; + va_start(args, format); + deprecationSupplemental(loc, format, args); + va_end(args); + } + + /// ditto + abstract void deprecationSupplemental(const ref Loc loc, const(char)* format, va_list); +} + +/** +Diagnostic reporter which prints the diagnostic messages to stderr. + +This is usually the default diagnostic reporter. +*/ +final class StderrDiagnosticReporter : DiagnosticReporter +{ + private const DiagnosticReporting useDeprecated; + + private int errorCount_; + private int warningCount_; + private int deprecationCount_; + + /** + Initializes this object. + + Params: + useDeprecated = indicates how deprecation diagnostics should be + handled + */ + this(DiagnosticReporting useDeprecated) + { + this.useDeprecated = useDeprecated; + } + + override int errorCount() + { + return errorCount_; + } + + override int warningCount() + { + return warningCount_; + } + + override int deprecationCount() + { + return deprecationCount_; + } + + override void error(const ref Loc loc, const(char)* format, va_list args) + { + verror(loc, format, args); + errorCount_++; + } + + override void errorSupplemental(const ref Loc loc, const(char)* format, va_list args) + { + verrorSupplemental(loc, format, args); + } + + override void warning(const ref Loc loc, const(char)* format, va_list args) + { + vwarning(loc, format, args); + warningCount_++; + } + + override void warningSupplemental(const ref Loc loc, const(char)* format, va_list args) + { + vwarningSupplemental(loc, format, args); + } + + override void deprecation(const ref Loc loc, const(char)* format, va_list args) + { + vdeprecation(loc, format, args); + + if (useDeprecated == DiagnosticReporting.error) + errorCount_++; + else + deprecationCount_++; + } + + override void deprecationSupplemental(const ref Loc loc, const(char)* format, va_list args) + { + vdeprecationSupplemental(loc, format, args); + } +} + /** * Color highlighting to classify messages */ @@ -754,7 +963,7 @@ private void colorHighlightCode(OutBuffer* buf) auto gaggedErrorsSave = global.startGagging(); scope diagnosticReporter = new StderrDiagnosticReporter(global.params.useDeprecated); - scope Lexer lex = new Lexer(null, cast(char*)buf.data, 0, buf.offset - 1, 0, 1, diagnosticReporter); + scope Lexer lex = new Lexer(null, cast(char*)buf.data, 0, buf.offset - 1, 0, 1); OutBuffer res; const(char)* lastp = cast(char*)buf.data; //printf("colorHighlightCode('%.*s')\n", cast(int)(buf.offset - 1), buf.data); @@ -764,7 +973,8 @@ private void colorHighlightCode(OutBuffer* buf) while (1) { Token tok; - lex.scan(&tok); + lex.scan(&tok) + .printDiagnostics(diagnosticReporter); res.writestring(lastp[0 .. tok.ptr - lastp]); HIGHLIGHT highlight; switch (tok.value) diff --git a/src/dmd/frontend.d b/src/dmd/frontend.d index fcdb55393d33..53d39d1bfb3f 100644 --- a/src/dmd/frontend.d +++ b/src/dmd/frontend.d @@ -15,7 +15,7 @@ module dmd.frontend; import dmd.dmodule : Module; -import dmd.lexer : DiagnosticReporter; +import dmd.errors : DiagnosticReporter; import std.range.primitives : isInputRange, ElementType; import std.traits : isNarrowString; @@ -367,7 +367,7 @@ string prettyPrint(Module m) private DiagnosticReporter defaultDiagnosticReporter() { import dmd.globals : global; - import dmd.lexer : StderrDiagnosticReporter; + import dmd.errors : StderrDiagnosticReporter; return new StderrDiagnosticReporter(global.params.useDeprecated); } diff --git a/src/dmd/iasmgcc.d b/src/dmd/iasmgcc.d index 42d54213a52b..f4e7a162a379 100644 --- a/src/dmd/iasmgcc.d +++ b/src/dmd/iasmgcc.d @@ -20,11 +20,11 @@ import core.stdc.string; import dmd.arraytypes; import dmd.astcodegen; import dmd.dscope; +import dmd.errors; import dmd.expression; import dmd.expressionsem; import dmd.identifier; import dmd.globals; -import dmd.lexer; import dmd.parse; import dmd.tokens; import dmd.statement; diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 1bdacec6f490..9b4c2f1fae80 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -150,7 +150,9 @@ unittest */ string text = "int"; // We rely on the implicit null-terminator scope diagnosticReporter = new StderrDiagnosticReporter(global.params.useDeprecated); - scope Lexer lex1 = new Lexer(null, text.ptr, 0, text.length, 0, 0, diagnosticReporter); + scope Lexer lex1 = new Lexer(null, text.ptr, 0, text.length, 0, 0); + + alias printDiagnostics = set => set.printDiagnostics(diagnosticReporter); TOK tok; tok = lex1.nextToken().unwrap!printDiagnostics; //printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOK.int32); @@ -186,7 +188,9 @@ unittest foreach (testcase; testcases) { scope diagnosticReporter = new StderrDiagnosticReporter(global.params.useDeprecated); - scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, 0, 0, diagnosticReporter); + scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, 0, 0); + + alias printDiagnostics = set => set.printDiagnostics(diagnosticReporter); TOK tok = lex2.nextToken().unwrap!printDiagnostics; size_t iterations = 1; while ((tok != TOK.endOfFile) && (iterations++ < testcase.length)) @@ -199,211 +203,6 @@ unittest } } -/// Interface for diagnostic reporting. -abstract class DiagnosticReporter -{ - /// Returns: the number of errors that occurred during lexing or parsing. - abstract int errorCount(); - - /// Returns: the number of warnings that occurred during lexing or parsing. - abstract int warningCount(); - - /// Returns: the number of deprecations that occurred during lexing or parsing. - abstract int deprecationCount(); - - /** - Reports an error message. - - Params: - loc = Location of error - format = format string for error - ... = format string arguments - */ - final void error(const ref Loc loc, const(char)* format, ...) - { - va_list args; - va_start(args, format); - error(loc, format, args); - va_end(args); - } - - /// ditto - abstract void error(const ref Loc loc, const(char)* format, va_list args); - - /** - Reports additional details about an error message. - - Params: - loc = Location of error - format = format string for supplemental message - ... = format string arguments - */ - final void errorSupplemental(const ref Loc loc, const(char)* format, ...) - { - va_list args; - va_start(args, format); - errorSupplemental(loc, format, args); - va_end(args); - } - - /// ditto - abstract void errorSupplemental(const ref Loc loc, const(char)* format, va_list); - - /** - Reports a warning message. - - Params: - loc = Location of warning - format = format string for warning - ... = format string arguments - */ - final void warning(const ref Loc loc, const(char)* format, ...) - { - va_list args; - va_start(args, format); - warning(loc, format, args); - va_end(args); - } - - /// ditto - abstract void warning(const ref Loc loc, const(char)* format, va_list args); - - /** - Reports additional details about a warning message. - - Params: - loc = Location of warning - format = format string for supplemental message - ... = format string arguments - */ - final void warningSupplemental(const ref Loc loc, const(char)* format, ...) - { - va_list args; - va_start(args, format); - warningSupplemental(loc, format, args); - va_end(args); - } - - /// ditto - abstract void warningSupplemental(const ref Loc loc, const(char)* format, va_list); - - /** - Reports a deprecation message. - - Params: - loc = Location of the deprecation - format = format string for the deprecation - ... = format string arguments - */ - final void deprecation(const ref Loc loc, const(char)* format, ...) - { - va_list args; - va_start(args, format); - deprecation(loc, format, args); - va_end(args); - } - - /// ditto - abstract void deprecation(const ref Loc loc, const(char)* format, va_list args); - - /** - Reports additional details about a deprecation message. - - Params: - loc = Location of deprecation - format = format string for supplemental message - ... = format string arguments - */ - final void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) - { - va_list args; - va_start(args, format); - deprecationSupplemental(loc, format, args); - va_end(args); - } - - /// ditto - abstract void deprecationSupplemental(const ref Loc loc, const(char)* format, va_list); -} - -/** -Diagnostic reporter which prints the diagnostic messages to stderr. - -This is usually the default diagnostic reporter. -*/ -final class StderrDiagnosticReporter : DiagnosticReporter -{ - private const DiagnosticReporting useDeprecated; - - private int errorCount_; - private int warningCount_; - private int deprecationCount_; - - /** - Initializes this object. - - Params: - useDeprecated = indicates how deprecation diagnostics should be - handled - */ - this(DiagnosticReporting useDeprecated) - { - this.useDeprecated = useDeprecated; - } - - override int errorCount() - { - return errorCount_; - } - - override int warningCount() - { - return warningCount_; - } - - override int deprecationCount() - { - return deprecationCount_; - } - - override void error(const ref Loc loc, const(char)* format, va_list args) - { - verror(loc, format, args); - errorCount_++; - } - - override void errorSupplemental(const ref Loc loc, const(char)* format, va_list args) - { - verrorSupplemental(loc, format, args); - } - - override void warning(const ref Loc loc, const(char)* format, va_list args) - { - vwarning(loc, format, args); - warningCount_++; - } - - override void warningSupplemental(const ref Loc loc, const(char)* format, va_list args) - { - vwarningSupplemental(loc, format, args); - } - - override void deprecation(const ref Loc loc, const(char)* format, va_list args) - { - vdeprecation(loc, format, args); - - if (useDeprecated == DiagnosticReporting.error) - errorCount_++; - else - deprecationCount_++; - } - - override void deprecationSupplemental(const ref Loc loc, const(char)* format, va_list args) - { - vdeprecationSupplemental(loc, format, args); - } -} - /*********************************************************** */ class Lexer @@ -430,7 +229,6 @@ class Lexer bool commentToken; // comments are TOK.comment's int lastDocLine; // last line of previous doc comment - DiagnosticReporter diagnosticReporter; Token* tokenFreelist; } @@ -445,18 +243,10 @@ class Lexer * endoffset = the last offset to read into base[] * doDocComment = handle documentation comments * commentToken = comments become TOK.comment's - * diagnosticReporter = the diagnostic reporter to use */ this(const(char)* filename, const(char)* base, size_t begoffset, - size_t endoffset, bool doDocComment, bool commentToken, - DiagnosticReporter diagnosticReporter) - in + size_t endoffset, bool doDocComment, bool commentToken) { - assert(diagnosticReporter !is null); - } - body - { - this.diagnosticReporter = diagnosticReporter; scanloc = Loc(filename, 1, 1); //printf("Lexer::Lexer(%p,%d)\n",base,length); //printf("lexer.filename = %s\n", filename); @@ -1378,7 +1168,8 @@ class Lexer */ private uint escapeSequence() { - return Lexer.escapeSequence(token.loc, diagnosticReporter, p); + return Lexer.escapeSequence(token.loc, p) + .unwrap!(set => diagnosticSet.add(set)); } /** @@ -1391,13 +1182,17 @@ class Lexer Returns: the escaped sequence as a single character */ - private static dchar escapeSequence(const ref Loc loc, DiagnosticReporter handler, ref const(char)* sequence) - in - { - assert(handler !is null); - } - body + private static Diagnosed!dchar escapeSequence(const ref Loc loc, ref const(char)* sequence) { + DiagnosticSet diagnosticSet; + + void error(Args...)(const ref Loc loc, string format, Args args) + { + diagnosticSet.add( + new FormattedDiagnostic!(Args)(loc, Severity.error, format, args) + ); + } + const(char)* p = sequence; // cache sequence reference on stack scope(exit) sequence = p; @@ -1462,20 +1257,20 @@ class Lexer break; if (!ishex(cast(char)c)) { - handler.error(loc, "escape hex sequence has %d hex digits instead of %d", n, ndigits); + error(loc, "escape hex sequence has %d hex digits instead of %d", n, ndigits); break; } } if (ndigits != 2 && !utf_isValidDchar(v)) { - handler.error(loc, "invalid UTF character \\U%08x", v); + error(loc, "invalid UTF character \\U%08x", v); v = '?'; // recover with valid UTF character } c = v; } else { - handler.error(loc, "undefined escape hex sequence \\%c%c", sequence[0], c); + error(loc, "undefined escape hex sequence \\%c%c", sequence[0], c); p++; } break; @@ -1489,7 +1284,7 @@ class Lexer c = HtmlNamedEntity(idstart, p - idstart); if (c == ~0) { - handler.error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart); + error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart); c = '?'; } p++; @@ -1497,7 +1292,7 @@ class Lexer default: if (isalpha(*p) || (p != idstart && isdigit(*p))) continue; - handler.error(loc, "unterminated named entity &%.*s;", cast(int)(p - idstart + 1), idstart); + error(loc, "unterminated named entity &%.*s;", cast(int)(p - idstart + 1), idstart); c = '?'; break; } @@ -1522,16 +1317,16 @@ class Lexer while (++n < 3 && isoctal(cast(char)c)); c = v; if (c > 0xFF) - handler.error(loc, "escape octal sequence \\%03o is larger than \\377", c); + error(loc, "escape octal sequence \\%03o is larger than \\377", c); } else { - handler.error(loc, "undefined escape sequence \\%c", c); + error(loc, "undefined escape sequence \\%c", c); p++; } break; } - return c; + return diagnosed(cast(dchar) c, diagnosticSet); } /** @@ -2875,23 +2670,12 @@ private: unittest { - static final class AssertDiagnosticReporter : DiagnosticReporter - { - override int errorCount() { assert(0); } - override int warningCount() { assert(0); } - override int deprecationCount() { assert(0); } - override void error(const ref Loc, const(char)*, va_list) { assert(0); } - override void errorSupplemental(const ref Loc, const(char)*, va_list) { assert(0); } - override void warning(const ref Loc, const(char)*, va_list) { assert(0); } - override void warningSupplemental(const ref Loc, const(char)*, va_list) { assert(0); } - override void deprecation(const ref Loc, const(char)*, va_list) { assert(0); } - override void deprecationSupplemental(const ref Loc, const(char)*, va_list) { assert(0); } - } static void test(T)(string sequence, T expected) { - scope assertOnError = new AssertDiagnosticReporter(); auto p = cast(const(char)*)sequence.ptr; - assert(expected == Lexer.escapeSequence(Loc.initial, assertOnError, p)); + auto diagnosed = Lexer.escapeSequence(Loc.initial, p); + assert(expected == diagnosed.value); + assert(diagnosed.diagnosticSet.empty); assert(p == sequence.ptr + sequence.length); } @@ -2930,36 +2714,13 @@ unittest } unittest { - static final class ExpectDiagnosticReporter : DiagnosticReporter - { - string expected; - bool gotError; - this(string expected) { this.expected = expected; } - - override int errorCount() { assert(0); } - override int warningCount() { assert(0); } - override int deprecationCount() { assert(0); } - - override void error(const ref Loc loc, const(char)* format, va_list args) - { - gotError = true; - char[100] buffer; - auto actual = buffer[0 .. vsprintf(buffer.ptr, format, args)]; - assert(expected == actual); - } - - override void errorSupplemental(const ref Loc, const(char)*, va_list) { assert(0); } - override void warning(const ref Loc, const(char)*, va_list) { assert(0); } - override void warningSupplemental(const ref Loc, const(char)*, va_list) { assert(0); } - override void deprecation(const ref Loc, const(char)*, va_list) { assert(0); } - override void deprecationSupplemental(const ref Loc, const(char)*, va_list) { assert(0); } - } static void test(string sequence, string expectedError, dchar expectedReturnValue, uint expectedScanLength) { - scope handler = new ExpectDiagnosticReporter(expectedError); auto p = cast(const(char)*)sequence.ptr; - auto actualReturnValue = Lexer.escapeSequence(Loc.initial, handler, p); - assert(handler.gotError); + auto diagnosed = Lexer.escapeSequence(Loc.initial, p); + auto actualReturnValue = diagnosed.value; + assert(diagnosed.diagnosticSet.length); + assert(diagnosed.diagnosticSet.front.message == expectedError); assert(expectedReturnValue == actualReturnValue); auto actualScanLength = p - sequence.ptr; diff --git a/src/dmd/parse.d b/src/dmd/parse.d index b5e8d7cf8260..ea6fe4d4add8 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -278,6 +278,7 @@ final class Parser(AST) : Lexer Loc endloc; // set to location of last right curly int inBrackets; // inside [] of array index or slice Loc lookingForElse; // location of lonely if looking for an else + DiagnosticReporter diagnosticReporter; } /********************* @@ -288,9 +289,10 @@ final class Parser(AST) : Lexer extern (D) this(const ref Loc loc, AST.Module _module, const(char)[] input, bool doDocComment, DiagnosticReporter diagnosticReporter) { - super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false, diagnosticReporter); + super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false); //printf("Parser::Parser()\n"); + this.diagnosticReporter = diagnosticReporter; scanloc = loc; if (!writeMixin(input, scanloc) && loc.filename) @@ -310,9 +312,10 @@ final class Parser(AST) : Lexer extern (D) this(AST.Module _module, const(char)[] input, bool doDocComment, DiagnosticReporter diagnosticReporter) { - super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false, diagnosticReporter); + super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false); //printf("Parser::Parser()\n"); + this.diagnosticReporter = diagnosticReporter; mod = _module; linkage = LINK.d; //nextToken(); // start up the scanner @@ -323,7 +326,7 @@ final class Parser(AST) : Lexer scope (exit) set = DiagnosticSet(); - .printDiagnostics(set); + .printDiagnostics(set, diagnosticReporter); } private auto forwardDiagnosedFunction(T)(lazy T value) diff --git a/test/unit/lexer/diagnostic_reporter.d b/test/unit/lexer/diagnostic_reporter.d index 494b3328f964..df1b46cbc50b 100644 --- a/test/unit/lexer/diagnostic_reporter.d +++ b/test/unit/lexer/diagnostic_reporter.d @@ -2,8 +2,8 @@ module lexer.diagnostic_reporter; import core.stdc.stdarg; +import dmd.errors : DiagnosticReporter; import dmd.globals : Loc; -import dmd.lexer : DiagnosticReporter; import support : afterEach, NoopDiagnosticReporter; @@ -72,12 +72,13 @@ unittest private void lexUntilEndOfFile(string code, DiagnosticReporter reporter) { - import dmd.errors : printDiagnostics; + import dmd.errors : printDiagnostics, unwrap; import dmd.lexer : Lexer; import dmd.tokens : TOK; - scope lexer = new Lexer("test", code.ptr, 0, code.length, 0, 0, reporter); - lexer.nextToken.unwrap!printDiagnostics; + alias printDiags = set => set.printDiagnostics(reporter); + scope lexer = new Lexer("test", code.ptr, 0, code.length, 0, 0); + lexer.nextToken.unwrap!printDiags; - while (lexer.nextToken.unwrap!printDiagnostics != TOK.endOfFile) {} + while (lexer.nextToken.unwrap!printDiags != TOK.endOfFile) {} } diff --git a/test/unit/support.d b/test/unit/support.d index 857495563f7a..f99fc1c39c5d 100644 --- a/test/unit/support.d +++ b/test/unit/support.d @@ -1,6 +1,6 @@ module support; -import dmd.lexer : DiagnosticReporter; +import dmd.errors : DiagnosticReporter; /// UDA used to indicate a function should be run before each test. enum beforeEach; From ddcfdfcf93acfadb14bef20980097d214f686281 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Sat, 23 Mar 2019 20:06:05 +0100 Subject: [PATCH 13/15] Fix tests --- src/dmd/errors.d | 20 +++++++++++++++++--- src/dmd/lexer.d | 15 +++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 11f88412abed..85a2efcaeaab 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -113,16 +113,30 @@ struct DiagnosticSet _diagnostics ~= set._diagnostics; } - DiagnosticSet opBinary(string op)(DiagnosticSet set) + DiagnosticSet opBinary(string op)(DiagnosticSet set) pure nothrow @safe if (op == "~") { DiagnosticSet newSet; - newSet.add(this); - newSet.add(set); + newSet ~= this; + newSet ~= set; return newSet; } + DiagnosticSet opOpAssign(string op)(Diagnostic diagnostic) pure nothrow @safe + if (op == "~") + { + _diagnostics ~= diagnostic; + return this; + } + + DiagnosticSet opOpAssign(string op)(DiagnosticSet set) pure nothrow @safe + if (op == "~") + { + _diagnostics ~= set._diagnostics; + return this; + } + void addSupplemental(const Diagnostic diagnostic) pure nothrow @safe { _diagnostics[$ - 1].addSupplementalDiagnostic(diagnostic); diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 9b4c2f1fae80..65da4e7ff458 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -325,9 +325,8 @@ class Lexer releaseToken(t); } else - { set = scan(&token); - } + //printf(token.toChars()); return diagnosed(token.value, set); } @@ -358,7 +357,7 @@ class Lexer final DiagnosticSet scan(Token* t) { scope (exit) - diagnosticSet = DiagnosticSet(); + diagnosticSet = DiagnosticSet(); const lastLine = scanloc.linnum; Loc startLoc; @@ -1052,7 +1051,7 @@ class Lexer { p++; Token n; - scan(&n); + diagnosticSet ~= scan(&n); if (n.value == TOK.identifier) { if (n.ident == Id.line) @@ -1555,7 +1554,7 @@ class Lexer // Start of identifier; must be a heredoc Token tok; p--; - scan(&tok); // read in heredoc identifier + diagnosticSet ~= scan(&tok); // read in heredoc identifier if (tok.value != TOK.identifier) { error("identifier expected for heredoc, not %s", tok.toChars()); @@ -1603,7 +1602,7 @@ class Lexer Token tok; auto psave = p; p--; - scan(&tok); // read in possible heredoc identifier + diagnosticSet ~= scan(&tok); // read in possible heredoc identifier //printf("endid = '%s'\n", tok.ident.toChars()); if (tok.value == TOK.identifier && tok.ident.equals(hereid)) { @@ -1649,7 +1648,7 @@ class Lexer while (1) { Token tok; - scan(&tok); + diagnosticSet ~= scan(&tok); switch (tok.value) { case TOK.leftCurly: @@ -2360,7 +2359,7 @@ class Lexer const(char)* filespec = null; const loc = this.loc(); Token tok; - scan(&tok); + diagnosticSet ~= scan(&tok); if (tok.value == TOK.int32Literal || tok.value == TOK.int64Literal) { const lin = cast(int)(tok.unsvalue - 1); From 42b9018581869b8918f23babb6fdd5a843f53141 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Sat, 23 Mar 2019 20:09:34 +0100 Subject: [PATCH 14/15] Replace `add` with `~=` --- src/dmd/errors.d | 7 +------ src/dmd/lexer.d | 18 +++++------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 85a2efcaeaab..1d5942aff375 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -57,7 +57,7 @@ struct Diagnosed(T) T unwrap(T)(Diagnosed!T diagnosed, ref DiagnosticSet diagnosticSet) { - diagnosticSet.add(diagnosed.diagnosticSet); + diagnosticSet ~= diagnosed.diagnosticSet; return diagnosed.value; } @@ -108,11 +108,6 @@ struct DiagnosticSet _diagnostics ~= diagnostic; } - void add(DiagnosticSet set) pure nothrow @safe - { - _diagnostics ~= set._diagnostics; - } - DiagnosticSet opBinary(string op)(DiagnosticSet set) pure nothrow @safe if (op == "~") { diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 65da4e7ff458..8f0ec782371b 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -1168,7 +1168,7 @@ class Lexer private uint escapeSequence() { return Lexer.escapeSequence(token.loc, p) - .unwrap!(set => diagnosticSet.add(set)); + .unwrap!(set => diagnosticSet ~= set); } /** @@ -1187,9 +1187,7 @@ class Lexer void error(Args...)(const ref Loc loc, string format, Args args) { - diagnosticSet.add( - new FormattedDiagnostic!(Args)(loc, Severity.error, format, args) - ); + diagnosticSet ~= new FormattedDiagnostic!(Args)(loc, Severity.error, format, args); } const(char)* p = sequence; // cache sequence reference on stack @@ -2303,9 +2301,7 @@ class Lexer void error(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - diagnosticSet.add( - new FormattedDiagnostic!(Args)(loc, Severity.error, format, args) - ); + diagnosticSet ~= new FormattedDiagnostic!(Args)(loc, Severity.error, format, args); } void errorSupplemental(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe @@ -2317,9 +2313,7 @@ class Lexer void warning(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - diagnosticSet.add( - new FormattedDiagnostic!(Args)(loc, Severity.warning, format, args) - ); + diagnosticSet ~= new FormattedDiagnostic!(Args)(loc, Severity.warning, format, args); } void warningSupplemental(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe @@ -2336,9 +2330,7 @@ class Lexer void deprecation(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe { - diagnosticSet.add( - new FormattedDiagnostic!(Args)(loc, Severity.deprecation, format, args) - ); + diagnosticSet ~= new FormattedDiagnostic!(Args)(loc, Severity.deprecation, format, args); } void deprecationSupplemental(Args...)(const ref Loc loc, string format, Args args) pure nothrow @safe From e42f83e1164d53abec74c0447612c2e48dfc05b4 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Sat, 23 Mar 2019 20:11:11 +0100 Subject: [PATCH 15/15] Remove one of the `unwrap` overloads --- src/dmd/errors.d | 6 ------ src/dmd/lexer.d | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/dmd/errors.d b/src/dmd/errors.d index 1d5942aff375..de748b827061 100644 --- a/src/dmd/errors.d +++ b/src/dmd/errors.d @@ -55,12 +55,6 @@ struct Diagnosed(T) DiagnosticSet diagnosticSet; } -T unwrap(T)(Diagnosed!T diagnosed, ref DiagnosticSet diagnosticSet) -{ - diagnosticSet ~= diagnosed.diagnosticSet; - return diagnosed.value; -} - T unwrap(alias func, T)(Diagnosed!T diagnosed) { func(diagnosed.diagnosticSet); diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index 8f0ec782371b..37938abadb30 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -1129,7 +1129,7 @@ class Lexer while (1) { - tk = peek(tk).unwrap(set); + tk = peek(tk).unwrap!(s => set ~= s); //tk.print(); switch (tk.value) { @@ -1140,7 +1140,7 @@ class Lexer --parens; if (parens) continue; - tk = peek(tk).unwrap(set); + tk = peek(tk).unwrap!(s => set ~= s); break; case TOK.leftCurly: curlynest++;