1 //===--- MacroPPCallbacks.h -------------------------------------*- 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 //  This file defines implementation for the macro preprocessors callbacks.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_LIB_CODEGEN_MACROPPCALLBACKS_H
14 #define LLVM_CLANG_LIB_CODEGEN_MACROPPCALLBACKS_H
15 
16 #include "clang/Lex/PPCallbacks.h"
17 
18 namespace llvm {
19 class DIMacroFile;
20 class DIMacroNode;
21 }
22 namespace clang {
23 class Preprocessor;
24 class MacroInfo;
25 class CodeGenerator;
26 
27 class MacroPPCallbacks : public PPCallbacks {
28   /// A pointer to code generator, where debug info generator can be found.
29   CodeGenerator *Gen;
30 
31   /// Preprocessor.
32   Preprocessor &PP;
33 
34   /// Location of recent included file, used for line number.
35   SourceLocation LastHashLoc;
36 
37   /// Counts current number of command line included files, which were entered
38   /// and were not exited yet.
39   int EnteredCommandLineIncludeFiles = 0;
40 
41   enum FileScopeStatus {
42     NoScope = 0,              // Scope is not initialized yet.
43     InitializedScope,         // Main file scope is initialized but not set yet.
44     BuiltinScope,             // <built-in> and <command line> file scopes.
45     CommandLineIncludeScope,  // Included file, from <command line> file, scope.
46     MainFileScope             // Main file scope.
47   };
48   FileScopeStatus Status;
49 
50   /// Parent contains all entered files that were not exited yet according to
51   /// the inclusion order.
52   llvm::SmallVector<llvm::DIMacroFile *, 4> Scopes;
53 
54   /// Get current DIMacroFile scope.
55   /// \return current DIMacroFile scope or nullptr if there is no such scope.
56   llvm::DIMacroFile *getCurrentScope();
57 
58   /// Get current line location or invalid location.
59   /// \param Loc current line location.
60   /// \return current line location \p `Loc`, or invalid location if it's in a
61   ///         skipped file scope.
62   SourceLocation getCorrectLocation(SourceLocation Loc);
63 
64   /// Use the passed preprocessor to write the macro name and value from the
65   /// given macro info and identifier info into the given \p `Name` and \p
66   /// `Value` output streams.
67   ///
68   /// \param II Identifier info, used to get the Macro name.
69   /// \param MI Macro info, used to get the Macro argumets and values.
70   /// \param PP Preprocessor.
71   /// \param [out] Name Place holder for returned macro name and arguments.
72   /// \param [out] Value Place holder for returned macro value.
73   static void writeMacroDefinition(const IdentifierInfo &II,
74                                    const MacroInfo &MI, Preprocessor &PP,
75                                    raw_ostream &Name, raw_ostream &Value);
76 
77   /// Update current file scope status to next file scope.
78   void updateStatusToNextScope();
79 
80   /// Handle the case when entering a file.
81   ///
82   /// \param Loc Indicates the new location.
83   void FileEntered(SourceLocation Loc);
84 
85   /// Handle the case when exiting a file.
86   ///
87   /// \param Loc Indicates the new location.
88   void FileExited(SourceLocation Loc);
89 
90 public:
91   MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP);
92 
93   /// Callback invoked whenever a source file is entered or exited.
94   ///
95   /// \param Loc Indicates the new location.
96   /// \param PrevFID the file that was exited if \p Reason is ExitFile.
97   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
98                    SrcMgr::CharacteristicKind FileType,
99                    FileID PrevFID = FileID()) override;
100 
101   /// Callback invoked whenever a directive (#xxx) is processed.
102   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
103                           StringRef FileName, bool IsAngled,
104                           CharSourceRange FilenameRange, const FileEntry *File,
105                           StringRef SearchPath, StringRef RelativePath,
106                           const Module *Imported,
107                           SrcMgr::CharacteristicKind FileType) override;
108 
109   /// Hook called whenever a macro definition is seen.
110   void MacroDefined(const Token &MacroNameTok,
111                     const MacroDirective *MD) override;
112 
113   /// Hook called whenever a macro \#undef is seen.
114   ///
115   /// MD is released immediately following this callback.
116   void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
117                       const MacroDirective *Undef) override;
118 };
119 
120 } // end namespace clang
121 
122 #endif
123