forked from OSchip/llvm-project
[clang] Add plugin ActionType to run command line plugin before main action
Currently we have a way to run a plugin if specified on the command line after the main action, and ways to unconditionally run the plugin before or after the main action, but no way to run a plugin if specified on the command line before the main action. This introduces the missing option. This is helpful because -clear-ast-before-backend clears the AST before codegen, while some plugins may want access to the AST. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D112096
This commit is contained in:
parent
eabf11f9ea
commit
fe66433fe1
|
@ -8,3 +8,4 @@ add_subdirectory(PrintFunctionNames)
|
||||||
add_subdirectory(AnnotateFunctions)
|
add_subdirectory(AnnotateFunctions)
|
||||||
add_subdirectory(Attribute)
|
add_subdirectory(Attribute)
|
||||||
add_subdirectory(CallSuperAttribute)
|
add_subdirectory(CallSuperAttribute)
|
||||||
|
add_subdirectory(PluginsOrder)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
add_llvm_library(PluginsOrder MODULE PluginsOrder.cpp PLUGIN_TOOL clang)
|
||||||
|
|
||||||
|
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
|
||||||
|
set(LLVM_LINK_COMPONENTS
|
||||||
|
Support
|
||||||
|
)
|
||||||
|
clang_target_link_libraries(PluginsOrder PRIVATE
|
||||||
|
clangAST
|
||||||
|
clangFrontend
|
||||||
|
)
|
||||||
|
endif()
|
|
@ -0,0 +1,117 @@
|
||||||
|
//===- PluginsOrder.cpp ---------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "clang/AST/AST.h"
|
||||||
|
#include "clang/AST/ASTConsumer.h"
|
||||||
|
#include "clang/Frontend/FrontendPluginRegistry.h"
|
||||||
|
using namespace clang;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class AlwaysBeforeConsumer : public ASTConsumer {
|
||||||
|
public:
|
||||||
|
void HandleTranslationUnit(ASTContext &) override {
|
||||||
|
llvm::errs() << "always-before\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AlwaysBeforeAction : public PluginASTAction {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||||
|
llvm::StringRef) override {
|
||||||
|
return std::make_unique<AlwaysBeforeConsumer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseArgs(const CompilerInstance &CI,
|
||||||
|
const std::vector<std::string> &args) override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginASTAction::ActionType getActionType() override {
|
||||||
|
return AddBeforeMainAction;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AlwaysAfterConsumer : public ASTConsumer {
|
||||||
|
public:
|
||||||
|
void HandleTranslationUnit(ASTContext &) override {
|
||||||
|
llvm::errs() << "always-after\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AlwaysAfterAction : public PluginASTAction {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||||
|
llvm::StringRef) override {
|
||||||
|
return std::make_unique<AlwaysAfterConsumer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseArgs(const CompilerInstance &CI,
|
||||||
|
const std::vector<std::string> &args) override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginASTAction::ActionType getActionType() override {
|
||||||
|
return AddAfterMainAction;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CmdAfterConsumer : public ASTConsumer {
|
||||||
|
public:
|
||||||
|
void HandleTranslationUnit(ASTContext &) override {
|
||||||
|
llvm::errs() << "cmd-after\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CmdAfterAction : public PluginASTAction {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||||
|
llvm::StringRef) override {
|
||||||
|
return std::make_unique<CmdAfterConsumer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseArgs(const CompilerInstance &CI,
|
||||||
|
const std::vector<std::string> &args) override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginASTAction::ActionType getActionType() override {
|
||||||
|
return CmdlineAfterMainAction;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CmdBeforeConsumer : public ASTConsumer {
|
||||||
|
public:
|
||||||
|
void HandleTranslationUnit(ASTContext &) override {
|
||||||
|
llvm::errs() << "cmd-before\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CmdBeforeAction : public PluginASTAction {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||||
|
llvm::StringRef) override {
|
||||||
|
return std::make_unique<CmdBeforeConsumer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseArgs(const CompilerInstance &CI,
|
||||||
|
const std::vector<std::string> &args) override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginASTAction::ActionType getActionType() override {
|
||||||
|
return CmdlineBeforeMainAction;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
static FrontendPluginRegistry::Add<CmdBeforeAction> X1("cmd-before", "");
|
||||||
|
static FrontendPluginRegistry::Add<CmdAfterAction> X2("cmd-after", "");
|
||||||
|
static FrontendPluginRegistry::Add<AlwaysBeforeAction> X3("always-before", "");
|
||||||
|
static FrontendPluginRegistry::Add<AlwaysAfterAction> X4("always-after", "");
|
|
@ -270,17 +270,18 @@ public:
|
||||||
const std::vector<std::string> &arg) = 0;
|
const std::vector<std::string> &arg) = 0;
|
||||||
|
|
||||||
enum ActionType {
|
enum ActionType {
|
||||||
Cmdline, ///< Action is determined by the cc1 command-line
|
CmdlineBeforeMainAction, ///< Execute the action before the main action if
|
||||||
|
///< on the command line
|
||||||
|
CmdlineAfterMainAction, ///< Execute the action after the main action if on
|
||||||
|
///< the command line
|
||||||
ReplaceAction, ///< Replace the main action
|
ReplaceAction, ///< Replace the main action
|
||||||
AddBeforeMainAction, ///< Execute the action before the main action
|
AddBeforeMainAction, ///< Execute the action before the main action
|
||||||
AddAfterMainAction ///< Execute the action after the main action
|
AddAfterMainAction ///< Execute the action after the main action
|
||||||
};
|
};
|
||||||
/// Get the action type for this plugin
|
/// Get the action type for this plugin
|
||||||
///
|
///
|
||||||
/// \return The action type. If the type is Cmdline then by default the
|
/// \return The action type. By default we use CmdlineAfterMainAction.
|
||||||
/// plugin does nothing and what it does is determined by the cc1
|
virtual ActionType getActionType() { return CmdlineAfterMainAction; }
|
||||||
/// command-line.
|
|
||||||
virtual ActionType getActionType() { return Cmdline; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract base class to use for preprocessor-based frontend actions.
|
/// Abstract base class to use for preprocessor-based frontend actions.
|
||||||
|
|
|
@ -187,15 +187,20 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
|
||||||
FrontendPluginRegistry::entries()) {
|
FrontendPluginRegistry::entries()) {
|
||||||
std::unique_ptr<PluginASTAction> P = Plugin.instantiate();
|
std::unique_ptr<PluginASTAction> P = Plugin.instantiate();
|
||||||
PluginASTAction::ActionType ActionType = P->getActionType();
|
PluginASTAction::ActionType ActionType = P->getActionType();
|
||||||
if (ActionType == PluginASTAction::Cmdline) {
|
if (ActionType == PluginASTAction::CmdlineAfterMainAction ||
|
||||||
|
ActionType == PluginASTAction::CmdlineBeforeMainAction) {
|
||||||
// This is O(|plugins| * |add_plugins|), but since both numbers are
|
// This is O(|plugins| * |add_plugins|), but since both numbers are
|
||||||
// way below 50 in practice, that's ok.
|
// way below 50 in practice, that's ok.
|
||||||
if (llvm::any_of(CI.getFrontendOpts().AddPluginActions,
|
if (llvm::any_of(CI.getFrontendOpts().AddPluginActions,
|
||||||
[&](const std::string &PluginAction) {
|
[&](const std::string &PluginAction) {
|
||||||
return PluginAction == Plugin.getName();
|
return PluginAction == Plugin.getName();
|
||||||
}))
|
})) {
|
||||||
|
if (ActionType == PluginASTAction::CmdlineBeforeMainAction)
|
||||||
|
ActionType = PluginASTAction::AddBeforeMainAction;
|
||||||
|
else
|
||||||
ActionType = PluginASTAction::AddAfterMainAction;
|
ActionType = PluginASTAction::AddAfterMainAction;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ((ActionType == PluginASTAction::AddBeforeMainAction ||
|
if ((ActionType == PluginASTAction::AddBeforeMainAction ||
|
||||||
ActionType == PluginASTAction::AddAfterMainAction) &&
|
ActionType == PluginASTAction::AddAfterMainAction) &&
|
||||||
P->ParseArgs(
|
P->ParseArgs(
|
||||||
|
|
|
@ -79,7 +79,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
|
||||||
if (Plugin.getName() == CI.getFrontendOpts().ActionName) {
|
if (Plugin.getName() == CI.getFrontendOpts().ActionName) {
|
||||||
std::unique_ptr<PluginASTAction> P(Plugin.instantiate());
|
std::unique_ptr<PluginASTAction> P(Plugin.instantiate());
|
||||||
if ((P->getActionType() != PluginASTAction::ReplaceAction &&
|
if ((P->getActionType() != PluginASTAction::ReplaceAction &&
|
||||||
P->getActionType() != PluginASTAction::Cmdline) ||
|
P->getActionType() != PluginASTAction::CmdlineAfterMainAction) ||
|
||||||
!P->ParseArgs(
|
!P->ParseArgs(
|
||||||
CI,
|
CI,
|
||||||
CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())]))
|
CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())]))
|
||||||
|
|
|
@ -97,6 +97,7 @@ if (CLANG_BUILD_EXAMPLES)
|
||||||
AnnotateFunctions
|
AnnotateFunctions
|
||||||
CallSuperAttr
|
CallSuperAttr
|
||||||
clang-interpreter
|
clang-interpreter
|
||||||
|
PluginsOrder
|
||||||
PrintFunctionNames
|
PrintFunctionNames
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// REQUIRES: plugins, examples
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -load %llvmshlibdir/PluginsOrder%pluginext %s 2>&1 | FileCheck %s --check-prefix=ALWAYS
|
||||||
|
// ALWAYS: always-before
|
||||||
|
// ALWAYS-NEXT: always-after
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -load %llvmshlibdir/PluginsOrder%pluginext %s -add-plugin cmd-after -add-plugin cmd-before 2>&1 | FileCheck %s --check-prefix=ALL
|
||||||
|
// RUN: %clang_cc1 -load %llvmshlibdir/PluginsOrder%pluginext %s -add-plugin cmd-before -add-plugin cmd-after 2>&1 | FileCheck %s --check-prefix=ALL
|
||||||
|
// ALL: cmd-before
|
||||||
|
// ALL-NEXT: always-before
|
||||||
|
// ALL-NEXT: cmd-after
|
||||||
|
// ALL-NEXT: always-after
|
Loading…
Reference in New Issue