Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -242,6 +242,8 @@ MemoryBufferRef getMember(const Archive::Symbol *Sym); private: + void maybeWarnOnEmptyArchive(); + std::unique_ptr File; llvm::DenseSet Seen; }; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -35,6 +35,11 @@ std::vector InputFile::Pool; +static bool isBitcode(MemoryBufferRef MB) { + using namespace sys::fs; + return identify_magic(MB.getBuffer()) == file_magic::bitcode; +} + // Deletes all InputFile instances created so far. void InputFile::freePool() { // Files are freed in reverse order so that files created @@ -424,19 +429,11 @@ template void ArchiveFile::parse() { File = check(Archive::create(MB), "failed to parse archive"); + maybeWarnOnEmptyArchive(); // Read the symbol table to construct Lazy objects. - bool IsEmpty = true; - for (const Archive::Symbol &Sym : File->symbols()) { + for (const Archive::Symbol &Sym : File->symbols()) Symtab::X->addLazyArchive(this, Sym); - IsEmpty = false; - } - - if (IsEmpty) - warn(getName() + " has no symbol. Chances are you are doing " - "an LTO build and forgot to use an ar command that can create " - "a symbol table for LLVM bitcode files. If so, use llvm-ar or " - "GNU ar + plugin."); } // Returns a buffer pointing to a member file containing a given symbol. @@ -460,6 +457,27 @@ return Ret; } +// Checks for a common usage error of ar command. This is purely optional. +// This function doesn't affect the program's behavior. +void ArchiveFile::maybeWarnOnEmptyArchive() { + if (File->symbols().begin() != File->symbols().end()) + return; + + Error Err; + for (const ErrorOr &COrErr : File->children(Err)) { + Archive::Child C = check(COrErr); + if (!isBitcode(check(C.getMemoryBufferRef()))) + return; + } + if (Err) + Error(Err); + + warn(getName() + " has no symbol." + " Chances are you are doing an LTO build and forgot to use an ar" + " command that can create a symbol table for LLVM bitcode files." + " If so, use llvm-ar or GNU ar + plugin."); +} + template SharedFile::SharedFile(MemoryBufferRef M) : ELFFileBase(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {} @@ -767,11 +785,6 @@ StringRef((char *)ELFData.data(), Size), MB.getBufferIdentifier())); } -static bool isBitcode(MemoryBufferRef MB) { - using namespace sys::fs; - return identify_magic(MB.getBuffer()) == file_magic::bitcode; -} - InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName) { InputFile *F = isBitcode(MB) ? new BitcodeFile(MB) : createELFFile(MB); Index: test/ELF/empty-archive.s =================================================================== --- test/ELF/empty-archive.s +++ test/ELF/empty-archive.s @@ -1,5 +1,3 @@ // RUN: llvm-ar rc %t.a // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -// RUN: ld.lld -shared %t.o %t.a -o t 2>&1 | FileCheck %s - -// CHECK: has no symbol. +// RUN: ld.lld -shared %t.o %t.a -o t Index: test/ELF/lto/archive.ll =================================================================== --- test/ELF/lto/archive.ll +++ test/ELF/lto/archive.ll @@ -8,6 +8,9 @@ ; RUN: ld.lld -m elf_x86_64 %t2.o --whole-archive %t.a -o %t3 -shared ; RUN: llvm-readobj -t %t3 | FileCheck %s +; RUN: llvm-ar rcS %t4.a %t1.o +; RUN: ld.lld -m elf_x86_64 %t2.o %t4.a -o %t3 -shared 2>&1 \ +; RUN: | FileCheck -check-prefix=WARN %s ; CHECK: Name: g ( ; CHECK-NEXT: Value: @@ -25,6 +28,8 @@ ; CHECK-NEXT: Other: 0 ; CHECK-NEXT: Section: .text +; WARN: has no symbol. + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu"