Index: lld/COFF/Driver.cpp =================================================================== --- lld/COFF/Driver.cpp +++ lld/COFF/Driver.cpp @@ -128,6 +128,15 @@ bool WholeArchive) { StringRef Filename = MB->getBufferIdentifier(); + // A file shouldn't be parsed more than once even if it is + // represented in different paths. + for (StringRef Path : FilePaths) { + if (sys::fs::equivalent(Path, Filename)) { + warn(Filename + ": object specified more than once"); + return; + } + } + MemoryBufferRef MBRef = takeBuffer(std::move(MB)); FilePaths.push_back(Filename); @@ -1229,22 +1238,25 @@ if (errorCount()) return; - bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag); + // A predicate returning true if a given path is an argument for + // /wholearchive:, or /wholearchive is enabled globally. + // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj" + // needs to be handled as "/wholearchive:foo.obj foo.obj". + auto IsWholeArchive = [&](StringRef Path) { + if (Args.hasArg(OPT_wholearchive_flag)) + return true; + for (auto *Arg : Args.filtered(OPT_wholearchive_file)) + if (sys::fs::equivalent(Path, Arg->getValue())) + return true; + return false; + }; + // Create a list of input files. Files can be given as arguments // for /defaultlib option. - std::vector MBs; - for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) { - switch (Arg->getOption().getID()) { - case OPT_INPUT: - if (Optional Path = findFile(Arg->getValue())) - enqueuePath(*Path, WholeArchiveFlag); - break; - case OPT_wholearchive_file: - if (Optional Path = findFile(Arg->getValue())) - enqueuePath(*Path, true); - break; - } - } + for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) + if (Optional Path = findFile(Arg->getValue())) + enqueuePath(*Path, IsWholeArchive(Arg->getValue())); + for (auto *Arg : Args.filtered(OPT_defaultlib)) if (Optional Path = findLib(Arg->getValue())) enqueuePath(*Path, false); Index: lld/test/COFF/wholearchive.s =================================================================== --- lld/test/COFF/wholearchive.s +++ lld/test/COFF/wholearchive.s @@ -10,6 +10,14 @@ # RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj -wholearchive %t.archive.lib -implib:%t.lib # RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB +# RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj %t.archive.lib -wholearchive:%t.archive.lib -implib:%t.lib +# RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB + +# RUN: mkdir -p %t.dir +# RUN: cp %t.archive.lib %t.dir/foo.lib +# RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj %t.dir/./foo.lib -wholearchive:%t.dir/foo.lib -implib:%t.lib +# RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB + # CHECK-IMPLIB: Symbol: __imp_exportfn3 # CHECK-IMPLIB: Symbol: exportfn3