Index: lib/Tooling/CommonOptionsParser.cpp =================================================================== --- lib/Tooling/CommonOptionsParser.cpp +++ lib/Tooling/CommonOptionsParser.cpp @@ -25,6 +25,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/CommandLine.h" +#include "llvm/Support/StringSaver.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Tooling.h" @@ -115,6 +116,14 @@ cl::cat(Category)); cl::HideUnrelatedOptions(Category); + + // Expand response files before loading compilation database from command line + SmallVector newArgv(argv, argv + argc); + BumpPtrAllocator A; + StringSaver Saver(A); + cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, newArgv); + argv = &newArgv[0]; + argc = static_cast(newArgv.size()); std::string ErrorMessage; Compilations = Index: unittests/Tooling/CompilationDatabaseTest.cpp =================================================================== --- unittests/Tooling/CompilationDatabaseTest.cpp +++ unittests/Tooling/CompilationDatabaseTest.cpp @@ -10,12 +10,16 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclGroup.h" #include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/FileMatchTrie.h" #include "clang/Tooling/JSONCompilationDatabase.h" #include "clang/Tooling/Tooling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "gtest/gtest.h" +#include + namespace clang { namespace tooling { @@ -626,5 +630,52 @@ EXPECT_EQ(2, Argc); } +class ParseCompilationDatabaseFromResponseFileTest : public testing::Test { +public: + SmallString<128> TestDir; + SmallString<128> ResponseFileName; + + ParseCompilationDatabaseFromResponseFileTest() { + std::error_code EC = llvm::sys::fs::createUniqueDirectory("unittest", TestDir); + EXPECT_TRUE(!EC); + llvm::sys::path::append(ResponseFileName, TestDir, "resp"); + } + void setResponseFileContent(const std::string &content) { + std::ofstream File(ResponseFileName.c_str()); + EXPECT_TRUE(File.is_open()); + File << content; + File.close(); + } + ~ParseCompilationDatabaseFromResponseFileTest() override { + llvm::sys::fs::remove(ResponseFileName); + llvm::sys::fs::remove(TestDir); + } +}; + +TEST_F(ParseCompilationDatabaseFromResponseFileTest, GetCompileCommands) { + setResponseFileContent("-- -a=true -b"); + SmallString<128> ResponseRef; + ResponseRef.append(1, '@'); + ResponseRef.append(ResponseFileName.c_str()); + int Argc = 3; + const char *Argv[] = { "1", "2", ResponseRef.c_str() }; + llvm::cl::OptionCategory Category("options"); + llvm::cl::opt option1("a", llvm::cl::desc(""), llvm::cl::init(false), + llvm::cl::cat(Category)); + llvm::cl::opt option2("b", llvm::cl::desc(""), llvm::cl::init(false), + llvm::cl::cat(Category)); + CommonOptionsParser Parser(Argc, Argv, Category); + CompilationDatabase &Database = Parser.getCompilations(); + std::vector ActualCC = Database.getCompileCommands("source"); + ASSERT_EQ(1u, ActualCC.size()); + std::vector ExpectedCmd; + ExpectedCmd.push_back("clang-tool"); + ExpectedCmd.push_back("-a=true"); + ExpectedCmd.push_back("-b"); + ExpectedCmd.push_back("source"); + + ASSERT_EQ(ExpectedCmd, ActualCC[0].CommandLine); +} + } // end namespace tooling } // end namespace clang