1199482Srdivacky//===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===//
2199482Srdivacky//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6199482Srdivacky//
7199482Srdivacky//===----------------------------------------------------------------------===//
8249423Sdim///
9249423Sdim/// \file
10341825Sdim/// Defines the clang::FrontendAction interface and various convenience
11249423Sdim/// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction,
12249423Sdim/// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction)
13249423Sdim/// derived from it.
14249423Sdim///
15249423Sdim//===----------------------------------------------------------------------===//
16199482Srdivacky
17199482Srdivacky#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H
18199482Srdivacky#define LLVM_CLANG_FRONTEND_FRONTENDACTION_H
19199482Srdivacky
20280031Sdim#include "clang/AST/ASTConsumer.h"
21226633Sdim#include "clang/Basic/LLVM.h"
22226633Sdim#include "clang/Basic/LangOptions.h"
23280031Sdim#include "clang/Frontend/ASTUnit.h"
24234353Sdim#include "clang/Frontend/FrontendOptions.h"
25199482Srdivacky#include "llvm/ADT/StringRef.h"
26353358Sdim#include "llvm/Support/Error.h"
27276479Sdim#include <memory>
28199482Srdivacky#include <string>
29210299Sed#include <vector>
30199482Srdivacky
31199482Srdivackynamespace clang {
32210299Sedclass ASTMergeAction;
33199482Srdivackyclass CompilerInstance;
34199482Srdivacky
35249423Sdim/// Abstract base class for actions which can be performed by the frontend.
36199482Srdivackyclass FrontendAction {
37234353Sdim  FrontendInputFile CurrentInput;
38276479Sdim  std::unique_ptr<ASTUnit> CurrentASTUnit;
39199482Srdivacky  CompilerInstance *Instance;
40203955Srdivacky  friend class ASTMergeAction;
41224145Sdim  friend class WrapperFrontendAction;
42199482Srdivacky
43218893Sdimprivate:
44280031Sdim  std::unique_ptr<ASTConsumer> CreateWrappedASTConsumer(CompilerInstance &CI,
45280031Sdim                                                        StringRef InFile);
46218893Sdim
47199482Srdivackyprotected:
48199482Srdivacky  /// @name Implementation Action Interface
49199482Srdivacky  /// @{
50199482Srdivacky
51344779Sdim  /// Prepare to execute the action on the given CompilerInstance.
52344779Sdim  ///
53344779Sdim  /// This is called before executing the action on any inputs, and can modify
54344779Sdim  /// the configuration as needed (including adjusting the input list).
55344779Sdim  virtual bool PrepareToExecuteAction(CompilerInstance &CI) { return true; }
56344779Sdim
57341825Sdim  /// Create the AST consumer object for this action, if supported.
58199482Srdivacky  ///
59249423Sdim  /// This routine is called as part of BeginSourceFile(), which will
60199482Srdivacky  /// fail if the AST consumer cannot be created. This will not be called if the
61199482Srdivacky  /// action has indicated that it only uses the preprocessor.
62199482Srdivacky  ///
63249423Sdim  /// \param CI - The current compiler instance, provided as a convenience, see
64199482Srdivacky  /// getCompilerInstance().
65199482Srdivacky  ///
66249423Sdim  /// \param InFile - The current input file, provided as a convenience, see
67199482Srdivacky  /// getCurrentFile().
68199482Srdivacky  ///
69249423Sdim  /// \return The new AST consumer, or null on failure.
70280031Sdim  virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
71280031Sdim                                                         StringRef InFile) = 0;
72199482Srdivacky
73341825Sdim  /// Callback before starting processing a single input, giving the
74224145Sdim  /// opportunity to modify the CompilerInvocation or do some other action
75224145Sdim  /// before BeginSourceFileAction is called.
76224145Sdim  ///
77249423Sdim  /// \return True on success; on failure BeginSourceFileAction(),
78249423Sdim  /// ExecuteAction() and EndSourceFileAction() will not be called.
79224145Sdim  virtual bool BeginInvocation(CompilerInstance &CI) { return true; }
80224145Sdim
81341825Sdim  /// Callback at the start of processing a single input.
82199482Srdivacky  ///
83249423Sdim  /// \return True on success; on failure ExecutionAction() and
84199482Srdivacky  /// EndSourceFileAction() will not be called.
85321369Sdim  virtual bool BeginSourceFileAction(CompilerInstance &CI) {
86199482Srdivacky    return true;
87199482Srdivacky  }
88199482Srdivacky
89341825Sdim  /// Callback to run the program action, using the initialized
90199482Srdivacky  /// compiler instance.
91199482Srdivacky  ///
92249423Sdim  /// This is guaranteed to only be called between BeginSourceFileAction()
93249423Sdim  /// and EndSourceFileAction().
94199482Srdivacky  virtual void ExecuteAction() = 0;
95199482Srdivacky
96341825Sdim  /// Callback at the end of processing a single input.
97249423Sdim  ///
98249423Sdim  /// This is guaranteed to only be called following a successful call to
99234353Sdim  /// BeginSourceFileAction (and BeginSourceFile).
100199482Srdivacky  virtual void EndSourceFileAction() {}
101199482Srdivacky
102341825Sdim  /// Callback at the end of processing a single input, to determine
103261991Sdim  /// if the output files should be erased or not.
104261991Sdim  ///
105261991Sdim  /// By default it returns true if a compiler error occurred.
106261991Sdim  /// This is guaranteed to only be called following a successful call to
107261991Sdim  /// BeginSourceFileAction (and BeginSourceFile).
108261991Sdim  virtual bool shouldEraseOutputFiles();
109261991Sdim
110199482Srdivacky  /// @}
111199482Srdivacky
112199482Srdivackypublic:
113199482Srdivacky  FrontendAction();
114199482Srdivacky  virtual ~FrontendAction();
115199482Srdivacky
116199482Srdivacky  /// @name Compiler Instance Access
117199482Srdivacky  /// @{
118199482Srdivacky
119199482Srdivacky  CompilerInstance &getCompilerInstance() const {
120199482Srdivacky    assert(Instance && "Compiler instance not registered!");
121199482Srdivacky    return *Instance;
122199482Srdivacky  }
123199482Srdivacky
124199482Srdivacky  void setCompilerInstance(CompilerInstance *Value) { Instance = Value; }
125199482Srdivacky
126199482Srdivacky  /// @}
127199482Srdivacky  /// @name Current File Information
128199482Srdivacky  /// @{
129199482Srdivacky
130199482Srdivacky  bool isCurrentFileAST() const {
131243830Sdim    assert(!CurrentInput.isEmpty() && "No current file!");
132276479Sdim    return (bool)CurrentASTUnit;
133199482Srdivacky  }
134199482Srdivacky
135234353Sdim  const FrontendInputFile &getCurrentInput() const {
136234353Sdim    return CurrentInput;
137234353Sdim  }
138309124Sdim
139344779Sdim  StringRef getCurrentFile() const {
140243830Sdim    assert(!CurrentInput.isEmpty() && "No current file!");
141243830Sdim    return CurrentInput.getFile();
142199482Srdivacky  }
143199482Srdivacky
144344779Sdim  StringRef getCurrentFileOrBufferName() const {
145344779Sdim    assert(!CurrentInput.isEmpty() && "No current file!");
146344779Sdim    return CurrentInput.isFile()
147344779Sdim               ? CurrentInput.getFile()
148344779Sdim               : CurrentInput.getBuffer()->getBufferIdentifier();
149344779Sdim  }
150344779Sdim
151210299Sed  InputKind getCurrentFileKind() const {
152243830Sdim    assert(!CurrentInput.isEmpty() && "No current file!");
153243830Sdim    return CurrentInput.getKind();
154210299Sed  }
155210299Sed
156199482Srdivacky  ASTUnit &getCurrentASTUnit() const {
157218893Sdim    assert(CurrentASTUnit && "No current AST unit!");
158199482Srdivacky    return *CurrentASTUnit;
159199482Srdivacky  }
160199482Srdivacky
161321369Sdim  Module *getCurrentModule() const;
162321369Sdim
163280031Sdim  std::unique_ptr<ASTUnit> takeCurrentASTUnit() {
164280031Sdim    return std::move(CurrentASTUnit);
165280031Sdim  }
166203955Srdivacky
167276479Sdim  void setCurrentInput(const FrontendInputFile &CurrentInput,
168280031Sdim                       std::unique_ptr<ASTUnit> AST = nullptr);
169199482Srdivacky
170199482Srdivacky  /// @}
171199482Srdivacky  /// @name Supported Modes
172199482Srdivacky  /// @{
173199482Srdivacky
174341825Sdim  /// Is this action invoked on a model file?
175280031Sdim  ///
176280031Sdim  /// Model files are incomplete translation units that relies on type
177280031Sdim  /// information from another translation unit. Check ParseModelFileAction for
178280031Sdim  /// details.
179280031Sdim  virtual bool isModelParsingAction() const { return false; }
180280031Sdim
181341825Sdim  /// Does this action only use the preprocessor?
182249423Sdim  ///
183249423Sdim  /// If so no AST context will be created and this action will be invalid
184249423Sdim  /// with AST file inputs.
185199482Srdivacky  virtual bool usesPreprocessorOnly() const = 0;
186199482Srdivacky
187341825Sdim  /// For AST-based actions, the kind of translation unit we're handling.
188226633Sdim  virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
189199482Srdivacky
190341825Sdim  /// Does this action support use with PCH?
191321369Sdim  virtual bool hasPCHSupport() const { return true; }
192199482Srdivacky
193341825Sdim  /// Does this action support use with AST files?
194321369Sdim  virtual bool hasASTFileSupport() const { return true; }
195199482Srdivacky
196341825Sdim  /// Does this action support use with IR files?
197210299Sed  virtual bool hasIRSupport() const { return false; }
198210299Sed
199341825Sdim  /// Does this action support use with code completion?
200199482Srdivacky  virtual bool hasCodeCompletionSupport() const { return false; }
201199482Srdivacky
202199482Srdivacky  /// @}
203199482Srdivacky  /// @name Public Action Interface
204199482Srdivacky  /// @{
205199482Srdivacky
206344779Sdim  /// Prepare the action to execute on the given compiler instance.
207344779Sdim  bool PrepareToExecute(CompilerInstance &CI) {
208344779Sdim    return PrepareToExecuteAction(CI);
209344779Sdim  }
210344779Sdim
211341825Sdim  /// Prepare the action for processing the input file \p Input.
212199482Srdivacky  ///
213249423Sdim  /// This is run after the options and frontend have been initialized,
214249423Sdim  /// but prior to executing any per-file processing.
215249423Sdim  ///
216199482Srdivacky  /// \param CI - The compiler instance this action is being run from. The
217199482Srdivacky  /// action may store and use this object up until the matching EndSourceFile
218199482Srdivacky  /// action.
219199482Srdivacky  ///
220234353Sdim  /// \param Input - The input filename and kind. Some input kinds are handled
221210299Sed  /// specially, for example AST inputs, since the AST file itself contains
222210299Sed  /// several objects which would normally be owned by the
223210299Sed  /// CompilerInstance. When processing AST input files, these objects should
224210299Sed  /// generally not be initialized in the CompilerInstance -- they will
225249423Sdim  /// automatically be shared with the AST file in between
226249423Sdim  /// BeginSourceFile() and EndSourceFile().
227199482Srdivacky  ///
228234353Sdim  /// \return True on success; on failure the compilation of this file should
229249423Sdim  /// be aborted and neither Execute() nor EndSourceFile() should be called.
230234353Sdim  bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
231199482Srdivacky
232341825Sdim  /// Set the source manager's main input file, and run the action.
233353358Sdim  llvm::Error Execute();
234199482Srdivacky
235341825Sdim  /// Perform any per-file post processing, deallocate per-file
236199482Srdivacky  /// objects, and run statistics and output file cleanup code.
237199482Srdivacky  void EndSourceFile();
238199482Srdivacky
239199482Srdivacky  /// @}
240199482Srdivacky};
241199482Srdivacky
242341825Sdim/// Abstract base class to use for AST consumer-based frontend actions.
243199482Srdivackyclass ASTFrontendAction : public FrontendAction {
244210299Sedprotected:
245341825Sdim  /// Implement the ExecuteAction interface by running Sema on
246249423Sdim  /// the already-initialized AST consumer.
247199482Srdivacky  ///
248199482Srdivacky  /// This will also take care of instantiating a code completion consumer if
249199482Srdivacky  /// the user requested it and the action supports it.
250276479Sdim  void ExecuteAction() override;
251199482Srdivacky
252199482Srdivackypublic:
253280031Sdim  ASTFrontendAction() {}
254276479Sdim  bool usesPreprocessorOnly() const override { return false; }
255199482Srdivacky};
256199482Srdivacky
257210299Sedclass PluginASTAction : public ASTFrontendAction {
258234353Sdim  virtual void anchor();
259280031Sdimpublic:
260280031Sdim  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
261280031Sdim                                                 StringRef InFile) override = 0;
262210299Sed
263341825Sdim  /// Parse the given plugin command line arguments.
264212904Sdim  ///
265212904Sdim  /// \param CI - The compiler instance, for use in reporting diagnostics.
266212904Sdim  /// \return True if the parsing succeeded; otherwise the plugin will be
267212904Sdim  /// destroyed and no action run. The plugin is responsible for using the
268212904Sdim  /// CompilerInstance's Diagnostic object to report errors.
269212904Sdim  virtual bool ParseArgs(const CompilerInstance &CI,
270212904Sdim                         const std::vector<std::string> &arg) = 0;
271309124Sdim
272309124Sdim  enum ActionType {
273309124Sdim    Cmdline,             ///< Action is determined by the cc1 command-line
274309124Sdim    ReplaceAction,       ///< Replace the main action
275309124Sdim    AddBeforeMainAction, ///< Execute the action before the main action
276309124Sdim    AddAfterMainAction   ///< Execute the action after the main action
277309124Sdim  };
278341825Sdim  /// Get the action type for this plugin
279309124Sdim  ///
280309124Sdim  /// \return The action type. If the type is Cmdline then by default the
281309124Sdim  /// plugin does nothing and what it does is determined by the cc1
282309124Sdim  /// command-line.
283309124Sdim  virtual ActionType getActionType() { return Cmdline; }
284210299Sed};
285210299Sed
286341825Sdim/// Abstract base class to use for preprocessor-based frontend actions.
287199482Srdivackyclass PreprocessorFrontendAction : public FrontendAction {
288199482Srdivackyprotected:
289341825Sdim  /// Provide a default implementation which returns aborts;
290199482Srdivacky  /// this method should never be called by FrontendAction clients.
291280031Sdim  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
292280031Sdim                                                 StringRef InFile) override;
293199482Srdivacky
294199482Srdivackypublic:
295276479Sdim  bool usesPreprocessorOnly() const override { return true; }
296199482Srdivacky};
297199482Srdivacky
298341825Sdim/// A frontend action which simply wraps some other runtime-specified
299249423Sdim/// frontend action.
300249423Sdim///
301249423Sdim/// Deriving from this class allows an action to inject custom logic around
302249423Sdim/// some existing action's behavior. It implements every virtual method in
303249423Sdim/// the FrontendAction interface by forwarding to the wrapped action.
304224145Sdimclass WrapperFrontendAction : public FrontendAction {
305276479Sdim  std::unique_ptr<FrontendAction> WrappedAction;
306224145Sdim
307224145Sdimprotected:
308353358Sdim  bool PrepareToExecuteAction(CompilerInstance &CI) override;
309280031Sdim  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
310280031Sdim                                                 StringRef InFile) override;
311276479Sdim  bool BeginInvocation(CompilerInstance &CI) override;
312321369Sdim  bool BeginSourceFileAction(CompilerInstance &CI) override;
313276479Sdim  void ExecuteAction() override;
314276479Sdim  void EndSourceFileAction() override;
315224145Sdim
316224145Sdimpublic:
317224145Sdim  /// Construct a WrapperFrontendAction from an existing action, taking
318224145Sdim  /// ownership of it.
319309124Sdim  WrapperFrontendAction(std::unique_ptr<FrontendAction> WrappedAction);
320224145Sdim
321276479Sdim  bool usesPreprocessorOnly() const override;
322276479Sdim  TranslationUnitKind getTranslationUnitKind() override;
323276479Sdim  bool hasPCHSupport() const override;
324276479Sdim  bool hasASTFileSupport() const override;
325276479Sdim  bool hasIRSupport() const override;
326276479Sdim  bool hasCodeCompletionSupport() const override;
327224145Sdim};
328224145Sdim
329199482Srdivacky}  // end namespace clang
330199482Srdivacky
331199482Srdivacky#endif
332