Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -1177,6 +1177,8 @@ // Make sure we have resolved all symbols. Symtab->reportRemainingUndefines(); + if (ErrorCount) + return; // Windows specific -- if no /subsystem is given, we need to infer // that from entry point name. Index: lld/trunk/COFF/SymbolTable.cpp =================================================================== --- lld/trunk/COFF/SymbolTable.cpp +++ lld/trunk/COFF/SymbolTable.cpp @@ -84,8 +84,16 @@ Driver->parseDirectives(S); } +static void errorOrWarn(const Twine &S) { + if (Config->Force) + warn(S); + else + error(S); +} + void SymbolTable::reportRemainingUndefines() { SmallPtrSet Undefs; + for (auto &I : Symtab) { Symbol *Sym = I.second; auto *Undef = dyn_cast(Sym->body()); @@ -93,7 +101,9 @@ continue; if (!Sym->IsUsedInRegularObj) continue; + StringRef Name = Undef->getName(); + // A weak alias may have been resolved, so check for that. if (Defined *D = Undef->getWeakAlias()) { // We resolve weak aliases by replacing the alias's SymbolBody with the @@ -112,6 +122,7 @@ Sym->Body = D->symbol()->Body; continue; } + // If we can resolve a symbol by removing __imp_ prefix, do that. // This odd rule is for compatibility with MSVC linker. if (Name.startswith("__imp_")) { @@ -124,23 +135,25 @@ continue; } } + // Remaining undefined symbols are not fatal if /force is specified. // They are replaced with dummy defined symbols. if (Config->Force) replaceBody(Sym, Name, 0); Undefs.insert(Sym->body()); } + if (Undefs.empty()) return; + for (SymbolBody *B : Config->GCRoot) if (Undefs.count(B)) - warn(": undefined symbol: " + B->getName()); + errorOrWarn(": undefined symbol: " + B->getName()); + for (ObjFile *File : ObjFile::Instances) for (SymbolBody *Sym : File->getSymbols()) if (Undefs.count(Sym)) - warn(toString(File) + ": undefined symbol: " + Sym->getName()); - if (!Config->Force) - fatal("link failed"); + errorOrWarn(toString(File) + ": undefined symbol: " + Sym->getName()); } std::pair SymbolTable::insert(StringRef Name) { Index: lld/trunk/test/COFF/entry-inference.test =================================================================== --- lld/trunk/test/COFF/entry-inference.test +++ lld/trunk/test/COFF/entry-inference.test @@ -14,10 +14,10 @@ # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 # RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log -# MAIN: : undefined symbol: mainCRTStartup -# WMAIN: : undefined symbol: wmainCRTStartup -# WINMAIN: : undefined symbol: WinMainCRTStartup -# WWINMAIN: : undefined symbol: wWinMainCRTStartup +# MAIN: error: : undefined symbol: mainCRTStartup +# WMAIN: error: : undefined symbol: wmainCRTStartup +# WINMAIN: error: : undefined symbol: WinMainCRTStartup +# WWINMAIN: error: : undefined symbol: wWinMainCRTStartup --- !COFF header: Index: lld/trunk/test/COFF/force.test =================================================================== --- lld/trunk/test/COFF/force.test +++ lld/trunk/test/COFF/force.test @@ -1,10 +1,11 @@ # RUN: yaml2obj < %s > %t.obj # RUN: not lld-link /out:%t.exe /entry:main %t.obj >& %t.log -# RUN: FileCheck %s < %t.log +# RUN: FileCheck -check-prefix=ERROR %s < %t.log # RUN: lld-link /out:%t.exe /entry:main %t.obj /force >& %t.log -# RUN: FileCheck %s < %t.log +# RUN: FileCheck -check-prefix=WARN %s < %t.log -# CHECK: .obj: undefined symbol: foo +# ERROR: error: {{.*}}.obj: undefined symbol: foo +# WARN: warning: {{.*}}.obj: undefined symbol: foo --- !COFF header: Index: lld/trunk/test/COFF/nodefaultlib.test =================================================================== --- lld/trunk/test/COFF/nodefaultlib.test +++ lld/trunk/test/COFF/nodefaultlib.test @@ -19,9 +19,9 @@ # RUN: /nodefaultlib:std64.lib >& %t.log || true # RUN: FileCheck -check-prefix=CHECK3 %s < %t.log -CHECK1: hello64.obj: {{[Nn]}}o such file or directory -CHECK2: hello64: {{[Nn]}}o such file or directory -CHECK3: hello64.obj: undefined symbol: MessageBoxA +CHECK1: error: could not open hello64.obj: {{[Nn]}}o such file or directory +CHECK2: error: could not open hello64: {{[Nn]}}o such file or directory +CHECK3: error: {{.*}}hello64.obj: undefined symbol: MessageBoxA # RUN: lld-link /libpath:%T /out:%t.exe /entry:main \ # RUN: /subsystem:console hello64.obj /defaultlib:std64.lib