diff --git a/clang/tools/libclang/Driver.cpp b/clang/tools/libclang/Driver.cpp index 4a1d4c516ee8c..5a64b5d90cf35 100644 --- a/clang/tools/libclang/Driver.cpp +++ b/clang/tools/libclang/Driver.cpp @@ -41,7 +41,22 @@ clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV, return nullptr; CXDiagnosticSetDiagnosticConsumer DiagConsumer; - auto DiagOpts = CreateAndPopulateDiagOpts(ArrayRef(ArgV, ArgC)); + + SmallVector Args(ArgV, ArgV + ArgC); + llvm::BumpPtrAllocator Alloc; + if (llvm::Error E = + driver::expandResponseFiles(Args, /*CLMode=*/false, Alloc)) { + // Construct a default DiagnosticOptions to use to emit the failure. + DiagnosticOptions DiagOpts; + auto Diags = CompilerInstance::createDiagnostics(&DiagOpts, + &DiagConsumer, false); + + Diags->Report(diag::err_drv_expand_response_file) + << llvm::toString(std::move(E)); + return nullptr; + } + + auto DiagOpts = CreateAndPopulateDiagOpts(Args); auto Diags = CompilerInstance::createDiagnostics(DiagOpts.release(), &DiagConsumer, false); @@ -64,7 +79,7 @@ clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV, VFS.release()); TheDriver.setCheckInputsExist(false); std::unique_ptr C( - TheDriver.BuildCompilation(ArrayRef(ArgV, ArgC))); + TheDriver.BuildCompilation(Args)); if (!C || Diags->hasErrorOccurred()) { if (OutDiags) *OutDiags = DiagConsumer.getDiagnosticSet(); diff --git a/clang/unittests/libclang/DriverTest.cpp b/clang/unittests/libclang/DriverTest.cpp index 03d435904784f..e39fa0519eab3 100644 --- a/clang/unittests/libclang/DriverTest.cpp +++ b/clang/unittests/libclang/DriverTest.cpp @@ -11,6 +11,8 @@ #include "llvm/Support/Debug.h" #include "gtest/gtest.h" +#include "TestUtils.h" + #define DEBUG_TYPE "driver-test" TEST(DriverTests, Basic) { @@ -129,3 +131,44 @@ TEST(DriverTests, DriverParsesDiagnosticsOptions) { clang_disposeDiagnosticSet(Diags); clang_Driver_ExternalActionList_dispose(EAL); } + +class LibclangDriverResponseFileTest : public LibclangParseTest {}; + +TEST_F(LibclangDriverResponseFileTest, DriverResponseFile) { + // Enable -Weverything (a flag not set by default) via a response file. + std::string ResponseFilename = "AdditionalOptions.resp"; + WriteFile(ResponseFilename, "-Weverything\n"); + + llvm::SmallString<256> ResponseArg("@"); + ResponseArg.append(ResponseFilename); + + const char *ArgV[] = {"clang", + ResponseArg.c_str(), + "-c", + "t.cpp", + "-o", + "t.o"}; + + CXDiagnosticSet Diags; + CXExternalActionList *EAL = clang_Driver_getExternalActionsForCommand_v0( + std::extent_v, ArgV, nullptr, "/", &Diags); + + ASSERT_NE(EAL, nullptr); + ASSERT_EQ(EAL->Count, 1); + ASSERT_EQ(nullptr, Diags); + + auto *CompileAction = EAL->Actions[0]; + ASSERT_GE(CompileAction->ArgC, 2); + EXPECT_STREQ(CompileAction->ArgV[0], "clang"); + EXPECT_STREQ(CompileAction->ArgV[1], "-cc1"); + + const char **WFlag = std::find(CompileAction->ArgV, + CompileAction->ArgV + CompileAction->ArgC, + llvm::StringRef("-Weverything")); + + ASSERT_NE(WFlag, CompileAction->ArgV + CompileAction->ArgC); + EXPECT_STREQ(*WFlag, "-Weverything"); + + clang_disposeDiagnosticSet(Diags); + clang_Driver_ExternalActionList_dispose(EAL); +}