Index: ELF/ScriptLexer.h =================================================================== --- ELF/ScriptLexer.h +++ ELF/ScriptLexer.h @@ -24,6 +24,9 @@ explicit ScriptLexer(MemoryBufferRef MB); void setError(const Twine &Msg); + void setErrorContext(const Twine &Msg) { ErrorContext = Msg.str(); } + void dropErrorContext() { ErrorContext.clear(); } + void tokenize(MemoryBufferRef MB); static StringRef skipSpace(StringRef S); bool atEOF(); @@ -39,6 +42,7 @@ std::vector Tokens; bool InExpr = false; size_t Pos = 0; + std::string ErrorContext; private: void maybeSplitExpr(); Index: ELF/ScriptLexer.cpp =================================================================== --- ELF/ScriptLexer.cpp +++ ELF/ScriptLexer.cpp @@ -78,6 +78,9 @@ if (ErrorCount) return; + if (!ErrorContext.empty()) + error(ErrorContext); + if (!Pos) { error(getCurrentLocation() + ": " + Msg); return; Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -604,6 +604,8 @@ } OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { + setErrorContext("unable to parse section definition for output section '" + + OutSec + "':"); OutputSection *Cmd = Script->createOutputSection(OutSec, getCurrentLocation()); @@ -666,6 +668,7 @@ // Consume optional comma following output section command. consume(","); + dropErrorContext(); return Cmd; } Index: test/ELF/linkerscript/operators.s =================================================================== --- test/ELF/linkerscript/operators.s +++ test/ELF/linkerscript/operators.s @@ -90,6 +90,13 @@ # RUN: FileCheck --check-prefix=TERNERR %s # TERNERR: : expected, but got ; +## Broken assignment. +# RUN: echo "SECTIONS { .= 1; }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=ASSIGNERR %s +# ASSIGNERR: unable to parse section definition for output section '.=': +# ASSIGNERR: : expected, but got ; + .globl _start _start: nop