Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -757,11 +757,21 @@ // clutter the output. // We instead remove trivially empty sections. The bfd linker seems even // more aggressive at removing them. - llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { - if (auto *Sec = dyn_cast(Base)) - return !Sec->Live; - return false; - }); + for (BaseCommand *& Cmd : SectionCommands) { + auto *Sec = dyn_cast(Cmd); + if (!Sec || Sec->Live) + continue; + + // If section had address or align expressions we want to check them were + // calculatable before we remove the section. Otherwise if any expression + // contains undefined symbol, we would not report the proper error. + for (const Expr &Expression : {Sec->AddrExpr, Sec->AlignExpr, Sec->LMAExpr}) + if (Expression) + Expression(); + Cmd = nullptr; + } + + llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { return !Base; }); } static bool isAllSectionDescription(const OutputSection &Cmd) { Index: test/ELF/linkerscript/address-expr-symbols.s =================================================================== --- test/ELF/linkerscript/address-expr-symbols.s +++ test/ELF/linkerscript/address-expr-symbols.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { .bar (a+b) : AT(d) ALIGN(c) { } };" > %t.script +# RUN: not ld.lld -o %t --script %t.script %t.o 2>&1 | FileCheck %s + +# CHECK-DAG: symbol not found: a +# CHECK-DAG: symbol not found: b +# CHECK-DAG: symbol not found: c +# CHECK-DAG: symbol not found: d + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { .bar (a+b) : SUBALIGN(c) { } };" > %t.script +# RUN: not ld.lld -o %t --script %t.script %t.o 2>&1 \ +# RUN: | FileCheck %s --check-prefix=SUBALIGN +# SUBALIGN: symbol not found: c