Eugene Zelenko | 8615047 | 2016-11-29 18:24:01 +0000 | [diff] [blame] | 1 | //===--- PPCallbacksTracker.h - Preprocessor tracking -----------*- C++ -*-===// |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
Eugene Zelenko | 8615047 | 2016-11-29 18:24:01 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 9 | /// |
| 10 | /// \file |
| 11 | /// \brief Classes and definitions for preprocessor tracking. |
| 12 | /// |
| 13 | /// The core definition is the PPCallbacksTracker class, derived from Clang's |
| 14 | /// PPCallbacks class from the Lex library, which overrides all the callbacks |
| 15 | /// and collects information about each callback call, saving it in a |
| 16 | /// data structure built up of CallbackCall and Argument objects, which |
| 17 | /// record the preprocessor callback name and arguments in high-level string |
| 18 | /// form for later inspection. |
| 19 | /// |
Eugene Zelenko | 8615047 | 2016-11-29 18:24:01 +0000 | [diff] [blame] | 20 | //===----------------------------------------------------------------------===// |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 21 | |
| 22 | #ifndef PPTRACE_PPCALLBACKSTRACKER_H |
| 23 | #define PPTRACE_PPCALLBACKSTRACKER_H |
| 24 | |
| 25 | #include "clang/Lex/PPCallbacks.h" |
| 26 | #include "clang/Lex/Preprocessor.h" |
Eugene Zelenko | 8615047 | 2016-11-29 18:24:01 +0000 | [diff] [blame] | 27 | #include "clang/Basic/SourceManager.h" |
| 28 | #include "llvm/ADT/ArrayRef.h" |
| 29 | #include "llvm/ADT/SmallSet.h" |
| 30 | #include "llvm/ADT/StringRef.h" |
| 31 | #include <string> |
| 32 | #include <vector> |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 33 | |
| 34 | /// \brief This class represents one callback function argument by name |
| 35 | /// and value. |
| 36 | class Argument { |
| 37 | public: |
| 38 | Argument(llvm::StringRef Name, llvm::StringRef Value) |
| 39 | : Name(Name), Value(Value) {} |
Eugene Zelenko | 8615047 | 2016-11-29 18:24:01 +0000 | [diff] [blame] | 40 | Argument() = default; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 41 | |
| 42 | std::string Name; |
| 43 | std::string Value; |
| 44 | }; |
| 45 | |
| 46 | /// \brief This class represents one callback call by name and an array |
| 47 | /// of arguments. |
| 48 | class CallbackCall { |
| 49 | public: |
| 50 | CallbackCall(llvm::StringRef Name) : Name(Name) {} |
Eugene Zelenko | 8615047 | 2016-11-29 18:24:01 +0000 | [diff] [blame] | 51 | CallbackCall() = default; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 52 | |
| 53 | std::string Name; |
| 54 | std::vector<Argument> Arguments; |
| 55 | }; |
| 56 | |
| 57 | /// \brief This class overrides the PPCallbacks class for tracking preprocessor |
| 58 | /// activity by means of its callback functions. |
| 59 | /// |
| 60 | /// This object is given a vector for storing the trace information, built up |
| 61 | /// of CallbackCall and subordinate Argument objects for representing the |
| 62 | /// callback calls and their arguments. It's a reference so the vector can |
| 63 | /// exist beyond the lifetime of this object, because it's deleted by the |
| 64 | /// preprocessor automatically in its destructor. |
| 65 | /// |
| 66 | /// This class supports a mechanism for inhibiting trace output for |
| 67 | /// specific callbacks by name, for the purpose of eliminating output for |
| 68 | /// callbacks of no interest that might clutter the output. |
| 69 | /// |
| 70 | /// Following the constructor and destructor function declarations, the |
| 71 | /// overidden callback functions are defined. The remaining functions are |
| 72 | /// helpers for recording the trace data, to reduce the coupling between it |
| 73 | /// and the recorded data structure. |
| 74 | class PPCallbacksTracker : public clang::PPCallbacks { |
| 75 | public: |
| 76 | /// \brief Note that all of the arguments are references, and owned |
| 77 | /// by the caller. |
| 78 | /// \param Ignore - Set of names of callbacks to ignore. |
| 79 | /// \param CallbackCalls - Trace buffer. |
| 80 | /// \param PP - The preprocessor. Needed for getting some argument strings. |
| 81 | PPCallbacksTracker(llvm::SmallSet<std::string, 4> &Ignore, |
| 82 | std::vector<CallbackCall> &CallbackCalls, |
| 83 | clang::Preprocessor &PP); |
| 84 | |
Alexander Kornienko | 87638f6 | 2015-04-11 07:59:33 +0000 | [diff] [blame] | 85 | ~PPCallbacksTracker() override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 86 | |
| 87 | // Overidden callback functions. |
| 88 | |
| 89 | void FileChanged(clang::SourceLocation Loc, |
| 90 | clang::PPCallbacks::FileChangeReason Reason, |
| 91 | clang::SrcMgr::CharacteristicKind FileType, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 92 | clang::FileID PrevFID = clang::FileID()) override; |
Nikola Smiljanic | 90476a5 | 2015-05-12 11:48:21 +0000 | [diff] [blame] | 93 | void FileSkipped(const clang::FileEntry &SkippedFile, |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 94 | const clang::Token &FilenameTok, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 95 | clang::SrcMgr::CharacteristicKind FileType) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 96 | bool FileNotFound(llvm::StringRef FileName, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 97 | llvm::SmallVectorImpl<char> &RecoveryPath) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 98 | void InclusionDirective(clang::SourceLocation HashLoc, |
| 99 | const clang::Token &IncludeTok, |
| 100 | llvm::StringRef FileName, bool IsAngled, |
| 101 | clang::CharSourceRange FilenameRange, |
| 102 | const clang::FileEntry *File, |
| 103 | llvm::StringRef SearchPath, |
| 104 | llvm::StringRef RelativePath, |
Julie Hockett | 546943f | 2018-05-10 19:13:14 +0000 | [diff] [blame] | 105 | const clang::Module *Imported, |
| 106 | clang::SrcMgr::CharacteristicKind FileType) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 107 | void moduleImport(clang::SourceLocation ImportLoc, clang::ModuleIdPath Path, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 108 | const clang::Module *Imported) override; |
| 109 | void EndOfMainFile() override; |
Rafael Espindola | d218565 | 2015-06-01 20:00:20 +0000 | [diff] [blame] | 110 | void Ident(clang::SourceLocation Loc, llvm::StringRef str) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 111 | void PragmaDirective(clang::SourceLocation Loc, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 112 | clang::PragmaIntroducerKind Introducer) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 113 | void PragmaComment(clang::SourceLocation Loc, |
| 114 | const clang::IdentifierInfo *Kind, |
Rafael Espindola | d218565 | 2015-06-01 20:00:20 +0000 | [diff] [blame] | 115 | llvm::StringRef Str) override; |
| 116 | void PragmaDetectMismatch(clang::SourceLocation Loc, llvm::StringRef Name, |
| 117 | llvm::StringRef Value) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 118 | void PragmaDebug(clang::SourceLocation Loc, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 119 | llvm::StringRef DebugType) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 120 | void PragmaMessage(clang::SourceLocation Loc, llvm::StringRef Namespace, |
| 121 | clang::PPCallbacks::PragmaMessageKind Kind, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 122 | llvm::StringRef Str) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 123 | void PragmaDiagnosticPush(clang::SourceLocation Loc, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 124 | llvm::StringRef Namespace) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 125 | void PragmaDiagnosticPop(clang::SourceLocation Loc, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 126 | llvm::StringRef Namespace) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 127 | void PragmaDiagnostic(clang::SourceLocation Loc, llvm::StringRef Namespace, |
Alp Toker | 9d63b5e | 2014-06-10 09:58:45 +0000 | [diff] [blame] | 128 | clang::diag::Severity mapping, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 129 | llvm::StringRef Str) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 130 | void PragmaOpenCLExtension(clang::SourceLocation NameLoc, |
| 131 | const clang::IdentifierInfo *Name, |
| 132 | clang::SourceLocation StateLoc, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 133 | unsigned State) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 134 | void PragmaWarning(clang::SourceLocation Loc, llvm::StringRef WarningSpec, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 135 | llvm::ArrayRef<int> Ids) override; |
| 136 | void PragmaWarningPush(clang::SourceLocation Loc, int Level) override; |
| 137 | void PragmaWarningPop(clang::SourceLocation Loc) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 138 | void MacroExpands(const clang::Token &MacroNameTok, |
Richard Smith | 33de856 | 2015-05-04 03:15:55 +0000 | [diff] [blame] | 139 | const clang::MacroDefinition &MD, clang::SourceRange Range, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 140 | const clang::MacroArgs *Args) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 141 | void MacroDefined(const clang::Token &MacroNameTok, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 142 | const clang::MacroDirective *MD) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 143 | void MacroUndefined(const clang::Token &MacroNameTok, |
David Blaikie | 5c4ec7c | 2017-04-26 20:58:03 +0000 | [diff] [blame] | 144 | const clang::MacroDefinition &MD, |
| 145 | const clang::MacroDirective *Undef) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 146 | void Defined(const clang::Token &MacroNameTok, |
Richard Smith | 33de856 | 2015-05-04 03:15:55 +0000 | [diff] [blame] | 147 | const clang::MacroDefinition &MD, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 148 | clang::SourceRange Range) override; |
Vedant Kumar | 5490afa | 2017-09-11 20:47:45 +0000 | [diff] [blame] | 149 | void SourceRangeSkipped(clang::SourceRange Range, |
| 150 | clang::SourceLocation EndifLoc) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 151 | void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 152 | ConditionValueKind ConditionValue) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 153 | void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 154 | ConditionValueKind ConditionValue, clang::SourceLocation IfLoc) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 155 | void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, |
Richard Smith | 33de856 | 2015-05-04 03:15:55 +0000 | [diff] [blame] | 156 | const clang::MacroDefinition &MD) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 157 | void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, |
Richard Smith | 33de856 | 2015-05-04 03:15:55 +0000 | [diff] [blame] | 158 | const clang::MacroDefinition &MD) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 159 | void Else(clang::SourceLocation Loc, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 160 | clang::SourceLocation IfLoc) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 161 | void Endif(clang::SourceLocation Loc, |
Craig Topper | a3dbe84 | 2014-03-02 10:20:11 +0000 | [diff] [blame] | 162 | clang::SourceLocation IfLoc) override; |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 163 | |
| 164 | // Helper functions. |
| 165 | |
| 166 | /// \brief Start a new callback. |
| 167 | void beginCallback(const char *Name); |
| 168 | |
| 169 | /// \brief Append a string to the top trace item. |
| 170 | void append(const char *Str); |
| 171 | |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 172 | /// \brief Append a bool argument to the top trace item. |
| 173 | void appendArgument(const char *Name, bool Value); |
| 174 | |
| 175 | /// \brief Append an int argument to the top trace item. |
| 176 | void appendArgument(const char *Name, int Value); |
| 177 | |
| 178 | /// \brief Append a string argument to the top trace item. |
| 179 | void appendArgument(const char *Name, const char *Value); |
| 180 | |
| 181 | /// \brief Append a string reference object argument to the top trace item. |
| 182 | void appendArgument(const char *Name, llvm::StringRef Value); |
| 183 | |
| 184 | /// \brief Append a string object argument to the top trace item. |
| 185 | void appendArgument(const char *Name, const std::string &Value); |
| 186 | |
| 187 | /// \brief Append a token argument to the top trace item. |
| 188 | void appendArgument(const char *Name, const clang::Token &Value); |
| 189 | |
| 190 | /// \brief Append an enum argument to the top trace item. |
Craig Topper | 45857d4 | 2015-10-18 05:14:41 +0000 | [diff] [blame] | 191 | void appendArgument(const char *Name, int Value, const char *const Strings[]); |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 192 | |
| 193 | /// \brief Append a FileID argument to the top trace item. |
| 194 | void appendArgument(const char *Name, clang::FileID Value); |
| 195 | |
| 196 | /// \brief Append a FileEntry argument to the top trace item. |
| 197 | void appendArgument(const char *Name, const clang::FileEntry *Value); |
| 198 | |
| 199 | /// \brief Append a SourceLocation argument to the top trace item. |
| 200 | void appendArgument(const char *Name, clang::SourceLocation Value); |
| 201 | |
| 202 | /// \brief Append a SourceRange argument to the top trace item. |
| 203 | void appendArgument(const char *Name, clang::SourceRange Value); |
| 204 | |
| 205 | /// \brief Append a CharSourceRange argument to the top trace item. |
| 206 | void appendArgument(const char *Name, clang::CharSourceRange Value); |
| 207 | |
| 208 | /// \brief Append a ModuleIdPath argument to the top trace item. |
| 209 | void appendArgument(const char *Name, clang::ModuleIdPath Value); |
| 210 | |
| 211 | /// \brief Append an IdentifierInfo argument to the top trace item. |
| 212 | void appendArgument(const char *Name, const clang::IdentifierInfo *Value); |
| 213 | |
| 214 | /// \brief Append a MacroDirective argument to the top trace item. |
| 215 | void appendArgument(const char *Name, const clang::MacroDirective *Value); |
| 216 | |
Richard Smith | 33de856 | 2015-05-04 03:15:55 +0000 | [diff] [blame] | 217 | /// \brief Append a MacroDefinition argument to the top trace item. |
| 218 | void appendArgument(const char *Name, const clang::MacroDefinition &Value); |
| 219 | |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 220 | /// \brief Append a MacroArgs argument to the top trace item. |
| 221 | void appendArgument(const char *Name, const clang::MacroArgs *Value); |
| 222 | |
| 223 | /// \brief Append a Module argument to the top trace item. |
| 224 | void appendArgument(const char *Name, const clang::Module *Value); |
| 225 | |
| 226 | /// \brief Append a double-quoted argument to the top trace item. |
Yaron Keren | 40178c3 | 2015-07-03 09:30:33 +0000 | [diff] [blame] | 227 | void appendQuotedArgument(const char *Name, const std::string &Value); |
John Thompson | 9979454 | 2013-10-31 12:23:32 +0000 | [diff] [blame] | 228 | |
| 229 | /// \brief Append a double-quoted file path argument to the top trace item. |
| 230 | void appendFilePathArgument(const char *Name, llvm::StringRef Value); |
| 231 | |
| 232 | /// \brief Get the raw source string of the range. |
| 233 | llvm::StringRef getSourceString(clang::CharSourceRange Range); |
| 234 | |
| 235 | /// \brief Callback trace information. |
| 236 | /// We use a reference so the trace will be preserved for the caller |
| 237 | /// after this object is destructed. |
| 238 | std::vector<CallbackCall> &CallbackCalls; |
| 239 | |
| 240 | /// \brief Names of callbacks to ignore. |
| 241 | llvm::SmallSet<std::string, 4> &Ignore; |
| 242 | |
| 243 | /// \brief Inhibit trace while this is set. |
| 244 | bool DisableTrace; |
| 245 | |
| 246 | clang::Preprocessor &PP; |
| 247 | }; |
| 248 | |
| 249 | #endif // PPTRACE_PPCALLBACKSTRACKER_H |