Skip to content

Commit 88f3fb1

Browse files
committed
Added support for expanding response files in clang_Driver_getExternalActionsForCommand_v0.
This is necessary because build systems like SwiftBuild may pass arguments to the Clang driver via response files. Without this, the response files are treated as inputs and passed along to the external actions themselves, which is incorrect. This resolves swiftlang#10441.
1 parent 4a74a45 commit 88f3fb1

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

clang/tools/libclang/Driver.cpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,29 @@ clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV,
4040
if (ArgC < 1)
4141
return nullptr;
4242

43-
CXDiagnosticSetDiagnosticConsumer DiagConsumer;
44-
auto DiagOpts = CreateAndPopulateDiagOpts(ArrayRef(ArgV, ArgC));
45-
4643
// Use createPhysicalFileSystem instead of getRealFileSystem so that
4744
// setCurrentWorkingDirectory doesn't change the working directory of the
4845
// process.
4946
std::unique_ptr<llvm::vfs::FileSystem> VFS =
5047
llvm::vfs::createPhysicalFileSystem();
5148

49+
CXDiagnosticSetDiagnosticConsumer DiagConsumer;
50+
51+
SmallVector<const char *, 256> Args(ArgV, ArgV + ArgC);
52+
llvm::BumpPtrAllocator Alloc;
53+
if (llvm::Error E =
54+
driver::expandResponseFiles(Args, /*CLMode=*/false, Alloc)) {
55+
// Construct a default DiagnosticOptions to use to emit the failure.
56+
DiagnosticOptions DiagOpts;
57+
auto Diags = CompilerInstance::createDiagnostics(*VFS, &DiagOpts,
58+
&DiagConsumer, false);
59+
60+
Diags->Report(diag::err_drv_expand_response_file)
61+
<< llvm::toString(std::move(E));
62+
return nullptr;
63+
}
64+
65+
auto DiagOpts = CreateAndPopulateDiagOpts(Args);
5266
auto Diags = CompilerInstance::createDiagnostics(*VFS, DiagOpts.release(),
5367
&DiagConsumer, false);
5468
if (WorkingDirectory)
@@ -65,7 +79,7 @@ clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV,
6579
VFS.release());
6680
TheDriver.setCheckInputsExist(false);
6781
std::unique_ptr<driver::Compilation> C(
68-
TheDriver.BuildCompilation(ArrayRef(ArgV, ArgC)));
82+
TheDriver.BuildCompilation(Args));
6983
if (!C || Diags->hasErrorOccurred()) {
7084
if (OutDiags)
7185
*OutDiags = DiagConsumer.getDiagnosticSet();

clang/unittests/libclang/DriverTest.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "llvm/Support/Debug.h"
1212
#include "gtest/gtest.h"
1313

14+
#include "TestUtils.h"
15+
1416
#define DEBUG_TYPE "driver-test"
1517

1618
TEST(DriverTests, Basic) {
@@ -129,3 +131,44 @@ TEST(DriverTests, DriverParsesDiagnosticsOptions) {
129131
clang_disposeDiagnosticSet(Diags);
130132
clang_Driver_ExternalActionList_dispose(EAL);
131133
}
134+
135+
class LibclangDriverResponseFileTest : public LibclangParseTest {};
136+
137+
TEST_F(LibclangDriverResponseFileTest, DriverResponseFile) {
138+
// Enable -Weverything (a flag not set by default) via a response file.
139+
std::string ResponseFilename = "AdditionalOptions.resp";
140+
WriteFile(ResponseFilename, "-Weverything\n");
141+
142+
llvm::SmallString<256> ResponseArg("@");
143+
ResponseArg.append(ResponseFilename);
144+
145+
const char *ArgV[] = {"clang",
146+
ResponseArg.c_str(),
147+
"-c",
148+
"t.cpp",
149+
"-o",
150+
"t.o"};
151+
152+
CXDiagnosticSet Diags;
153+
CXExternalActionList *EAL = clang_Driver_getExternalActionsForCommand_v0(
154+
std::extent_v<decltype(ArgV)>, ArgV, nullptr, "/", &Diags);
155+
156+
ASSERT_NE(EAL, nullptr);
157+
ASSERT_EQ(EAL->Count, 1);
158+
ASSERT_EQ(nullptr, Diags);
159+
160+
auto *CompileAction = EAL->Actions[0];
161+
ASSERT_GE(CompileAction->ArgC, 2);
162+
EXPECT_STREQ(CompileAction->ArgV[0], "clang");
163+
EXPECT_STREQ(CompileAction->ArgV[1], "-cc1");
164+
165+
const char **WFlag = std::find(CompileAction->ArgV,
166+
CompileAction->ArgV + CompileAction->ArgC,
167+
llvm::StringRef("-Weverything"));
168+
169+
ASSERT_NE(WFlag, CompileAction->ArgV + CompileAction->ArgC);
170+
EXPECT_STREQ(*WFlag, "-Weverything");
171+
172+
clang_disposeDiagnosticSet(Diags);
173+
clang_Driver_ExternalActionList_dispose(EAL);
174+
}

0 commit comments

Comments
 (0)