Frontend: Allow passing -cc1 level arguments to plugins. Patch by Troy Straszheim!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106113 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/examples/PrintFunctionNames/PrintFunctionNames.cpp b/examples/PrintFunctionNames/PrintFunctionNames.cpp
index 5b7b66a..397cf84 100644
--- a/examples/PrintFunctionNames/PrintFunctionNames.cpp
+++ b/examples/PrintFunctionNames/PrintFunctionNames.cpp
@@ -31,11 +31,24 @@
}
};
-class PrintFunctionNamesAction : public ASTFrontendAction {
+class PrintFunctionNamesAction : public PluginASTAction {
protected:
ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) {
return new PrintFunctionsConsumer();
}
+
+ bool ParseArgs(const std::vector<std::string>& args) {
+ for (unsigned i=0; i<args.size(); ++i)
+ llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
+ if (args.size() && args[0] == "help")
+ PrintHelp(llvm::errs());
+
+ return true;
+ }
+ void PrintHelp(llvm::raw_ostream& ros) {
+ ros << "Help for PrintFunctionNames plugin goes here\n";
+ }
+
};
}
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 7e639b5..ab9f902 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -264,8 +264,11 @@
def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">;
def load : Separate<"-load">, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
-def plugin : Separate<"-plugin">,
+def plugin : Separate<"-plugin">, MetaVarName<"<name>">,
HelpText<"Use the named plugin action (use \"help\" to list available options)">;
+def plugin_arg : JoinedAndSeparate<"-plugin-arg-">,
+ MetaVarName<"<name> <arg>">,
+ HelpText<"Pass <arg> to plugin <name>">;
def resource_dir : Separate<"-resource-dir">,
HelpText<"The directory which holds the compiler resource files">;
def version : Flag<"-version">,
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index b16a6aa..f6a68bf 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -13,6 +13,11 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/OwningPtr.h"
#include <string>
+#include <vector>
+
+namespace llvm {
+ class raw_ostream;
+}
namespace clang {
class ASTConsumer;
@@ -214,6 +219,16 @@
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<std::string>& 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/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 07e062e..0f45389 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -94,6 +94,9 @@
/// The name of the action to run when using a plugin action.
std::string ActionName;
+ /// Arg to pass to the plugin
+ std::vector<std::string> PluginArgs;
+
/// The list of plugins to load.
std::vector<std::string> Plugins;
diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h
index 8341492..ec925ad 100644
--- a/include/clang/Frontend/FrontendPluginRegistry.h
+++ b/include/clang/Frontend/FrontendPluginRegistry.h
@@ -16,7 +16,7 @@
namespace clang {
/// The frontend plugin registry.
-typedef llvm::Registry<FrontendAction> FrontendPluginRegistry;
+typedef llvm::Registry<PluginASTAction> FrontendPluginRegistry;
} // end namespace clang
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index 618ba8e..39530f2 100644
--- a/lib/Driver/OptTable.cpp
+++ b/lib/Driver/OptTable.cpp
@@ -267,7 +267,7 @@
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 @@
Name += ' ';
// FALLTHROUGH
case Option::JoinedClass: case Option::CommaJoinedClass:
+ case Option::JoinedAndSeparateClass:
if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
Name += MetaVarName;
else
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index d74052f..a925047 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -397,6 +397,10 @@
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 @@
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/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index c4c1bd9..841e40a 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -85,21 +85,15 @@
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)