[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(Attribute)
|
||||
add_subdirectory(CallSuperAttribute)
|
||||
add_subdirectory(PluginsOrder)
|
||||
|
|
11
clang/examples/PluginsOrder/CMakeLists.txt
Normal file
11
clang/examples/PluginsOrder/CMakeLists.txt
Normal file
|
@ -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()
|
117
clang/examples/PluginsOrder/PluginsOrder.cpp
Normal file
117
clang/examples/PluginsOrder/PluginsOrder.cpp
Normal file
|
@ -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;
|
||||
|
||||
enum ActionType {
|
||||
Cmdline, ///< Action is determined by the cc1 command-line
|
||||
ReplaceAction, ///< Replace the main action
|
||||
AddBeforeMainAction, ///< Execute the action before the main action
|
||||
AddAfterMainAction ///< Execute the action after the main action
|
||||
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
|
||||
AddBeforeMainAction, ///< Execute the action before the main action
|
||||
AddAfterMainAction ///< Execute the action after the main action
|
||||
};
|
||||
/// Get the action type for this plugin
|
||||
///
|
||||
/// \return The action type. If the type is Cmdline then by default the
|
||||
/// plugin does nothing and what it does is determined by the cc1
|
||||
/// command-line.
|
||||
virtual ActionType getActionType() { return Cmdline; }
|
||||
/// \return The action type. By default we use CmdlineAfterMainAction.
|
||||
virtual ActionType getActionType() { return CmdlineAfterMainAction; }
|
||||
};
|
||||
|
||||
/// Abstract base class to use for preprocessor-based frontend actions.
|
||||
|
|
|
@ -187,14 +187,19 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
|
|||
FrontendPluginRegistry::entries()) {
|
||||
std::unique_ptr<PluginASTAction> P = Plugin.instantiate();
|
||||
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
|
||||
// way below 50 in practice, that's ok.
|
||||
if (llvm::any_of(CI.getFrontendOpts().AddPluginActions,
|
||||
[&](const std::string &PluginAction) {
|
||||
return PluginAction == Plugin.getName();
|
||||
}))
|
||||
ActionType = PluginASTAction::AddAfterMainAction;
|
||||
})) {
|
||||
if (ActionType == PluginASTAction::CmdlineBeforeMainAction)
|
||||
ActionType = PluginASTAction::AddBeforeMainAction;
|
||||
else
|
||||
ActionType = PluginASTAction::AddAfterMainAction;
|
||||
}
|
||||
}
|
||||
if ((ActionType == PluginASTAction::AddBeforeMainAction ||
|
||||
ActionType == PluginASTAction::AddAfterMainAction) &&
|
||||
|
|
|
@ -79,7 +79,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
|
|||
if (Plugin.getName() == CI.getFrontendOpts().ActionName) {
|
||||
std::unique_ptr<PluginASTAction> P(Plugin.instantiate());
|
||||
if ((P->getActionType() != PluginASTAction::ReplaceAction &&
|
||||
P->getActionType() != PluginASTAction::Cmdline) ||
|
||||
P->getActionType() != PluginASTAction::CmdlineAfterMainAction) ||
|
||||
!P->ParseArgs(
|
||||
CI,
|
||||
CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())]))
|
||||
|
|
|
@ -97,6 +97,7 @@ if (CLANG_BUILD_EXAMPLES)
|
|||
AnnotateFunctions
|
||||
CallSuperAttr
|
||||
clang-interpreter
|
||||
PluginsOrder
|
||||
PrintFunctionNames
|
||||
)
|
||||
endif ()
|
||||
|
|
12
clang/test/Frontend/plugins-order.c
Normal file
12
clang/test/Frontend/plugins-order.c
Normal file
|
@ -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
Block a user