1 //===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- C++ -*-===// 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 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the PPCallbacks interface. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_LEX_PPCALLBACKS_H 15 #define LLVM_CLANG_LEX_PPCALLBACKS_H 16 17 #include "clang/Lex/DirectoryLookup.h" 18 #include "clang/Basic/SourceLocation.h" 19 #include "clang/Basic/DiagnosticIDs.h" 20 #include "llvm/ADT/StringRef.h" 21 #include <string> 22 23 namespace clang { 24 class SourceLocation; 25 class Token; 26 class IdentifierInfo; 27 class MacroInfo; 28 29 /// PPCallbacks - This interface provides a way to observe the actions of the 30 /// preprocessor as it does its thing. Clients can define their hooks here to 31 /// implement preprocessor level tools. 32 class PPCallbacks { 33 public: 34 virtual ~PPCallbacks(); 35 36 enum FileChangeReason { 37 EnterFile, ExitFile, SystemHeaderPragma, RenameFile 38 }; 39 40 /// FileChanged - This callback is invoked whenever a source file is 41 /// entered or exited. The SourceLocation indicates the new location, and 42 /// EnteringFile indicates whether this is because we are entering a new 43 /// #include'd file (when true) or whether we're exiting one because we ran 44 /// off the end (when false). 45 /// 46 /// \param PrevFID the file that was exited if \arg Reason is ExitFile. 47 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 48 SrcMgr::CharacteristicKind FileType, 49 FileID PrevFID = FileID()) { 50 } 51 52 /// FileSkipped - This callback is invoked whenever a source file is 53 /// skipped as the result of header guard optimization. ParentFile 54 /// is the file that #includes the skipped file. FilenameTok is the 55 /// token in ParentFile that indicates the skipped file. 56 virtual void FileSkipped(const FileEntry &ParentFile, 57 const Token &FilenameTok, 58 SrcMgr::CharacteristicKind FileType) { 59 } 60 61 /// \brief This callback is invoked whenever an inclusion directive of 62 /// any kind (\c #include, \c #import, etc.) has been processed, regardless 63 /// of whether the inclusion will actually result in an inclusion. 64 /// 65 /// \param HashLoc The location of the '#' that starts the inclusion 66 /// directive. 67 /// 68 /// \param IncludeTok The token that indicates the kind of inclusion 69 /// directive, e.g., 'include' or 'import'. 70 /// 71 /// \param FileName The name of the file being included, as written in the 72 /// source code. 73 /// 74 /// \param IsAngled Whether the file name was enclosed in angle brackets; 75 /// otherwise, it was enclosed in quotes. 76 /// 77 /// \param File The actual file that may be included by this inclusion 78 /// directive. 79 /// 80 /// \param EndLoc The location of the last token within the inclusion 81 /// directive. 82 /// 83 /// \param SearchPath Contains the search path which was used to find the file 84 /// in the file system. If the file was found via an absolute include path, 85 /// SearchPath will be empty. For framework includes, the SearchPath and 86 /// RelativePath will be split up. For example, if an include of "Some/Some.h" 87 /// is found via the framework path 88 /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be 89 /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be 90 /// "Some.h". 91 /// 92 /// \param RelativePath The path relative to SearchPath, at which the include 93 /// file was found. This is equal to FileName except for framework includes. 94 virtual void InclusionDirective(SourceLocation HashLoc, 95 const Token &IncludeTok, 96 StringRef FileName, 97 bool IsAngled, 98 const FileEntry *File, 99 SourceLocation EndLoc, 100 StringRef SearchPath, 101 StringRef RelativePath) { 102 } 103 104 /// EndOfMainFile - This callback is invoked when the end of the main file is 105 /// reach, no subsequent callbacks will be made. 106 virtual void EndOfMainFile() { 107 } 108 109 /// Ident - This callback is invoked when a #ident or #sccs directive is read. 110 /// \param Loc The location of the directive. 111 /// \param str The text of the directive. 112 /// 113 virtual void Ident(SourceLocation Loc, const std::string &str) { 114 } 115 116 /// PragmaComment - This callback is invoked when a #pragma comment directive 117 /// is read. 118 /// 119 virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 120 const std::string &Str) { 121 } 122 123 /// PragmaMessage - This callback is invoked when a #pragma message directive 124 /// is read. 125 /// \param Loc The location of the message directive. 126 /// \param str The text of the message directive. 127 /// 128 virtual void PragmaMessage(SourceLocation Loc, StringRef Str) { 129 } 130 131 /// PragmaDiagnosticPush - This callback is invoked when a 132 /// #pragma gcc dianostic push directive is read. 133 virtual void PragmaDiagnosticPush(SourceLocation Loc, 134 StringRef Namespace) { 135 } 136 137 /// PragmaDiagnosticPop - This callback is invoked when a 138 /// #pragma gcc dianostic pop directive is read. 139 virtual void PragmaDiagnosticPop(SourceLocation Loc, 140 StringRef Namespace) { 141 } 142 143 /// PragmaDiagnostic - This callback is invoked when a 144 /// #pragma gcc dianostic directive is read. 145 virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 146 diag::Mapping mapping, StringRef Str) { 147 } 148 149 /// MacroExpands - This is called by 150 /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is 151 /// found. 152 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, 153 SourceRange Range) { 154 } 155 156 /// MacroDefined - This hook is called whenever a macro definition is seen. 157 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { 158 } 159 160 /// MacroUndefined - This hook is called whenever a macro #undef is seen. 161 /// MI is released immediately following this callback. 162 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { 163 } 164 165 /// Defined - This hook is called whenever the 'defined' operator is seen. 166 virtual void Defined(const Token &MacroNameTok) { 167 } 168 169 /// SourceRangeSkipped - This hook is called when a source range is skipped. 170 /// \param Range The SourceRange that was skipped. The range begins at the 171 /// #if/#else directive and ends after the #endif/#else directive. 172 virtual void SourceRangeSkipped(SourceRange Range) { 173 } 174 175 /// If -- This hook is called whenever an #if is seen. 176 /// \param Range The SourceRange of the expression being tested. 177 // FIXME: better to pass in a list (or tree!) of Tokens. 178 virtual void If(SourceRange Range) { 179 } 180 181 /// Elif -- This hook is called whenever an #elif is seen. 182 /// \param Range The SourceRange of the expression being tested. 183 // FIXME: better to pass in a list (or tree!) of Tokens. 184 virtual void Elif(SourceRange Range) { 185 } 186 187 /// Ifdef -- This hook is called whenever an #ifdef is seen. 188 /// \param Loc The location of the token being tested. 189 /// \param II Information on the token being tested. 190 virtual void Ifdef(const Token &MacroNameTok) { 191 } 192 193 /// Ifndef -- This hook is called whenever an #ifndef is seen. 194 /// \param Loc The location of the token being tested. 195 /// \param II Information on the token being tested. 196 virtual void Ifndef(const Token &MacroNameTok) { 197 } 198 199 /// Else -- This hook is called whenever an #else is seen. 200 virtual void Else() { 201 } 202 203 /// Endif -- This hook is called whenever an #endif is seen. 204 virtual void Endif() { 205 } 206 }; 207 208 /// PPChainedCallbacks - Simple wrapper class for chaining callbacks. 209 class PPChainedCallbacks : public PPCallbacks { 210 PPCallbacks *First, *Second; 211 212 public: 213 PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second) 214 : First(_First), Second(_Second) {} 215 ~PPChainedCallbacks() { 216 delete Second; 217 delete First; 218 } 219 220 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 221 SrcMgr::CharacteristicKind FileType, 222 FileID PrevFID) { 223 First->FileChanged(Loc, Reason, FileType, PrevFID); 224 Second->FileChanged(Loc, Reason, FileType, PrevFID); 225 } 226 227 virtual void FileSkipped(const FileEntry &ParentFile, 228 const Token &FilenameTok, 229 SrcMgr::CharacteristicKind FileType) { 230 First->FileSkipped(ParentFile, FilenameTok, FileType); 231 Second->FileSkipped(ParentFile, FilenameTok, FileType); 232 } 233 234 virtual void InclusionDirective(SourceLocation HashLoc, 235 const Token &IncludeTok, 236 StringRef FileName, 237 bool IsAngled, 238 const FileEntry *File, 239 SourceLocation EndLoc, 240 StringRef SearchPath, 241 StringRef RelativePath) { 242 First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, 243 EndLoc, SearchPath, RelativePath); 244 Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, 245 EndLoc, SearchPath, RelativePath); 246 } 247 248 virtual void EndOfMainFile() { 249 First->EndOfMainFile(); 250 Second->EndOfMainFile(); 251 } 252 253 virtual void Ident(SourceLocation Loc, const std::string &str) { 254 First->Ident(Loc, str); 255 Second->Ident(Loc, str); 256 } 257 258 virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 259 const std::string &Str) { 260 First->PragmaComment(Loc, Kind, Str); 261 Second->PragmaComment(Loc, Kind, Str); 262 } 263 264 virtual void PragmaMessage(SourceLocation Loc, StringRef Str) { 265 First->PragmaMessage(Loc, Str); 266 Second->PragmaMessage(Loc, Str); 267 } 268 269 virtual void PragmaDiagnosticPush(SourceLocation Loc, 270 StringRef Namespace) { 271 First->PragmaDiagnosticPush(Loc, Namespace); 272 Second->PragmaDiagnosticPush(Loc, Namespace); 273 } 274 275 virtual void PragmaDiagnosticPop(SourceLocation Loc, 276 StringRef Namespace) { 277 First->PragmaDiagnosticPop(Loc, Namespace); 278 Second->PragmaDiagnosticPop(Loc, Namespace); 279 } 280 281 virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 282 diag::Mapping mapping, StringRef Str) { 283 First->PragmaDiagnostic(Loc, Namespace, mapping, Str); 284 Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); 285 } 286 287 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, 288 SourceRange Range) { 289 First->MacroExpands(MacroNameTok, MI, Range); 290 Second->MacroExpands(MacroNameTok, MI, Range); 291 } 292 293 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { 294 First->MacroDefined(MacroNameTok, MI); 295 Second->MacroDefined(MacroNameTok, MI); 296 } 297 298 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { 299 First->MacroUndefined(MacroNameTok, MI); 300 Second->MacroUndefined(MacroNameTok, MI); 301 } 302 303 virtual void Defined(const Token &MacroNameTok) { 304 First->Defined(MacroNameTok); 305 Second->Defined(MacroNameTok); 306 } 307 308 virtual void SourceRangeSkipped(SourceRange Range) { 309 First->SourceRangeSkipped(Range); 310 Second->SourceRangeSkipped(Range); 311 } 312 313 /// If -- This hook is called whenever an #if is seen. 314 virtual void If(SourceRange Range) { 315 First->If(Range); 316 Second->If(Range); 317 } 318 319 /// Elif -- This hook is called whenever an #if is seen. 320 virtual void Elif(SourceRange Range) { 321 First->Elif(Range); 322 Second->Elif(Range); 323 } 324 325 /// Ifdef -- This hook is called whenever an #ifdef is seen. 326 virtual void Ifdef(const Token &MacroNameTok) { 327 First->Ifdef(MacroNameTok); 328 Second->Ifdef(MacroNameTok); 329 } 330 331 /// Ifndef -- This hook is called whenever an #ifndef is seen. 332 virtual void Ifndef(const Token &MacroNameTok) { 333 First->Ifndef(MacroNameTok); 334 Second->Ifndef(MacroNameTok); 335 } 336 337 /// Else -- This hook is called whenever an #else is seen. 338 virtual void Else() { 339 First->Else(); 340 Second->Else(); 341 } 342 343 /// Endif -- This hook is called whenever an #endif is seen. 344 virtual void Endif() { 345 First->Endif(); 346 Second->Endif(); 347 } 348 }; 349 350 } // end namespace clang 351 352 #endif 353