Home | History | Annotate | Line # | Download | only in Frontend
      1 //===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 ///
      9 /// \file
     10 /// Defines the clang::FrontendAction interface and various convenience
     11 /// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction,
     12 /// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction)
     13 /// derived from it.
     14 ///
     15 //===----------------------------------------------------------------------===//
     16 
     17 #ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H
     18 #define LLVM_CLANG_FRONTEND_FRONTENDACTION_H
     19 
     20 #include "clang/AST/ASTConsumer.h"
     21 #include "clang/Basic/LLVM.h"
     22 #include "clang/Basic/LangOptions.h"
     23 #include "clang/Frontend/ASTUnit.h"
     24 #include "clang/Frontend/FrontendOptions.h"
     25 #include "llvm/ADT/StringRef.h"
     26 #include "llvm/Support/Error.h"
     27 #include <memory>
     28 #include <string>
     29 #include <vector>
     30 
     31 namespace clang {
     32 class ASTMergeAction;
     33 class CompilerInstance;
     34 
     35 /// Abstract base class for actions which can be performed by the frontend.
     36 class FrontendAction {
     37   FrontendInputFile CurrentInput;
     38   std::unique_ptr<ASTUnit> CurrentASTUnit;
     39   CompilerInstance *Instance;
     40   friend class ASTMergeAction;
     41   friend class WrapperFrontendAction;
     42 
     43 private:
     44   std::unique_ptr<ASTConsumer> CreateWrappedASTConsumer(CompilerInstance &CI,
     45                                                         StringRef InFile);
     46 
     47 protected:
     48   /// @name Implementation Action Interface
     49   /// @{
     50 
     51   /// Prepare to execute the action on the given CompilerInstance.
     52   ///
     53   /// This is called before executing the action on any inputs, and can modify
     54   /// the configuration as needed (including adjusting the input list).
     55   virtual bool PrepareToExecuteAction(CompilerInstance &CI) { return true; }
     56 
     57   /// Create the AST consumer object for this action, if supported.
     58   ///
     59   /// This routine is called as part of BeginSourceFile(), which will
     60   /// fail if the AST consumer cannot be created. This will not be called if the
     61   /// action has indicated that it only uses the preprocessor.
     62   ///
     63   /// \param CI - The current compiler instance, provided as a convenience, see
     64   /// getCompilerInstance().
     65   ///
     66   /// \param InFile - The current input file, provided as a convenience, see
     67   /// getCurrentFile().
     68   ///
     69   /// \return The new AST consumer, or null on failure.
     70   virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
     71                                                          StringRef InFile) = 0;
     72 
     73   /// Callback before starting processing a single input, giving the
     74   /// opportunity to modify the CompilerInvocation or do some other action
     75   /// before BeginSourceFileAction is called.
     76   ///
     77   /// \return True on success; on failure BeginSourceFileAction(),
     78   /// ExecuteAction() and EndSourceFileAction() will not be called.
     79   virtual bool BeginInvocation(CompilerInstance &CI) { return true; }
     80 
     81   /// Callback at the start of processing a single input.
     82   ///
     83   /// \return True on success; on failure ExecutionAction() and
     84   /// EndSourceFileAction() will not be called.
     85   virtual bool BeginSourceFileAction(CompilerInstance &CI) {
     86     return true;
     87   }
     88 
     89   /// Callback to run the program action, using the initialized
     90   /// compiler instance.
     91   ///
     92   /// This is guaranteed to only be called between BeginSourceFileAction()
     93   /// and EndSourceFileAction().
     94   virtual void ExecuteAction() = 0;
     95 
     96   /// Callback at the end of processing a single input.
     97   ///
     98   /// This is guaranteed to only be called following a successful call to
     99   /// BeginSourceFileAction (and BeginSourceFile).
    100   virtual void EndSourceFileAction() {}
    101 
    102   /// Callback at the end of processing a single input, to determine
    103   /// if the output files should be erased or not.
    104   ///
    105   /// By default it returns true if a compiler error occurred.
    106   /// This is guaranteed to only be called following a successful call to
    107   /// BeginSourceFileAction (and BeginSourceFile).
    108   virtual bool shouldEraseOutputFiles();
    109 
    110   /// @}
    111 
    112 public:
    113   FrontendAction();
    114   virtual ~FrontendAction();
    115 
    116   /// @name Compiler Instance Access
    117   /// @{
    118 
    119   CompilerInstance &getCompilerInstance() const {
    120     assert(Instance && "Compiler instance not registered!");
    121     return *Instance;
    122   }
    123 
    124   void setCompilerInstance(CompilerInstance *Value) { Instance = Value; }
    125 
    126   /// @}
    127   /// @name Current File Information
    128   /// @{
    129 
    130   bool isCurrentFileAST() const {
    131     assert(!CurrentInput.isEmpty() && "No current file!");
    132     return (bool)CurrentASTUnit;
    133   }
    134 
    135   const FrontendInputFile &getCurrentInput() const {
    136     return CurrentInput;
    137   }
    138 
    139   StringRef getCurrentFile() const {
    140     assert(!CurrentInput.isEmpty() && "No current file!");
    141     return CurrentInput.getFile();
    142   }
    143 
    144   StringRef getCurrentFileOrBufferName() const {
    145     assert(!CurrentInput.isEmpty() && "No current file!");
    146     return CurrentInput.isFile()
    147                ? CurrentInput.getFile()
    148                : CurrentInput.getBuffer().getBufferIdentifier();
    149   }
    150 
    151   InputKind getCurrentFileKind() const {
    152     assert(!CurrentInput.isEmpty() && "No current file!");
    153     return CurrentInput.getKind();
    154   }
    155 
    156   ASTUnit &getCurrentASTUnit() const {
    157     assert(CurrentASTUnit && "No current AST unit!");
    158     return *CurrentASTUnit;
    159   }
    160 
    161   Module *getCurrentModule() const;
    162 
    163   std::unique_ptr<ASTUnit> takeCurrentASTUnit() {
    164     return std::move(CurrentASTUnit);
    165   }
    166 
    167   void setCurrentInput(const FrontendInputFile &CurrentInput,
    168                        std::unique_ptr<ASTUnit> AST = nullptr);
    169 
    170   /// @}
    171   /// @name Supported Modes
    172   /// @{
    173 
    174   /// Is this action invoked on a model file?
    175   ///
    176   /// Model files are incomplete translation units that relies on type
    177   /// information from another translation unit. Check ParseModelFileAction for
    178   /// details.
    179   virtual bool isModelParsingAction() const { return false; }
    180 
    181   /// Does this action only use the preprocessor?
    182   ///
    183   /// If so no AST context will be created and this action will be invalid
    184   /// with AST file inputs.
    185   virtual bool usesPreprocessorOnly() const = 0;
    186 
    187   /// For AST-based actions, the kind of translation unit we're handling.
    188   virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
    189 
    190   /// Does this action support use with PCH?
    191   virtual bool hasPCHSupport() const { return true; }
    192 
    193   /// Does this action support use with AST files?
    194   virtual bool hasASTFileSupport() const { return true; }
    195 
    196   /// Does this action support use with IR files?
    197   virtual bool hasIRSupport() const { return false; }
    198 
    199   /// Does this action support use with code completion?
    200   virtual bool hasCodeCompletionSupport() const { return false; }
    201 
    202   /// @}
    203   /// @name Public Action Interface
    204   /// @{
    205 
    206   /// Prepare the action to execute on the given compiler instance.
    207   bool PrepareToExecute(CompilerInstance &CI) {
    208     return PrepareToExecuteAction(CI);
    209   }
    210 
    211   /// Prepare the action for processing the input file \p Input.
    212   ///
    213   /// This is run after the options and frontend have been initialized,
    214   /// but prior to executing any per-file processing.
    215   ///
    216   /// \param CI - The compiler instance this action is being run from. The
    217   /// action may store and use this object up until the matching EndSourceFile
    218   /// action.
    219   ///
    220   /// \param Input - The input filename and kind. Some input kinds are handled
    221   /// specially, for example AST inputs, since the AST file itself contains
    222   /// several objects which would normally be owned by the
    223   /// CompilerInstance. When processing AST input files, these objects should
    224   /// generally not be initialized in the CompilerInstance -- they will
    225   /// automatically be shared with the AST file in between
    226   /// BeginSourceFile() and EndSourceFile().
    227   ///
    228   /// \return True on success; on failure the compilation of this file should
    229   /// be aborted and neither Execute() nor EndSourceFile() should be called.
    230   bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
    231 
    232   /// Set the source manager's main input file, and run the action.
    233   llvm::Error Execute();
    234 
    235   /// Perform any per-file post processing, deallocate per-file
    236   /// objects, and run statistics and output file cleanup code.
    237   virtual void EndSourceFile();
    238 
    239   /// @}
    240 };
    241 
    242 /// Abstract base class to use for AST consumer-based frontend actions.
    243 class ASTFrontendAction : public FrontendAction {
    244 protected:
    245   /// Implement the ExecuteAction interface by running Sema on
    246   /// the already-initialized AST consumer.
    247   ///
    248   /// This will also take care of instantiating a code completion consumer if
    249   /// the user requested it and the action supports it.
    250   void ExecuteAction() override;
    251 
    252 public:
    253   ASTFrontendAction() {}
    254   bool usesPreprocessorOnly() const override { return false; }
    255 };
    256 
    257 class PluginASTAction : public ASTFrontendAction {
    258   virtual void anchor();
    259 public:
    260   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
    261                                                  StringRef InFile) override = 0;
    262 
    263   /// Parse the given plugin command line arguments.
    264   ///
    265   /// \param CI - The compiler instance, for use in reporting diagnostics.
    266   /// \return True if the parsing succeeded; otherwise the plugin will be
    267   /// destroyed and no action run. The plugin is responsible for using the
    268   /// CompilerInstance's Diagnostic object to report errors.
    269   virtual bool ParseArgs(const CompilerInstance &CI,
    270                          const std::vector<std::string> &arg) = 0;
    271 
    272   enum ActionType {
    273     Cmdline,             ///< Action is determined by the cc1 command-line
    274     ReplaceAction,       ///< Replace the main action
    275     AddBeforeMainAction, ///< Execute the action before the main action
    276     AddAfterMainAction   ///< Execute the action after the main action
    277   };
    278   /// Get the action type for this plugin
    279   ///
    280   /// \return The action type. If the type is Cmdline then by default the
    281   /// plugin does nothing and what it does is determined by the cc1
    282   /// command-line.
    283   virtual ActionType getActionType() { return Cmdline; }
    284 };
    285 
    286 /// Abstract base class to use for preprocessor-based frontend actions.
    287 class PreprocessorFrontendAction : public FrontendAction {
    288 protected:
    289   /// Provide a default implementation which returns aborts;
    290   /// this method should never be called by FrontendAction clients.
    291   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
    292                                                  StringRef InFile) override;
    293 
    294 public:
    295   bool usesPreprocessorOnly() const override { return true; }
    296 };
    297 
    298 /// A frontend action which simply wraps some other runtime-specified
    299 /// frontend action.
    300 ///
    301 /// Deriving from this class allows an action to inject custom logic around
    302 /// some existing action's behavior. It implements every virtual method in
    303 /// the FrontendAction interface by forwarding to the wrapped action.
    304 class WrapperFrontendAction : public FrontendAction {
    305 protected:
    306   std::unique_ptr<FrontendAction> WrappedAction;
    307 
    308   bool PrepareToExecuteAction(CompilerInstance &CI) override;
    309   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
    310                                                  StringRef InFile) override;
    311   bool BeginInvocation(CompilerInstance &CI) override;
    312   bool BeginSourceFileAction(CompilerInstance &CI) override;
    313   void ExecuteAction() override;
    314   void EndSourceFile() override;
    315   void EndSourceFileAction() override;
    316   bool shouldEraseOutputFiles() override;
    317 
    318 public:
    319   /// Construct a WrapperFrontendAction from an existing action, taking
    320   /// ownership of it.
    321   WrapperFrontendAction(std::unique_ptr<FrontendAction> WrappedAction);
    322 
    323   bool usesPreprocessorOnly() const override;
    324   TranslationUnitKind getTranslationUnitKind() override;
    325   bool hasPCHSupport() const override;
    326   bool hasASTFileSupport() const override;
    327   bool hasIRSupport() const override;
    328   bool hasCodeCompletionSupport() const override;
    329 };
    330 
    331 }  // end namespace clang
    332 
    333 #endif
    334