From: Manuel Klimek Date: Tue, 4 Jun 2013 14:44:44 +0000 (+0000) Subject: Enables chaining of argument adjusters in clang tools. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48b3f0f74da575a66802dc5019b7440914983885;p=clang Enables chaining of argument adjusters in clang tools. This enables changing clang-check to get extra arguments. Patch by Pavel Labath. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183227 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 7de0a1fe2a..dc8163e553 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -175,8 +175,8 @@ class ToolInvocation { /// This class is written to be usable for command line utilities. /// By default the class uses ClangSyntaxOnlyAdjuster to modify /// command line arguments before the arguments are used to run -/// a frontend action. One could install another command line -/// arguments adjuster by call setArgumentsAdjuster() method. +/// a frontend action. One could install an additional command line +/// arguments adjuster by calling the appendArgumentsAdjuster() method. class ClangTool { public: /// \brief Constructs a clang tool to run over a list of files. @@ -188,7 +188,7 @@ class ClangTool { ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths); - virtual ~ClangTool() {} + virtual ~ClangTool() { clearArgumentsAdjusters(); } /// \brief Map a virtual file to be used while running the tool. /// @@ -199,8 +199,20 @@ class ClangTool { /// \brief Install command line arguments adjuster. /// /// \param Adjuster Command line arguments adjuster. + // + /// FIXME: Function is deprecated. Use (clear/append)ArgumentsAdjuster instead. + /// Remove it once all callers are gone. void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster); + /// \brief Append a command line arguments adjuster to the adjuster chain. + /// + /// \param Adjuster An argument adjuster, which will be run on the output of + /// previous argument adjusters. + void appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster); + + /// \brief Clear the command line arguments adjuster chain. + void clearArgumentsAdjusters(); + /// Runs a frontend action over all files specified in the command line. /// /// \param ActionFactory Factory generating the frontend actions. The function @@ -221,7 +233,7 @@ class ClangTool { // Contains a list of pairs (, ). std::vector< std::pair > MappedFileContents; - OwningPtr ArgsAdjuster; + SmallVector ArgsAdjusters; }; template diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp index 52855f657f..cdb9bc71ee 100644 --- a/lib/Tooling/Tooling.cpp +++ b/lib/Tooling/Tooling.cpp @@ -237,7 +237,7 @@ void ToolInvocation::addFileMappingsTo(SourceManager &Sources) { ClangTool::ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths) : Files((FileSystemOptions())), - ArgsAdjuster(new ClangSyntaxOnlyAdjuster()) { + ArgsAdjusters(1, new ClangSyntaxOnlyAdjuster()) { for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) { SmallString<1024> File(getAbsolutePath(SourcePaths[I])); @@ -264,7 +264,18 @@ void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) { } void ClangTool::setArgumentsAdjuster(ArgumentsAdjuster *Adjuster) { - ArgsAdjuster.reset(Adjuster); + clearArgumentsAdjusters(); + appendArgumentsAdjuster(Adjuster); +} + +void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster) { + ArgsAdjusters.push_back(Adjuster); +} + +void ClangTool::clearArgumentsAdjusters() { + for (unsigned I = 0, E = ArgsAdjusters.size(); I != E; ++I) + delete ArgsAdjusters[I]; + ArgsAdjusters.clear(); } int ClangTool::run(FrontendActionFactory *ActionFactory) { @@ -292,8 +303,9 @@ int ClangTool::run(FrontendActionFactory *ActionFactory) { if (chdir(CompileCommands[I].second.Directory.c_str())) llvm::report_fatal_error("Cannot chdir into \"" + CompileCommands[I].second.Directory + "\n!"); - std::vector CommandLine = - ArgsAdjuster->Adjust(CompileCommands[I].second.CommandLine); + std::vector CommandLine = CompileCommands[I].second.CommandLine; + for (unsigned I = 0, E = ArgsAdjusters.size(); I != E; ++I) + CommandLine = ArgsAdjusters[I]->Adjust(CommandLine); assert(!CommandLine.empty()); CommandLine[0] = MainExecutable; // FIXME: We need a callback mechanism for the tool writer to output a diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp index d96366dcd5..e435ea92e2 100644 --- a/unittests/Tooling/ToolingTest.cpp +++ b/unittests/Tooling/ToolingTest.cpp @@ -193,5 +193,46 @@ TEST(runToolOnCode, TestSkipFunctionBody) { "int skipMeNot() { an_error_here }")); } +struct CheckSyntaxOnlyAdjuster: public ArgumentsAdjuster { + bool &Found; + bool &Ran; + + CheckSyntaxOnlyAdjuster(bool &Found, bool &Ran) : Found(Found), Ran(Ran) { } + + virtual CommandLineArguments + Adjust(const CommandLineArguments &Args) LLVM_OVERRIDE { + Ran = true; + for (unsigned I = 0, E = Args.size(); I != E; ++I) { + if (Args[I] == "-fsyntax-only") { + Found = true; + break; + } + } + return Args; + } +}; + +TEST(ClangToolTest, ArgumentAdjusters) { + FixedCompilationDatabase Compilations("/", std::vector()); + + ClangTool Tool(Compilations, std::vector(1, "/a.cc")); + Tool.mapVirtualFile("/a.cc", "void a() {}"); + + bool Found = false; + bool Ran = false; + Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran)); + Tool.run(newFrontendActionFactory()); + EXPECT_TRUE(Ran); + EXPECT_TRUE(Found); + + Ran = Found = false; + Tool.clearArgumentsAdjusters(); + Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran)); + Tool.appendArgumentsAdjuster(new ClangSyntaxOnlyAdjuster()); + Tool.run(newFrontendActionFactory()); + EXPECT_TRUE(Ran); + EXPECT_FALSE(Found); +} + } // end namespace tooling } // end namespace clang