diff --git a/compiler/src/dmd/errors.d b/compiler/src/dmd/errors.d index 68bfa60a16..aa0be3a161 100644 --- a/compiler/src/dmd/errors.d +++ b/compiler/src/dmd/errors.d @@ -442,7 +442,7 @@ private struct ErrorInfo this.kind = kind; } - const SourceLoc loc; // location of error + const SourceLoc loc; // location of error Classification headerColor; // color to set `header` output to const(char)* p1; // additional message prefix const(char)* p2; // additional message prefix @@ -731,13 +731,9 @@ private void verrorPrint(const(char)* format, va_list ap, ref ErrorInfo info) !loc.filename.startsWith(".d-mixin-") && !global.params.mixinOut.doOutput) { - import dmd.root.filename : FileName; - if (auto text = cast(const(char[])) global.fileManager.getFileContents(FileName(loc.filename))) - { - tmp.reset(); - printErrorLineContext(tmp, text, loc.fileOffset); - fputs(tmp.peekChars(), stderr); - } + tmp.reset(); + printErrorLineContext(tmp, loc.fileContent, loc.fileOffset); + fputs(tmp.peekChars(), stderr); } old_loc = loc; fflush(stderr); // ensure it gets written out in case of compiler aborts @@ -750,7 +746,7 @@ private void printErrorLineContext(ref OutBuffer buf, const(char)[] text, size_t import dmd.root.utf : utf_decodeChar; if (offset >= text.length) - return; // Out of bounds (can happen in pre-processed C files currently) + return; // Out of bounds (missing source content in SourceLoc) // Scan backwards for beginning of line size_t s = offset; diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 730d53e489..910dd0d037 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -383,12 +383,14 @@ struct SourceLoc final uint32_t line; uint32_t column; uint32_t fileOffset; + _d_dynamicArray< const char > fileContent; const char* toChars(bool showColumns = Loc::showColumns, MessageStyle messageStyle = Loc::messageStyle) const; SourceLoc() : filename(), line(), column(), - fileOffset() + fileOffset(), + fileContent() { } }; diff --git a/compiler/src/dmd/globals.h b/compiler/src/dmd/globals.h index 59952a2c10..62a575e322 100644 --- a/compiler/src/dmd/globals.h +++ b/compiler/src/dmd/globals.h @@ -421,6 +421,7 @@ struct SourceLoc uint32_t line; uint32_t column; uint32_t fileOffset; + DString fileContent; }; struct Loc diff --git a/compiler/src/dmd/lexer.d b/compiler/src/dmd/lexer.d index 63313ac2ed..ed9f7f1ce7 100644 --- a/compiler/src/dmd/lexer.d +++ b/compiler/src/dmd/lexer.d @@ -132,7 +132,7 @@ class Lexer // debug printf("Lexer::Lexer(%p)\n", base); // debug printf("lexer.filename = %s\n", filename); token = Token.init; - this.baseLoc = newBaseLoc(filename, endoffset); + this.baseLoc = newBaseLoc(filename, base[0 .. endoffset]); this.linnum = 1; this.base = base; this.end = base + endoffset; @@ -224,7 +224,7 @@ class Lexer inTokenStringConstant = 0; lastDocLine = 0; - baseLoc = newBaseLoc("#defines", slice.length); + baseLoc = newBaseLoc("#defines", slice); scanloc = baseLoc.getLoc(0); } diff --git a/compiler/src/dmd/location.d b/compiler/src/dmd/location.d index 54b3fb6e0a..393ffb8a92 100644 --- a/compiler/src/dmd/location.d +++ b/compiler/src/dmd/location.d @@ -64,7 +64,7 @@ nothrow: extern (C++) static Loc singleFilename(const char* filename) { Loc result; - locFileTable ~= new BaseLoc(filename.toDString, locIndex, 0, [0]); + locFileTable ~= new BaseLoc(filename.toDString, null, locIndex, 0, [0]); result.index = locIndex++; return result; } @@ -235,16 +235,20 @@ struct SourceLoc uint column; /// column number (starts at 1) uint fileOffset; /// byte index into file + /// Index `fileOffset` into this to to obtain source code context of this location + const(char)[] fileContent; + // aliases for backwards compatibility alias linnum = line; alias charnum = column; - this(const(char)[] filename, uint line, uint column, uint fileOffset = 0) nothrow @nogc pure @safe + this(const(char)[] filename, uint line, uint column, uint fileOffset = 0, const(char)[] fileContent = null) nothrow @nogc pure @safe { this.filename = filename; this.line = line; this.column = column; this.fileOffset = fileOffset; + this.fileContent = fileContent; } this(Loc loc) nothrow @nogc @trusted @@ -300,15 +304,15 @@ private size_t fileTableIndex(uint index) nothrow @nogc * Create a new source location map for a file * Params: * filename = source file name - * size = space to reserve for locations, equal to the file size in bytes + * fileContent = content of source file * Returns: new BaseLoc */ -BaseLoc* newBaseLoc(const(char)* filename, size_t size) nothrow +BaseLoc* newBaseLoc(const(char)* filename, const(char)[] fileContent) nothrow { - locFileTable ~= new BaseLoc(filename.toDString, locIndex, 1, [0]); + locFileTable ~= new BaseLoc(filename.toDString, fileContent, locIndex, 1, [0]); // Careful: the endloc of a FuncDeclaration can // point to 1 past the very last byte in the file, so account for that - locIndex += size + 1; + locIndex += fileContent.length + 1; return locFileTable[$ - 1]; } @@ -354,6 +358,7 @@ struct BaseLoc @safe nothrow: const(char)[] filename; /// Source file name + const(char)[] fileContents; /// Source file contents uint startIndex; /// Subtract this from Loc.index to get file offset int startLine = 1; /// Line number at index 0 uint[] lines; /// For each line, the file offset at which it starts. At index 0 there's always a 0 entry. @@ -384,11 +389,11 @@ struct BaseLoc { auto fname = filename.toDString; if (substitutions.length == 0) - substitutions ~= BaseLoc(this.filename, 0, 0); + substitutions ~= BaseLoc(this.filename, null, 0, 0); if (fname.length == 0) fname = substitutions[$ - 1].filename; - substitutions ~= BaseLoc(fname, offset, cast(int) (line - lines.length + startLine - 2)); + substitutions ~= BaseLoc(fname, null, offset, cast(int) (line - lines.length + startLine - 2)); } /// Returns: `loc` modified by substitutions from #file / #line directives @@ -408,7 +413,7 @@ struct BaseLoc private SourceLoc getSourceLoc(uint offset) @nogc { const i = getLineIndex(offset); - const sl = SourceLoc(filename, cast(int) (i + startLine), cast(int) (1 + offset - lines[i]), offset); + const sl = SourceLoc(filename, cast(int) (i + startLine), cast(int) (1 + offset - lines[i]), offset, fileContents); return substitute(sl); } diff --git a/compiler/test/compilable/pragmapack.c b/compiler/test/compilable/pragmapack.c index 7c2470e566..938c7cde4d 100644 --- a/compiler/test/compilable/pragmapack.c +++ b/compiler/test/compilable/pragmapack.c @@ -1,4 +1,4 @@ -/* REQUIRED_ARGS: -wi +/* REQUIRED_ARGS: -wi -verrors=simple TEST_OUTPUT: --- compilable/pragmapack.c(101): Warning: current pack attribute is default diff --git a/compiler/test/fail_compilation/fail_pretty_errors.d b/compiler/test/fail_compilation/fail_pretty_errors.d index 2016a50175..79242b163e 100644 --- a/compiler/test/fail_compilation/fail_pretty_errors.d +++ b/compiler/test/fail_compilation/fail_pretty_errors.d @@ -1,22 +1,24 @@ -/* +/* REQUIRED_ARGS: -verrors=context TEST_OUTPUT: --- -fail_compilation/fail_pretty_errors.d(27): Error: undefined identifier `a` +fail_compilation/fail_pretty_errors.d(29): Error: undefined identifier `a` a = 1; ^ -fail_compilation/fail_pretty_errors.d-mixin-32(32): Error: undefined identifier `b` -fail_compilation/fail_pretty_errors.d(37): Error: cannot implicitly convert expression `5` of type `int` to `string` +fail_compilation/fail_pretty_errors.d-mixin-34(34): Error: undefined identifier `b` +b = 1; +^ +fail_compilation/fail_pretty_errors.d(39): Error: cannot implicitly convert expression `5` of type `int` to `string` string x = 5; ^ -fail_compilation/fail_pretty_errors.d(42): Error: mixin `fail_pretty_errors.testMixin2.mixinTemplate!()` error instantiating +fail_compilation/fail_pretty_errors.d(44): Error: mixin `fail_pretty_errors.testMixin2.mixinTemplate!()` error instantiating mixin mixinTemplate; ^ -fail_compilation/fail_pretty_errors.d(48): Error: invalid array operation `"" + ""` (possible missing []) +fail_compilation/fail_pretty_errors.d(50): Error: invalid array operation `"" + ""` (possible missing []) auto x = ""+""; ^ -fail_compilation/fail_pretty_errors.d(48): did you mean to concatenate (`"" ~ ""`) instead ? -fail_compilation/fail_pretty_errors.d(51): Error: cannot implicitly convert expression `1111` of type `int` to `byte` +fail_compilation/fail_pretty_errors.d(50): did you mean to concatenate (`"" ~ ""`) instead ? +fail_compilation/fail_pretty_errors.d(53): Error: cannot implicitly convert expression `1111` of type `int` to `byte` byte ɑ = 1111; ^ --- diff --git a/compiler/test/fail_compilation/failcstuff6.c b/compiler/test/fail_compilation/failcstuff6.c index 88c541ca64..24ea19c81d 100644 --- a/compiler/test/fail_compilation/failcstuff6.c +++ b/compiler/test/fail_compilation/failcstuff6.c @@ -1,7 +1,10 @@ // check dsymbolSemantic analysis of C files /* TEST_OUTPUT: +REQUIRED_ARGS: -verrors=context --- fail_compilation/failcstuff6.c(56): Error: enum member `failcstuff6.test_overflow.boom` initialization with `2147483647+1` causes overflow for type `int` + boom, + ^ --- */