Index: lld/MachO/SymbolTable.cpp =================================================================== --- lld/MachO/SymbolTable.cpp +++ lld/MachO/SymbolTable.cpp @@ -174,24 +174,23 @@ } void lld::macho::treatUndefinedSymbol(const Undefined &sym) { - std::string message = "undefined symbol: " + toString(sym); - std::string fileName = toString(sym.getFile()); - - if (!fileName.empty()) - message += "\n>>> referenced by " + fileName; + auto message = [](const Undefined &sym) { + std::string message = "undefined symbol: " + toString(sym); + std::string fileName = toString(sym.getFile()); + if (!fileName.empty()) + message += "\n>>> referenced by " + fileName; + return message; + }; switch (config->undefinedSymbolTreatment) { - case UndefinedSymbolTreatment::suppress: - error("-undefined suppress unimplemented"); - break; case UndefinedSymbolTreatment::error: - error(message); + error(message(sym)); break; case UndefinedSymbolTreatment::warning: - warn(message); - error("-undefined warning unimplemented"); - break; + warn(message(sym)); + LLVM_FALLTHROUGH; case UndefinedSymbolTreatment::dynamic_lookup: - error("dynamic_lookup unimplemented for " + message); + case UndefinedSymbolTreatment::suppress: + symtab->addDynamicLookup(sym.getName()); break; case UndefinedSymbolTreatment::unknown: llvm_unreachable("unknown -undefined TREATMENT"); Index: lld/MachO/UnwindInfoSection.cpp =================================================================== --- lld/MachO/UnwindInfoSection.cpp +++ lld/MachO/UnwindInfoSection.cpp @@ -121,7 +121,9 @@ if (auto *s = r.referent.dyn_cast()) { if (auto *undefined = dyn_cast(s)) { treatUndefinedSymbol(*undefined); - continue; + // treatUndefinedSymbol() can replace s with a DylibSymbol, re-check. + if (isa(s)) + continue; } if (auto *defined = dyn_cast(s)) { // Check if we have created a synthetic symbol at the same address. Index: lld/MachO/Writer.cpp =================================================================== --- lld/MachO/Writer.cpp +++ lld/MachO/Writer.cpp @@ -462,7 +462,9 @@ if (auto *sym = r.referent.dyn_cast()) { if (auto *undefined = dyn_cast(sym)) treatUndefinedSymbol(*undefined); - else if (target->validateSymbolRelocation(sym, isec, r)) + // treatUndefinedSymbol() can replace sym with a DylibSymbol, re-check. + if (!isa(sym) && + target->validateSymbolRelocation(sym, isec, r)) prepareSymbolRelocation(sym, isec, r); } else { assert(r.referent.is()); Index: lld/test/MachO/treat-undef-sym.s =================================================================== --- lld/test/MachO/treat-undef-sym.s +++ lld/test/MachO/treat-undef-sym.s @@ -10,13 +10,24 @@ # RUN: FileCheck %s -check-prefix=INVAL-WARNING # RUN: not %lld -undefined suppress -o /dev/null %t.o 2>&1 | \ # RUN: FileCheck %s -check-prefix=INVAL-SUPPRESS - -# FIXME: Enable these -undefined checks once -flat_namespace is implemented. -# RN: %no_fatal_warnings_lld -flat_namespace -undefined warning \ -# RN: -o /dev/null %t.o 2>&1 | \ -# RN: FileCheck %s -check-prefix=WARNING -# RN: %lld -flat_namespace -undefined suppress -o /dev/null %t.o 2>&1 | \ -# RN: FileCheck %s -check-prefix=SUPPRESS --allow-empty +# RUN: %lld -undefined dynamic_lookup -lSystem -o %t.out %t.o 2>&1 | \ +# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty +# RUN: llvm-objdump --macho --lazy-bind %t.out \ +# RUN: | FileCheck --check-prefix=BIND %s + +# RUN: %no_fatal_warnings_lld -lSystem -flat_namespace -undefined warning \ +# RUN: -o %t.out %t.o 2>&1 | \ +# RUN: FileCheck %s -check-prefix=WARNING +# RUN: llvm-objdump --macho --lazy-bind %t.out \ +# RUN: | FileCheck --check-prefix=BIND %s +# RUN: %lld -flat_namespace -lSystem -undefined suppress -o %t.out %t.o 2>&1 | \ +# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty +# RUN: llvm-objdump --macho --lazy-bind %t.out \ +# RUN: | FileCheck --check-prefix=BIND %s +# RUN: %lld -flat_namespace -lSystem -undefined dynamic_lookup -o %t.out %t.o 2>&1 | \ +# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty +# RUN: llvm-objdump --macho --lazy-bind %t.out \ +# RUN: | FileCheck --check-prefix=BIND %s # ERROR: error: undefined symbol: _bar # ERROR-NEXT: >>> referenced by @@ -27,7 +38,6 @@ # INVAL-SUPPRESS: error: '-undefined suppress' only valid with '-flat_namespace' # INVAL-SUPPRESS-NEXT: error: undefined symbol: _bar - # WARNING: warning: undefined symbol: _bar # WARNING-NEXT: >>> referenced by @@ -37,6 +47,9 @@ # UNKNOWN-NEXT: error: undefined symbol: _bar # UNKNOWN-NEXT: >>> referenced by +# BIND: Lazy bind table: +# BIND: __DATA __la_symbol_ptr 0x{{[0-9a-f]*}} flat-namespace _bar + .globl _main _main: callq _bar