Index: lld/trunk/ELF/SymbolTable.h =================================================================== --- lld/trunk/ELF/SymbolTable.h +++ lld/trunk/ELF/SymbolTable.h @@ -108,7 +108,7 @@ llvm::DenseSet ComdatGroups; // Set of .so files to not link the same shared object file more than once. - llvm::DenseSet SoNames; + llvm::DenseMap SoNames; // A map from demangled symbol names to their symbol objects. // This mapping is 1:N because two symbols with different versions Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -94,8 +94,20 @@ if (auto *F = dyn_cast>(File)) { // DSOs are uniquified not by filename but by soname. F->parseSoName(); - if (errorCount() || !SoNames.insert(F->SoName).second) + if (errorCount()) return; + + // If a DSO appears more than once on the command line with and without + // --as-needed, --no-as-needed takes precedence over --as-needed because a + // user can add an extra DSO with --no-as-needed to force it to be added to + // the dependency list. + DenseMap::iterator It; + bool WasInserted; + std::tie(It, WasInserted) = SoNames.try_emplace(F->SoName, F); + cast>(It->second)->IsNeeded |= F->IsNeeded; + if (!WasInserted) + return; + SharedFiles.push_back(F); F->parseRest(); return; Index: lld/trunk/test/ELF/as-needed-not-in-regular.s =================================================================== --- lld/trunk/test/ELF/as-needed-not-in-regular.s +++ lld/trunk/test/ELF/as-needed-not-in-regular.s @@ -19,6 +19,12 @@ # the reference to a2 is weak, don't add a DT_NEEDED entry for a.so. # CHECK-NOT: a.so +# RUN: ld.lld %t.o %tb.so --as-needed %ta.so --no-as-needed %ta.so -o %t +# RUN: llvm-readelf -d %t | FileCheck %s -check-prefix=NEEDED + +# a.so is needed because one of its occurrences is needed. +# NEEDED: a.so + .global _start .weak a2 _start: