Skip to content

Commit d5a4244

Browse files
committed
[clang][driver] Special care for -l and -Wl, flags in config files
Currently, if a -l (or -Wl,) flag is added into a config file (e.g. clang.cfg), it is situated before any object file in the effective command line. If the library requested by given -l flag is static, its symbols will not be made visible to any of the object files provided by the user. Also, the presence of any of the linker flags in a config file confuses the driver whenever the user invokes clang without any parameters. This patch solves both of those problems, by moving the -l and -Wl, flags specified in a config file to the end of the input list, and by discarding them when there are no other inputs provided by the user, or the last phase is not the linking phase.
1 parent deab4e9 commit d5a4244

File tree

6 files changed

+102
-0
lines changed

6 files changed

+102
-0
lines changed

clang/include/clang/Driver/Driver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ class Driver {
297297
/// Object that stores strings read from configuration file.
298298
llvm::StringSaver Saver;
299299

300+
/// Linker inputs originated from configuration file.
301+
std::unique_ptr<llvm::opt::InputArgList> CfgLinkerInputs;
302+
300303
/// Arguments originated from configuration file.
301304
std::unique_ptr<llvm::opt::InputArgList> CfgOptions;
302305

clang/lib/Driver/Driver.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,16 @@ bool Driver::readConfigFile(StringRef FileName,
10621062
for (Arg *A : *NewOptions)
10631063
A->claim();
10641064

1065+
std::unique_ptr<InputArgList> NewLinkerIns = std::make_unique<InputArgList>();
1066+
for (Arg *A : NewOptions->filtered(options::OPT_Wl_COMMA, options::OPT_l)) {
1067+
const Arg *BaseArg = &A->getBaseArg();
1068+
if (BaseArg == A)
1069+
BaseArg = nullptr;
1070+
appendOneArg(*NewLinkerIns, A, BaseArg);
1071+
}
1072+
NewOptions->eraseArg(options::OPT_Wl_COMMA);
1073+
NewOptions->eraseArg(options::OPT_l);
1074+
10651075
if (!CfgOptions)
10661076
CfgOptions = std::move(NewOptions);
10671077
else {
@@ -1073,6 +1083,19 @@ bool Driver::readConfigFile(StringRef FileName,
10731083
appendOneArg(*CfgOptions, Opt, BaseArg);
10741084
}
10751085
}
1086+
1087+
if (!CfgLinkerInputs)
1088+
CfgLinkerInputs = std::move(NewLinkerIns);
1089+
else {
1090+
// If this is a subsequent config file, append options to the previous one.
1091+
for (auto *Opt : *NewLinkerIns) {
1092+
const Arg *BaseArg = &Opt->getBaseArg();
1093+
if (BaseArg == Opt)
1094+
BaseArg = nullptr;
1095+
appendOneArg(*CfgLinkerInputs, Opt, BaseArg);
1096+
}
1097+
}
1098+
10761099
ConfigFiles.push_back(std::string(CfgFileName));
10771100
return false;
10781101
}
@@ -1250,6 +1273,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
12501273
if (!ContainsError)
12511274
ContainsError = loadConfigFiles();
12521275
bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
1276+
bool HasConfigLinkerIn = !ContainsError && (CfgLinkerInputs.get() != nullptr);
12531277

12541278
// All arguments, from both config file and command line.
12551279
InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
@@ -1552,6 +1576,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
15521576
// Construct the list of inputs.
15531577
InputList Inputs;
15541578
BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
1579+
if (HasConfigLinkerIn && Inputs.size()) {
1580+
Arg *FinalPhaseArg;
1581+
if (getFinalPhase(*TranslatedArgs, &FinalPhaseArg) == phases::Link) {
1582+
DerivedArgList TranslatedLinkerIns(*CfgLinkerInputs);
1583+
for (Arg *A : *CfgLinkerInputs)
1584+
TranslatedLinkerIns.append(A);
1585+
BuildInputs(C->getDefaultToolChain(), TranslatedLinkerIns, Inputs);
1586+
}
1587+
}
15551588

15561589
// Populate the tool chains for the offloading devices, if any.
15571590
CreateOffloadingDeviceToolChains(*C, Inputs);

clang/test/Driver/Inputs/config-l.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Wall -lm -Wl,-Bstatic -lhappy -Wl,-Bdynamic

clang/test/Driver/config-file.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,35 @@
8282
// CHECK-TWO-CONFIGS: -isysroot
8383
// CHECK-TWO-CONFIGS-SAME: /opt/data
8484
// CHECK-TWO-CONFIGS-SAME: -Wall
85+
86+
//--- The linker input flags should be moved to the end of input list and appear only when linking.
87+
// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -o %s.out %s -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING
88+
// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp -o %s.out %s -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-LIBOMP-GOES-LAST
89+
// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING
90+
// RUN: %clang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING
91+
// RUN: %clang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg -o %s.out %s -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-MSVC
92+
// RUN: %clang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-MSVC
93+
// CHECK-LINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
94+
// CHECK-LINKING: "-Wall"
95+
// CHECK-LINKING: "{{.*}}-{{.*}}.o" "-lm" "-Bstatic" "-lhappy" "-Bdynamic"
96+
// CHECK-LINKING-LIBOMP-GOES-LAST: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
97+
// CHECK-LINKING-LIBOMP-GOES-LAST: "-Wall"
98+
// CHECK-LINKING-LIBOMP-GOES-LAST-SAME: "-fopenmp"
99+
// CHECK-LINKING-LIBOMP-GOES-LAST: "{{.*}}-{{.*}}.o" "-lm" "-Bstatic" "-lhappy" "-Bdynamic"
100+
// CHECK-LINKING-LIBOMP-GOES-LAST-SAME: "-lomp"
101+
// CHECK-NOLINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
102+
// CHECK-NOLINKING: "-Wall"
103+
// CHECK-NOLINKING-NO: "-lm"
104+
// CHECK-NOLINKING-NO: "-Bstatic"
105+
// CHECK-NOLINKING-NO: "-lhappy"
106+
// CHECK-NOLINKING-NO: "-Bdynamic"
107+
// CHECK-NOLINKING-NO: "-lomp"
108+
// CHECK-LINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
109+
// CHECK-LINKING-MSVC: "-Wall"
110+
// CHECK-LINKING-MSVC: "{{.*}}-{{.*}}.o" "m.lib" "-Bstatic" "happy.lib" "-Bdynamic"
111+
// CHECK-NOLINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
112+
// CHECK-NOLINKING-MSVC: "-Wall"
113+
// CHECK-NOLINKING-MSVC-NO: "m.lib"
114+
// CHECK-NOLINKING-MSVC-NO: "-Bstatic"
115+
// CHECK-NOLINKING-MSVC-NO: "happy.lib"
116+
// CHECK-NOLINKING-MSVC-NO: "-Bdynamic"

flang/test/Driver/Inputs/config-l.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-ffast-math -lm -Wl,-Bstatic -lhappy -Wl,-Bdynamic

flang/test/Driver/config-file.f90

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,35 @@
6161
! CHECK-TWO-CONFIGS-NEXT: Configuration file: {{.*}}Inputs{{.}}config2{{.}}config-4.cfg
6262
! CHECK-TWO-CONFIGS: -ffp-contract=fast
6363
! CHECK-TWO-CONFIGS: -O3
64+
65+
!--- The linker input flags should be moved to the end of input list and appear only when linking.
66+
! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -o %s.out %s -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING
67+
! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp -o %s.out %s -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-LIBOMP-GOES-LAST
68+
! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING
69+
! RUN: %flang --target=aarch64-unknown-linux-gnu --config %S/Inputs/config-l.cfg -fopenmp -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING
70+
! RUN: %flang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg -o %s.out %s -### 2>&1 | FileCheck %s -check-prefix CHECK-LINKING-MSVC
71+
! RUN: %flang --target=x86_64-pc-windows-msvc --config %S/Inputs/config-l.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NOLINKING-MSVC
72+
! CHECK-LINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
73+
! CHECK-LINKING: "-ffast-math"
74+
! CHECK-LINKING: "{{.*}}-{{.*}}.o" "-lm" "-Bstatic" "-lhappy" "-Bdynamic"
75+
! CHECK-LINKING-LIBOMP-GOES-LAST: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
76+
! CHECK-LINKING-LIBOMP-GOES-LAST: "-ffast-math"
77+
! CHECK-LINKING-LIBOMP-GOES-LAST-SAME: "-fopenmp"
78+
! CHECK-LINKING-LIBOMP-GOES-LAST: "{{.*}}-{{.*}}.o" "-lm" "-Bstatic" "-lhappy" "-Bdynamic"
79+
! CHECK-LINKING-LIBOMP-GOES-LAST-SAME: "-lomp"
80+
! CHECK-NOLINKING: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
81+
! CHECK-NOLINKING: "-ffast-math"
82+
! CHECK-NOLINKING-NO: "-lm"
83+
! CHECK-NOLINKING-NO: "-Bstatic"
84+
! CHECK-NOLINKING-NO: "-lhappy"
85+
! CHECK-NOLINKING-NO: "-Bdynamic"
86+
! CHECK-NOLINKING-NO: "-lomp"
87+
! CHECK-LINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
88+
! CHECK-LINKING-MSVC: "-ffast-math"
89+
! CHECK-LINKING-MSVC: "{{.*}}-{{.*}}.o" "m.lib" "-Bstatic" "happy.lib" "-Bdynamic"
90+
! CHECK-NOLINKING-MSVC: Configuration file: {{.*}}Inputs{{.}}config-l.cfg
91+
! CHECK-NOLINKING-MSVC: "-ffast-math"
92+
! CHECK-NOLINKING-MSVC-NO: "m.lib"
93+
! CHECK-NOLINKING-MSVC-NO: "-Bstatic"
94+
! CHECK-NOLINKING-MSVC-NO: "happy.lib"
95+
! CHECK-NOLINKING-MSVC-NO: "-Bdynamic"

0 commit comments

Comments
 (0)