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,7 +116,13 @@ 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 = FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage); Index: unittests/Tooling/CMakeLists.txt =================================================================== --- unittests/Tooling/CMakeLists.txt +++ unittests/Tooling/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_unittest(ToolingTests CommentHandlerTest.cpp + CommonOptionsParserTest.cpp CompilationDatabaseTest.cpp FixItTest.cpp LookupTest.cpp Index: unittests/Tooling/CommonOptionsParserTest.cpp =================================================================== --- /dev/null +++ unittests/Tooling/CommonOptionsParserTest.cpp @@ -0,0 +1,68 @@ +//===- unittests/Tooling/CommonOptionsParserTest.cpp +//----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/CommonOptionsParser.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; +using namespace clang::tooling; + +class CommonOptionsParserTest : public testing::Test { +public: + SmallString<128> TestDir; + SmallString<128> ResponseFileName; + + CommonOptionsParserTest() { + std::error_code EC = sys::fs::createUniqueDirectory("unittest", TestDir); + EXPECT_TRUE(!EC); + 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(); + } + ~CommonOptionsParserTest() override { + sys::fs::remove(ResponseFileName); + sys::fs::remove(TestDir); + } +}; + +TEST_F(CommonOptionsParserTest, + ExpandResponseFileBeforeLoadingCompilationDatabase) { + setResponseFileContent("-option_1 -- -option_2=true -option_3"); + SmallString<128> ResponseRef; + ResponseRef.append(1, '@'); + ResponseRef.append(ResponseFileName.c_str()); + int Argc = 3; + const char *Argv[] = {"pos_1", "pos_2", ResponseRef.c_str()}; + cl::OptionCategory Category("options"); + cl::opt option1("option_1", cl::desc(""), cl::init(false), + cl::cat(Category)); + cl::opt option2("option_2", cl::desc(""), cl::init(false), + cl::cat(Category)); + cl::opt option3("option_3", cl::desc(""), cl::init(false), + 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("-option_2=true"); + ExpectedCmd.push_back("-option_3"); + ExpectedCmd.push_back("source"); + + ASSERT_EQ(ExpectedCmd, ActualCC[0].CommandLine); +} \ No newline at end of file