Frontend: Allow passing -cc1 level arguments to plugins. Patch by Troy Straszheim!

llvm-svn: 106113
This commit is contained in:
Daniel Dunbar 2010-06-16 16:59:23 +00:00
parent 26036fd722
commit 7c995e8fac
8 changed files with 57 additions and 16 deletions

View File

@ -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<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";
}
};
}

View File

@ -264,8 +264,11 @@ def cxx_inheritance_view : Separate<"-cxx-inheritance-view">,
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">,

View File

@ -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 @@ 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<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 {

View File

@ -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<std::string> PluginArgs;
/// The list of plugins to load.
std::vector<std::string> Plugins;

View File

@ -16,7 +16,7 @@
namespace clang {
/// The frontend plugin registry.
typedef llvm::Registry<FrontendAction> FrontendPluginRegistry;
typedef llvm::Registry<PluginASTAction> FrontendPluginRegistry;
} // end namespace clang

View File

@ -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

View File

@ -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)) {

View File

@ -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)