Skip to content

Commit 28d9953

Browse files
committed
[lld/mac] reject -undefined warning and -undefined suppress with -twolevel_namespace
See discussion on https://reviews.llvm.org/D93263 -flat_namespace isn't implemented yet, and neither is -undefined dynamic, so this makes -undefined pretty pointless in lld/MachO for now. But once we implement -flat_namespace (which we need to do anyways to get check-llvm to pass with lld as host linker), the code's already there. Follow-up to https://reviews.llvm.org/D93263#2491865 Differential Revision: https://reviews.llvm.org/D96963
1 parent 559f372 commit 28d9953

File tree

4 files changed

+53
-12
lines changed

4 files changed

+53
-12
lines changed

lld/MachO/Config.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ struct PlatformInfo {
3030
llvm::VersionTuple sdk;
3131
};
3232

33+
enum class NamespaceKind {
34+
twolevel,
35+
flat,
36+
};
37+
3338
enum class UndefinedSymbolTreatment {
3439
unknown,
3540
error,
@@ -61,6 +66,7 @@ struct Configuration {
6166
bool demangle = false;
6267
llvm::MachO::Architecture arch;
6368
PlatformInfo platform;
69+
NamespaceKind namespaceKind = NamespaceKind::twolevel;
6470
UndefinedSymbolTreatment undefinedSymbolTreatment =
6571
UndefinedSymbolTreatment::error;
6672
llvm::MachO::HeaderFileType outputType;

lld/MachO/Driver.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,18 +582,27 @@ static void handlePlatformVersion(const opt::Arg *arg) {
582582

583583
static void handleUndefined(const opt::Arg *arg) {
584584
StringRef treatmentStr = arg->getValue(0);
585-
config->undefinedSymbolTreatment =
585+
auto treatment =
586586
StringSwitch<UndefinedSymbolTreatment>(treatmentStr)
587587
.Case("error", UndefinedSymbolTreatment::error)
588588
.Case("warning", UndefinedSymbolTreatment::warning)
589589
.Case("suppress", UndefinedSymbolTreatment::suppress)
590590
.Case("dynamic_lookup", UndefinedSymbolTreatment::dynamic_lookup)
591591
.Default(UndefinedSymbolTreatment::unknown);
592-
if (config->undefinedSymbolTreatment == UndefinedSymbolTreatment::unknown) {
592+
if (treatment == UndefinedSymbolTreatment::unknown) {
593593
warn(Twine("unknown -undefined TREATMENT '") + treatmentStr +
594594
"', defaulting to 'error'");
595-
config->undefinedSymbolTreatment = UndefinedSymbolTreatment::error;
595+
treatment = UndefinedSymbolTreatment::error;
596+
} else if (config->namespaceKind == NamespaceKind::twolevel &&
597+
(treatment == UndefinedSymbolTreatment::warning ||
598+
treatment == UndefinedSymbolTreatment::suppress)) {
599+
if (treatment == UndefinedSymbolTreatment::warning)
600+
error("'-undefined warning' only valid with '-flat_namespace'");
601+
else
602+
error("'-undefined suppress' only valid with '-flat_namespace'");
603+
treatment = UndefinedSymbolTreatment::error;
596604
}
605+
config->undefinedSymbolTreatment = treatment;
597606
}
598607

599608
static void warnIfDeprecatedOption(const opt::Option &opt) {
@@ -760,6 +769,18 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
760769
if (const opt::Arg *arg = args.getLastArg(OPT_static, OPT_dynamic))
761770
config->staticLink = (arg->getOption().getID() == OPT_static);
762771

772+
if (const opt::Arg *arg =
773+
args.getLastArg(OPT_flat_namespace, OPT_twolevel_namespace)) {
774+
config->namespaceKind = arg->getOption().getID() == OPT_twolevel_namespace
775+
? NamespaceKind::twolevel
776+
: NamespaceKind::flat;
777+
if (config->namespaceKind == NamespaceKind::flat) {
778+
warn("Option '" + arg->getOption().getPrefixedName() +
779+
"' is not yet implemented. Stay tuned...");
780+
config->namespaceKind = NamespaceKind::twolevel;
781+
}
782+
}
783+
763784
config->systemLibraryRoots = getSystemLibraryRoots(args);
764785
config->librarySearchPaths =
765786
getLibrarySearchPaths(args, config->systemLibraryRoots);

lld/MachO/Options.td

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,12 @@ def alias_list : Separate<["-"], "alias_list">,
448448
Flags<[HelpHidden]>,
449449
Group<grp_resolve>;
450450
def flat_namespace : Flag<["-"], "flat_namespace">,
451-
HelpText<"Resolve symbols from all dylibs, both direct & transitive. Do not record source libraries: dyld must re-search at runtime and use the first definition found">,
451+
HelpText<"Resolve symbols from all dylibs, both direct and transitive. Do not record source libraries: dyld must re-search at runtime and use the first definition found">,
452452
Flags<[HelpHidden]>,
453453
Group<grp_resolve>;
454+
def twolevel_namespace : Flag<["-"], "twolevel_namespace">,
455+
HelpText<"Make dyld look up symbols by (dylib,name) pairs (default)">,
456+
Group<grp_resolve>;
454457
def u : Separate<["-"], "u">,
455458
MetaVarName<"<symbol>">,
456459
HelpText<"Require that <symbol> be defined for the link to succeed">,
@@ -1302,10 +1305,6 @@ def threaded_starts_section : Flag<["-"], "threaded_starts_section">,
13021305
HelpText<"This option is undocumented in ld64">,
13031306
Flags<[HelpHidden]>,
13041307
Group<grp_undocumented>;
1305-
def twolevel_namespace : Flag<["-"], "twolevel_namespace">,
1306-
HelpText<"This option is undocumented in ld64">,
1307-
Flags<[HelpHidden]>,
1308-
Group<grp_undocumented>;
13091308
def verbose_optimization_hints : Flag<["-"], "verbose_optimization_hints">,
13101309
HelpText<"This option is undocumented in ld64">,
13111310
Flags<[HelpHidden]>,

lld/test/MachO/treat-undef-sym.s

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,29 @@
55
# RUN: FileCheck %s -check-prefix=UNKNOWN
66
# RUN: not %lld -undefined error -o /dev/null %t.o 2>&1 | \
77
# RUN: FileCheck %s -check-prefix=ERROR
8-
# RUN: %no_fatal_warnings_lld -undefined warning -o /dev/null %t.o 2>&1 | \
9-
# RUN: FileCheck %s -check-prefix=WARNING
10-
# RUN: %lld -undefined suppress -o /dev/null %t.o 2>&1 | \
11-
# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
8+
9+
# RUN: not %lld -undefined warning -o /dev/null %t.o 2>&1 | \
10+
# RUN: FileCheck %s -check-prefix=INVAL-WARNING
11+
# RUN: not %lld -undefined suppress -o /dev/null %t.o 2>&1 | \
12+
# RUN: FileCheck %s -check-prefix=INVAL-SUPPRESS
13+
14+
# FIXME: Enable these -undefined checks once -flat_namespace is implemented.
15+
# RN: %no_fatal_warnings_lld -flat_namespace -undefined warning \
16+
# RN: -o /dev/null %t.o 2>&1 | \
17+
# RN: FileCheck %s -check-prefix=WARNING
18+
# RN: %lld -flat_namespace -undefined suppress -o /dev/null %t.o 2>&1 | \
19+
# RN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
1220

1321
# ERROR: error: undefined symbol: _bar
1422
# ERROR-NEXT: >>> referenced by
1523

24+
# INVAL-WARNING: error: '-undefined warning' only valid with '-flat_namespace'
25+
# INVAL-WARNING-NEXT: error: undefined symbol: _bar
26+
27+
# INVAL-SUPPRESS: error: '-undefined suppress' only valid with '-flat_namespace'
28+
# INVAL-SUPPRESS-NEXT: error: undefined symbol: _bar
29+
30+
1631
# WARNING: warning: undefined symbol: _bar
1732
# WARNING-NEXT: >>> referenced by
1833

0 commit comments

Comments
 (0)