Index: COFF/Config.h =================================================================== --- COFF/Config.h +++ COFF/Config.h @@ -94,7 +94,8 @@ bool DoICF = true; bool TailMerge; bool Relocatable = true; - bool Force = false; + bool ForceMultiple = false; + bool ForceUnresolved = false; bool Debug = false; bool DebugDwarf = false; bool DebugGHashes = false; Index: COFF/Driver.cpp =================================================================== --- COFF/Driver.cpp +++ COFF/Driver.cpp @@ -888,7 +888,11 @@ // Handle /force or /force:unresolved if (Args.hasArg(OPT_force, OPT_force_unresolved)) - Config->Force = true; + Config->ForceUnresolved = true; + + // Handle /force or /force:multiple + if (Args.hasArg(OPT_force, OPT_force_multiple)) + Config->ForceMultiple = true; // Handle /debug if (Args.hasArg(OPT_debug, OPT_debug_dwarf, OPT_debug_ghash)) { Index: COFF/Options.td =================================================================== --- COFF/Options.td +++ COFF/Options.td @@ -99,8 +99,11 @@ def wholearchive_flag : F<"wholearchive">; def force : F<"force">, + HelpText<"Allow undefined and multiply defined symbols when creating executables">; +def force_unresolved : F<"force:unresolved">, HelpText<"Allow undefined symbols when creating executables">; -def force_unresolved : F<"force:unresolved">; +def force_multiple : F<"force:multiple">, + HelpText<"Allow multiply defined symbols when creating executables">; defm WX : B<"WX", "Treat warnings as errors", "Don't treat warnings as errors">; defm allowbind : B<"allowbind", "Enable DLL binding (default)", Index: COFF/SymbolTable.cpp =================================================================== --- COFF/SymbolTable.cpp +++ COFF/SymbolTable.cpp @@ -60,7 +60,7 @@ } static void errorOrWarn(const Twine &S) { - if (Config->Force) + if (Config->ForceUnresolved) warn(S); else error(S); @@ -237,7 +237,7 @@ // Remaining undefined symbols are not fatal if /force is specified. // They are replaced with dummy defined symbols. - if (Config->Force) + if (Config->ForceUnresolved) replaceSymbol(Sym, Name, 0); Undefs.insert(Sym); } @@ -326,8 +326,14 @@ } void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) { - error("duplicate symbol: " + toString(*Existing) + " in " + - toString(Existing->getFile()) + " and in " + toString(NewFile)); + std::string Msg = "duplicate symbol: " + toString(*Existing) + " in " + + toString(Existing->getFile()) + " and in " + + toString(NewFile); + + if (Config->ForceMultiple) + warn(Msg); + else + error(Msg); } Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { Index: test/COFF/force-multiple.test =================================================================== --- test/COFF/force-multiple.test +++ test/COFF/force-multiple.test @@ -0,0 +1,45 @@ +# RUN: yaml2obj < %s > %t1.obj +# RUN: yaml2obj < %s > %t2.obj + +# RUN: not lld-link /out:%t.exe /entry:main %t1.obj %t2.obj >& %t.log +# RUN: FileCheck -check-prefix=ERROR %s < %t.log + +# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.obj /force >& %t.log +# RUN: FileCheck -check-prefix=WARN %s < %t.log + +# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.obj /force:multiple >& %t.log +# RUN: FileCheck -check-prefix=WARN %s < %t.log + +# ERROR: error: duplicate symbol: main + +# WARN: warning: duplicate symbol: main + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 000000000000 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 6 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +...