[clang] fe66433 - [clang] Add plugin ActionType to run command line plugin before main action

Arthur Eubanks via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 20 08:58:31 PDT 2021


Author: Arthur Eubanks
Date: 2021-10-20T08:58:20-07:00
New Revision: fe66433fe119819a033827610f7eae4cdd8b1470

URL: https://github.com/llvm/llvm-project/commit/fe66433fe119819a033827610f7eae4cdd8b1470
DIFF: https://github.com/llvm/llvm-project/commit/fe66433fe119819a033827610f7eae4cdd8b1470.diff

LOG: [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

Added: 
    clang/examples/PluginsOrder/CMakeLists.txt
    clang/examples/PluginsOrder/PluginsOrder.cpp
    clang/test/Frontend/plugins-order.c

Modified: 
    clang/examples/CMakeLists.txt
    clang/include/clang/Frontend/FrontendAction.h
    clang/lib/Frontend/FrontendAction.cpp
    clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
    clang/test/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/clang/examples/CMakeLists.txt b/clang/examples/CMakeLists.txt
index 300d8d795c674..684d81d180278 100644
--- a/clang/examples/CMakeLists.txt
+++ b/clang/examples/CMakeLists.txt
@@ -8,3 +8,4 @@ add_subdirectory(PrintFunctionNames)
 add_subdirectory(AnnotateFunctions)
 add_subdirectory(Attribute)
 add_subdirectory(CallSuperAttribute)
+add_subdirectory(PluginsOrder)

diff  --git a/clang/examples/PluginsOrder/CMakeLists.txt b/clang/examples/PluginsOrder/CMakeLists.txt
new file mode 100644
index 0000000000000..289e234ac28c4
--- /dev/null
+++ b/clang/examples/PluginsOrder/CMakeLists.txt
@@ -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()

diff  --git a/clang/examples/PluginsOrder/PluginsOrder.cpp b/clang/examples/PluginsOrder/PluginsOrder.cpp
new file mode 100644
index 0000000000000..e25ab7aceca85
--- /dev/null
+++ b/clang/examples/PluginsOrder/PluginsOrder.cpp
@@ -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", "");

diff  --git a/clang/include/clang/Frontend/FrontendAction.h b/clang/include/clang/Frontend/FrontendAction.h
index dfefddfb45279..039f6f247b6d8 100644
--- a/clang/include/clang/Frontend/FrontendAction.h
+++ b/clang/include/clang/Frontend/FrontendAction.h
@@ -270,17 +270,18 @@ class PluginASTAction : public ASTFrontendAction {
                          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.

diff  --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 6b0a55d79039c..b56db78d3e71a 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -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) &&

diff  --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index dc8409f88dfad..8e18f33af0cbc 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -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())]))

diff  --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 9bf791f93f32e..9a822f2915afd 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -97,6 +97,7 @@ if (CLANG_BUILD_EXAMPLES)
     AnnotateFunctions
     CallSuperAttr
     clang-interpreter
+    PluginsOrder
     PrintFunctionNames
     )
 endif ()

diff  --git a/clang/test/Frontend/plugins-order.c b/clang/test/Frontend/plugins-order.c
new file mode 100644
index 0000000000000..355ec4fb0b257
--- /dev/null
+++ b/clang/test/Frontend/plugins-order.c
@@ -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


        


More information about the cfe-commits mailing list