Index: lld/ELF/Relocations.cpp =================================================================== --- lld/ELF/Relocations.cpp +++ lld/ELF/Relocations.cpp @@ -705,27 +705,18 @@ return Msg; } -// Report an undefined symbol if necessary. -// Returns true if this function printed out an error message. -template -static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, - uint64_t Offset) { - if (!Sym.isUndefined() || Sym.isWeak()) - return false; - - bool CanBeExternal = !Sym.isLocal() && Sym.computeBinding() != STB_LOCAL && - Sym.Visibility == STV_DEFAULT; - if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) - return false; +struct UndefinedDiag { + Symbol *Sym; + InputSectionBase *Sec; + uint64_t Offset; + bool IsWarning; +}; - // clang (as of 2019-06-12) / gcc (as of 8.2.1) PPC64 may emit a .rela.toc - // which references a switch table in a discarded .rodata/.text section. The - // .toc and the .rela.toc are incorrectly not placed in the comdat. The ELF - // spec says references from outside the group to a STB_LOCAL symbol are not - // allowed. Work around the bug. - if (Config->EMachine == EM_PPC64 && - cast(Sym).DiscardedSecIdx != 0 && Sec.Name == ".toc") - return false; +template +static void reportUndefinedSymbol(const UndefinedDiag &Undef) { + Symbol &Sym = *Undef.Sym; + InputSectionBase &Sec = *Undef.Sec; + uint64_t Offset = Undef.Offset; auto Visibility = [&]() -> std::string { switch (Sym.Visibility) { @@ -754,14 +745,41 @@ Msg += "\nthe vtable symbol may be undefined because the class is missing " "its key function (see https://lld.llvm.org/missingkeyfunction)"; - if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) || - Config->NoinhibitExec) { + if (Undef.IsWarning) warn(Msg); + else + error(Msg); +} + +// Report an undefined symbol if necessary. +// Returns true if this function printed out an error message. +template +static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, + uint64_t Offset) { + if (!Sym.isUndefined() || Sym.isWeak()) return false; - } - error(Msg); - return true; + bool CanBeExternal = !Sym.isLocal() && Sym.computeBinding() != STB_LOCAL && + Sym.Visibility == STV_DEFAULT; + if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) + return false; + + // clang (as of 2019-06-12) / gcc (as of 8.2.1) PPC64 may emit a .rela.toc + // which references a switch table in a discarded .rodata/.text section. The + // .toc and the .rela.toc are incorrectly not placed in the comdat. The ELF + // spec says references from outside the group to a STB_LOCAL symbol are not + // allowed. Work around the bug. + if (Config->EMachine == EM_PPC64 && + cast(Sym).DiscardedSecIdx != 0 && Sec.Name == ".toc") + return false; + + + UndefinedDiag Undef = { &Sym, &Sec, Offset, /*IsWarning=*/false }; + if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) || + Config->NoinhibitExec) + Undef.IsWarning = true; + reportUndefinedSymbol(Undef); + return !Undef.IsWarning; } // MIPS N32 ABI treats series of successive relocations with the same offset