diff --git a/clang/lib/Tooling/ArgumentsAdjusters.cpp b/clang/lib/Tooling/ArgumentsAdjusters.cpp --- a/clang/lib/Tooling/ArgumentsAdjusters.cpp +++ b/clang/lib/Tooling/ArgumentsAdjusters.cpp @@ -62,7 +62,8 @@ HasSyntaxOnly = true; } if (!HasSyntaxOnly) - AdjustedArgs.push_back("-fsyntax-only"); + AdjustedArgs = + getInsertArgumentAdjuster("-fsyntax-only")(AdjustedArgs, ""); return AdjustedArgs; }; } @@ -137,7 +138,7 @@ CommandLineArguments::iterator I; if (Pos == ArgumentInsertPosition::END) { - I = Return.end(); + I = std::find(Return.begin(), Return.end(), "--"); } else { I = Return.begin(); ++I; // To leave the program name in place diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp --- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp +++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp @@ -177,6 +177,10 @@ Opt.matches(OPT__SLASH_Fo)))) continue; + // ...including when the inputs are passed after --. + if (Opt.matches(OPT__DASH_DASH)) + break; + // Strip -x, but record the overridden language. if (const auto GivenType = tryParseTypeArg(*Arg)) { Type = *GivenType; @@ -235,6 +239,8 @@ llvm::Twine(ClangCLMode ? "/std:" : "-std=") + LangStandard::getLangStandardForKind(Std).getName()).str()); } + if (Filename.startswith("-") || (ClangCLMode && Filename.startswith("/"))) + Result.CommandLine.push_back("--"); Result.CommandLine.push_back(std::string(Filename)); return Result; } diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -440,8 +440,9 @@ return; // If there's no override in place add our resource dir. - Args.push_back("-resource-dir=" + - CompilerInvocation::GetResourcesPath(Argv0, MainAddr)); + Args = getInsertArgumentAdjuster( + ("-resource-dir=" + CompilerInvocation::GetResourcesPath(Argv0, MainAddr)) + .c_str())(Args, ""); } int ClangTool::run(ToolAction *Action) { diff --git a/clang/unittests/Tooling/CompilationDatabaseTest.cpp b/clang/unittests/Tooling/CompilationDatabaseTest.cpp --- a/clang/unittests/Tooling/CompilationDatabaseTest.cpp +++ b/clang/unittests/Tooling/CompilationDatabaseTest.cpp @@ -725,14 +725,14 @@ protected: // Look up the command from a relative path, and return it in string form. // The input file is not included in the returned command. - std::string getCommand(llvm::StringRef F) { + std::string getCommand(llvm::StringRef F, bool MakeNative = true) { auto Results = inferMissingCompileCommands(std::make_unique(Entries)) - ->getCompileCommands(path(F)); + ->getCompileCommands(MakeNative ? path(F) : F); if (Results.empty()) return "none"; // drop the input file argument, so tests don't have to deal with path(). - EXPECT_EQ(Results[0].CommandLine.back(), path(F)) + EXPECT_EQ(Results[0].CommandLine.back(), MakeNative ? path(F) : F) << "Last arg should be the file"; Results[0].CommandLine.pop_back(); return llvm::join(Results[0].CommandLine, " "); @@ -812,6 +812,28 @@ EXPECT_EQ(getCommand("dir/bar.cpp"), "clang -D dir/foo.cpp -Wall"); } +TEST_F(InterpolateTest, StripDoubleDash) { + add("dir/foo.cpp", "-o foo.o -std=c++14 -Wall -- dir/foo.cpp"); + // input file and output option are removed + // -Wall flag isn't + // -std option gets re-added as the last argument before the input file + // -- is removed as it's not necessary - the new input file doesn't start with + // a dash + EXPECT_EQ(getCommand("dir/bar.cpp"), "clang -D dir/foo.cpp -Wall -std=c++14"); +} + +TEST_F(InterpolateTest, InsertDoubleDash) { + add("dir/foo.cpp", "-o foo.o -std=c++14 -Wall"); + EXPECT_EQ(getCommand("-dir/bar.cpp", false), + "clang -D dir/foo.cpp -Wall -std=c++14 --"); +} + +TEST_F(InterpolateTest, InsertDoubleDashForClangCL) { + add("dir/foo.cpp", "clang-cl", "/std:c++14 /W4"); + EXPECT_EQ(getCommand("/dir/bar.cpp", false), + "clang-cl -D dir/foo.cpp /W4 /std:c++14 --"); +} + TEST_F(InterpolateTest, Case) { add("FOO/BAR/BAZ/SHOUT.cc"); add("foo/bar/baz/quiet.cc"); @@ -831,7 +853,7 @@ add("foo.cpp", "clang-cl", "/W4"); // Language flags should be added with CL syntax. - EXPECT_EQ(getCommand("foo.h"), "clang-cl -D foo.cpp /W4 /TP"); + EXPECT_EQ(getCommand("foo.h", false), "clang-cl -D foo.cpp /W4 /TP"); } TEST_F(InterpolateTest, DriverModes) { @@ -839,8 +861,10 @@ add("bar.cpp", "clang", "--driver-mode=cl"); // --driver-mode overrides should be respected. - EXPECT_EQ(getCommand("foo.h"), "clang-cl -D foo.cpp --driver-mode=gcc -x c++-header"); - EXPECT_EQ(getCommand("bar.h"), "clang -D bar.cpp --driver-mode=cl /TP"); + EXPECT_EQ(getCommand("foo.h"), + "clang-cl -D foo.cpp --driver-mode=gcc -x c++-header"); + EXPECT_EQ(getCommand("bar.h", false), + "clang -D bar.cpp --driver-mode=cl /TP"); } TEST(TransferCompileCommandTest, Smoke) {