From 7c995e8facb8c2b620ad46b141c24758f573d68a Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 16 Jun 2010 16:59:23 +0000 Subject: [PATCH] Frontend: Allow passing -cc1 level arguments to plugins. Patch by Troy Straszheim! llvm-svn: 106113 --- .../PrintFunctionNames/PrintFunctionNames.cpp | 15 ++++++++++++++- clang/include/clang/Driver/CC1Options.td | 5 ++++- clang/include/clang/Frontend/FrontendAction.h | 15 +++++++++++++++ clang/include/clang/Frontend/FrontendOptions.h | 3 +++ .../clang/Frontend/FrontendPluginRegistry.h | 2 +- clang/lib/Driver/OptTable.cpp | 3 ++- clang/lib/Frontend/CompilerInvocation.cpp | 14 +++++++++++++- clang/tools/driver/cc1_main.cpp | 16 +++++----------- 8 files changed, 57 insertions(+), 16 deletions(-) diff --git a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp index 5b7b66a4f7ff..397cf843fa7f 100644 --- a/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp +++ b/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp @@ -31,11 +31,24 @@ public: } }; -class PrintFunctionNamesAction : public ASTFrontendAction { +class PrintFunctionNamesAction : public PluginASTAction { protected: ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) { return new PrintFunctionsConsumer(); } + + bool ParseArgs(const std::vector& args) { + for (unsigned i=0; i, def o : Separate<"-o">, MetaVarName<"">, HelpText<"Specify output file">; def load : Separate<"-load">, MetaVarName<"">, HelpText<"Load the named plugin (dynamic shared object)">; -def plugin : Separate<"-plugin">, +def plugin : Separate<"-plugin">, MetaVarName<"">, HelpText<"Use the named plugin action (use \"help\" to list available options)">; +def plugin_arg : JoinedAndSeparate<"-plugin-arg-">, + MetaVarName<" ">, + HelpText<"Pass to plugin ">; def resource_dir : Separate<"-resource-dir">, HelpText<"The directory which holds the compiler resource files">; def version : Flag<"-version">, diff --git a/clang/include/clang/Frontend/FrontendAction.h b/clang/include/clang/Frontend/FrontendAction.h index b16a6aa5093d..f6a68bf69e89 100644 --- a/clang/include/clang/Frontend/FrontendAction.h +++ b/clang/include/clang/Frontend/FrontendAction.h @@ -13,6 +13,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" #include +#include + +namespace llvm { + class raw_ostream; +} namespace clang { class ASTConsumer; @@ -214,6 +219,16 @@ public: virtual bool usesPreprocessorOnly() const { return false; } }; +class PluginASTAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) = 0; + +public: + virtual bool ParseArgs(const std::vector& arg) = 0; + virtual void PrintHelp(llvm::raw_ostream&) = 0; +}; + /// PreprocessorFrontendAction - Abstract base class to use for preprocessor /// based frontend actions. class PreprocessorFrontendAction : public FrontendAction { diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 07e062ed6ba6..0f4538976d57 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -94,6 +94,9 @@ public: /// The name of the action to run when using a plugin action. std::string ActionName; + /// Arg to pass to the plugin + std::vector PluginArgs; + /// The list of plugins to load. std::vector Plugins; diff --git a/clang/include/clang/Frontend/FrontendPluginRegistry.h b/clang/include/clang/Frontend/FrontendPluginRegistry.h index 8341492cfd23..ec925adb0186 100644 --- a/clang/include/clang/Frontend/FrontendPluginRegistry.h +++ b/clang/include/clang/Frontend/FrontendPluginRegistry.h @@ -16,7 +16,7 @@ namespace clang { /// The frontend plugin registry. -typedef llvm::Registry FrontendPluginRegistry; +typedef llvm::Registry FrontendPluginRegistry; } // end namespace clang diff --git a/clang/lib/Driver/OptTable.cpp b/clang/lib/Driver/OptTable.cpp index 618ba8e9964e..39530f211d80 100644 --- a/clang/lib/Driver/OptTable.cpp +++ b/clang/lib/Driver/OptTable.cpp @@ -267,7 +267,7 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { case Option::GroupClass: case Option::InputClass: case Option::UnknownClass: assert(0 && "Invalid option with help text."); - case Option::MultiArgClass: case Option::JoinedAndSeparateClass: + case Option::MultiArgClass: assert(0 && "Cannot print metavar for this kind of option."); case Option::FlagClass: @@ -277,6 +277,7 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { Name += ' '; // FALLTHROUGH case Option::JoinedClass: case Option::CommaJoinedClass: + case Option::JoinedAndSeparateClass: if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) Name += MetaVarName; else diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d74052fd99d0..a925047d9456 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -397,6 +397,10 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, if (!Opts.ActionName.empty()) { Res.push_back("-plugin"); Res.push_back(Opts.ActionName); + for(unsigned i = 0, e = Opts.PluginArgs.size(); i != e; ++i) { + Res.push_back("-plugin-arg-" + Opts.ActionName); + Res.push_back(Opts.PluginArgs[i]); + } } for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i) { Res.push_back("-load"); @@ -989,9 +993,17 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::RunPreprocessorOnly; break; } } - if (const Arg *A = Args.getLastArg(OPT_plugin)) { + + if (const Arg* A = Args.getLastArg(OPT_plugin)) { + Opts.Plugins.push_back(A->getValue(Args,0)); Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(Args); + + for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg), + end = Args.filtered_end(); it != end; ++it) { + if ((*it)->getValue(Args, 0) == Opts.ActionName) + Opts.PluginArgs.push_back((*it)->getValue(Args, 1)); + } } if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) { diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index c4c1bd9e8bf6..841e40abfc75 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -85,21 +85,15 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) { case ParseSyntaxOnly: return new SyntaxOnlyAction(); case PluginAction: { - if (CI.getFrontendOpts().ActionName == "help") { - llvm::errs() << "clang -cc1 plugins:\n"; - for (FrontendPluginRegistry::iterator it = - FrontendPluginRegistry::begin(), - ie = FrontendPluginRegistry::end(); - it != ie; ++it) - llvm::errs() << " " << it->getName() << " - " << it->getDesc() << "\n"; - return 0; - } for (FrontendPluginRegistry::iterator it = FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); it != ie; ++it) { - if (it->getName() == CI.getFrontendOpts().ActionName) - return it->instantiate(); + if (it->getName() == CI.getFrontendOpts().ActionName) { + PluginASTAction* plugin = it->instantiate(); + plugin->ParseArgs(CI.getFrontendOpts().PluginArgs); + return plugin; + } } CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)