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 31namespace clang { 32class ASTMergeAction; 33class CompilerInstance; 34 35/// Abstract base class for actions which can be performed by the frontend. 36class FrontendAction { 37 FrontendInputFile CurrentInput; 38 std::unique_ptr<ASTUnit> CurrentASTUnit; 39 CompilerInstance *Instance; 40 friend class ASTMergeAction; 41 friend class WrapperFrontendAction; 42 43private: 44 std::unique_ptr<ASTConsumer> CreateWrappedASTConsumer(CompilerInstance &CI, 45 StringRef InFile); 46 47protected: 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 112public: 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 void EndSourceFile(); 238 239 /// @} 240}; 241 242/// Abstract base class to use for AST consumer-based frontend actions. 243class ASTFrontendAction : public FrontendAction { 244protected: 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 252public: 253 ASTFrontendAction() {} 254 bool usesPreprocessorOnly() const override { return false; } 255}; 256 257class PluginASTAction : public ASTFrontendAction { 258 virtual void anchor(); 259public: 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. 287class PreprocessorFrontendAction : public FrontendAction { 288protected: 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 294public: 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. 304class WrapperFrontendAction : public FrontendAction { 305 std::unique_ptr<FrontendAction> WrappedAction; 306 307protected: 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 EndSourceFileAction() override; 315 bool shouldEraseOutputFiles() override; 316 317public: 318 /// Construct a WrapperFrontendAction from an existing action, taking 319 /// ownership of it. 320 WrapperFrontendAction(std::unique_ptr<FrontendAction> WrappedAction); 321 322 bool usesPreprocessorOnly() const override; 323 TranslationUnitKind getTranslationUnitKind() override; 324 bool hasPCHSupport() const override; 325 bool hasASTFileSupport() const override; 326 bool hasIRSupport() const override; 327 bool hasCodeCompletionSupport() const override; 328}; 329 330} // end namespace clang 331 332#endif 333