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. FileSkipped(const FileEntry & ParentFile,const Token & FilenameTok,SrcMgr::CharacteristicKind FileType)56 virtual void FileSkipped(const FileEntry &ParentFile, 57 const Token &FilenameTok, 58 SrcMgr::CharacteristicKind FileType) { 59 } 60 61 /// FileNotFound - This callback is invoked whenever an inclusion directive 62 /// results in a file-not-found error. 63 /// 64 /// \param FileName The name of the file being included, as written in the 65 /// source code. 66 /// 67 /// \param RecoveryPath If this client indicates that it can recover from 68 /// this missing file, the client should set this as an additional header 69 /// search patch. 70 /// 71 /// \returns true to indicate that the preprocessor should attempt to recover 72 /// by adding \p RecoveryPath as a header search path. FileNotFound(StringRef FileName,SmallVectorImpl<char> & RecoveryPath)73 virtual bool FileNotFound(StringRef FileName, 74 SmallVectorImpl<char> &RecoveryPath) { 75 return false; 76 } 77 78 /// \brief This callback is invoked whenever an inclusion directive of 79 /// any kind (\c #include, \c #import, etc.) has been processed, regardless 80 /// of whether the inclusion will actually result in an inclusion. 81 /// 82 /// \param HashLoc The location of the '#' that starts the inclusion 83 /// directive. 84 /// 85 /// \param IncludeTok The token that indicates the kind of inclusion 86 /// directive, e.g., 'include' or 'import'. 87 /// 88 /// \param FileName The name of the file being included, as written in the 89 /// source code. 90 /// 91 /// \param IsAngled Whether the file name was enclosed in angle brackets; 92 /// otherwise, it was enclosed in quotes. 93 /// 94 /// \param File The actual file that may be included by this inclusion 95 /// directive. 96 /// 97 /// \param EndLoc The location of the last token within the inclusion 98 /// directive. 99 /// 100 /// \param SearchPath Contains the search path which was used to find the file 101 /// in the file system. If the file was found via an absolute include path, 102 /// SearchPath will be empty. For framework includes, the SearchPath and 103 /// RelativePath will be split up. For example, if an include of "Some/Some.h" 104 /// is found via the framework path 105 /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be 106 /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be 107 /// "Some.h". 108 /// 109 /// \param RelativePath The path relative to SearchPath, at which the include 110 /// file was found. This is equal to FileName except for framework includes. InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,const FileEntry * File,SourceLocation EndLoc,StringRef SearchPath,StringRef RelativePath)111 virtual void InclusionDirective(SourceLocation HashLoc, 112 const Token &IncludeTok, 113 StringRef FileName, 114 bool IsAngled, 115 const FileEntry *File, 116 SourceLocation EndLoc, 117 StringRef SearchPath, 118 StringRef RelativePath) { 119 } 120 121 /// EndOfMainFile - This callback is invoked when the end of the main file is 122 /// reach, no subsequent callbacks will be made. EndOfMainFile()123 virtual void EndOfMainFile() { 124 } 125 126 /// Ident - This callback is invoked when a #ident or #sccs directive is read. 127 /// \param Loc The location of the directive. 128 /// \param str The text of the directive. 129 /// Ident(SourceLocation Loc,const std::string & str)130 virtual void Ident(SourceLocation Loc, const std::string &str) { 131 } 132 133 /// PragmaComment - This callback is invoked when a #pragma comment directive 134 /// is read. 135 /// PragmaComment(SourceLocation Loc,const IdentifierInfo * Kind,const std::string & Str)136 virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 137 const std::string &Str) { 138 } 139 140 /// PragmaMessage - This callback is invoked when a #pragma message directive 141 /// is read. 142 /// \param Loc The location of the message directive. 143 /// \param str The text of the message directive. 144 /// PragmaMessage(SourceLocation Loc,StringRef Str)145 virtual void PragmaMessage(SourceLocation Loc, StringRef Str) { 146 } 147 148 /// PragmaDiagnosticPush - This callback is invoked when a 149 /// #pragma gcc dianostic push directive is read. PragmaDiagnosticPush(SourceLocation Loc,StringRef Namespace)150 virtual void PragmaDiagnosticPush(SourceLocation Loc, 151 StringRef Namespace) { 152 } 153 154 /// PragmaDiagnosticPop - This callback is invoked when a 155 /// #pragma gcc dianostic pop directive is read. PragmaDiagnosticPop(SourceLocation Loc,StringRef Namespace)156 virtual void PragmaDiagnosticPop(SourceLocation Loc, 157 StringRef Namespace) { 158 } 159 160 /// PragmaDiagnostic - This callback is invoked when a 161 /// #pragma gcc dianostic directive is read. PragmaDiagnostic(SourceLocation Loc,StringRef Namespace,diag::Mapping mapping,StringRef Str)162 virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 163 diag::Mapping mapping, StringRef Str) { 164 } 165 166 /// MacroExpands - This is called by 167 /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is 168 /// found. MacroExpands(const Token & MacroNameTok,const MacroInfo * MI,SourceRange Range)169 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, 170 SourceRange Range) { 171 } 172 173 /// MacroDefined - This hook is called whenever a macro definition is seen. MacroDefined(const Token & MacroNameTok,const MacroInfo * MI)174 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { 175 } 176 177 /// MacroUndefined - This hook is called whenever a macro #undef is seen. 178 /// MI is released immediately following this callback. MacroUndefined(const Token & MacroNameTok,const MacroInfo * MI)179 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { 180 } 181 182 /// Defined - This hook is called whenever the 'defined' operator is seen. Defined(const Token & MacroNameTok)183 virtual void Defined(const Token &MacroNameTok) { 184 } 185 186 /// SourceRangeSkipped - This hook is called when a source range is skipped. 187 /// \param Range The SourceRange that was skipped. The range begins at the 188 /// #if/#else directive and ends after the #endif/#else directive. SourceRangeSkipped(SourceRange Range)189 virtual void SourceRangeSkipped(SourceRange Range) { 190 } 191 192 /// If -- This hook is called whenever an #if is seen. 193 /// \param Loc the source location of the directive. 194 /// \param ConditionRange The SourceRange of the expression being tested. 195 // FIXME: better to pass in a list (or tree!) of Tokens. If(SourceLocation Loc,SourceRange ConditionRange)196 virtual void If(SourceLocation Loc, SourceRange ConditionRange) { 197 } 198 199 /// Elif -- This hook is called whenever an #elif is seen. 200 /// \param Loc the source location of the directive. 201 /// \param ConditionRange The SourceRange of the expression being tested. 202 /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. 203 // FIXME: better to pass in a list (or tree!) of Tokens. Elif(SourceLocation Loc,SourceRange ConditionRange,SourceLocation IfLoc)204 virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, 205 SourceLocation IfLoc) { 206 } 207 208 /// Ifdef -- This hook is called whenever an #ifdef is seen. 209 /// \param Loc the source location of the directive. 210 /// \param II Information on the token being tested. Ifdef(SourceLocation Loc,const Token & MacroNameTok)211 virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { 212 } 213 214 /// Ifndef -- This hook is called whenever an #ifndef is seen. 215 /// \param Loc the source location of the directive. 216 /// \param II Information on the token being tested. Ifndef(SourceLocation Loc,const Token & MacroNameTok)217 virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { 218 } 219 220 /// Else -- This hook is called whenever an #else is seen. 221 /// \param Loc the source location of the directive. 222 /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. Else(SourceLocation Loc,SourceLocation IfLoc)223 virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { 224 } 225 226 /// Endif -- This hook is called whenever an #endif is seen. 227 /// \param Loc the source location of the directive. 228 /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. Endif(SourceLocation Loc,SourceLocation IfLoc)229 virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { 230 } 231 }; 232 233 /// PPChainedCallbacks - Simple wrapper class for chaining callbacks. 234 class PPChainedCallbacks : public PPCallbacks { 235 virtual void anchor(); 236 PPCallbacks *First, *Second; 237 238 public: PPChainedCallbacks(PPCallbacks * _First,PPCallbacks * _Second)239 PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second) 240 : First(_First), Second(_Second) {} ~PPChainedCallbacks()241 ~PPChainedCallbacks() { 242 delete Second; 243 delete First; 244 } 245 FileChanged(SourceLocation Loc,FileChangeReason Reason,SrcMgr::CharacteristicKind FileType,FileID PrevFID)246 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 247 SrcMgr::CharacteristicKind FileType, 248 FileID PrevFID) { 249 First->FileChanged(Loc, Reason, FileType, PrevFID); 250 Second->FileChanged(Loc, Reason, FileType, PrevFID); 251 } 252 FileSkipped(const FileEntry & ParentFile,const Token & FilenameTok,SrcMgr::CharacteristicKind FileType)253 virtual void FileSkipped(const FileEntry &ParentFile, 254 const Token &FilenameTok, 255 SrcMgr::CharacteristicKind FileType) { 256 First->FileSkipped(ParentFile, FilenameTok, FileType); 257 Second->FileSkipped(ParentFile, FilenameTok, FileType); 258 } 259 FileNotFound(StringRef FileName,SmallVectorImpl<char> & RecoveryPath)260 virtual bool FileNotFound(StringRef FileName, 261 SmallVectorImpl<char> &RecoveryPath) { 262 return First->FileNotFound(FileName, RecoveryPath) || 263 Second->FileNotFound(FileName, RecoveryPath); 264 } 265 InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,const FileEntry * File,SourceLocation EndLoc,StringRef SearchPath,StringRef RelativePath)266 virtual void InclusionDirective(SourceLocation HashLoc, 267 const Token &IncludeTok, 268 StringRef FileName, 269 bool IsAngled, 270 const FileEntry *File, 271 SourceLocation EndLoc, 272 StringRef SearchPath, 273 StringRef RelativePath) { 274 First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, 275 EndLoc, SearchPath, RelativePath); 276 Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, 277 EndLoc, SearchPath, RelativePath); 278 } 279 EndOfMainFile()280 virtual void EndOfMainFile() { 281 First->EndOfMainFile(); 282 Second->EndOfMainFile(); 283 } 284 Ident(SourceLocation Loc,const std::string & str)285 virtual void Ident(SourceLocation Loc, const std::string &str) { 286 First->Ident(Loc, str); 287 Second->Ident(Loc, str); 288 } 289 PragmaComment(SourceLocation Loc,const IdentifierInfo * Kind,const std::string & Str)290 virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 291 const std::string &Str) { 292 First->PragmaComment(Loc, Kind, Str); 293 Second->PragmaComment(Loc, Kind, Str); 294 } 295 PragmaMessage(SourceLocation Loc,StringRef Str)296 virtual void PragmaMessage(SourceLocation Loc, StringRef Str) { 297 First->PragmaMessage(Loc, Str); 298 Second->PragmaMessage(Loc, Str); 299 } 300 PragmaDiagnosticPush(SourceLocation Loc,StringRef Namespace)301 virtual void PragmaDiagnosticPush(SourceLocation Loc, 302 StringRef Namespace) { 303 First->PragmaDiagnosticPush(Loc, Namespace); 304 Second->PragmaDiagnosticPush(Loc, Namespace); 305 } 306 PragmaDiagnosticPop(SourceLocation Loc,StringRef Namespace)307 virtual void PragmaDiagnosticPop(SourceLocation Loc, 308 StringRef Namespace) { 309 First->PragmaDiagnosticPop(Loc, Namespace); 310 Second->PragmaDiagnosticPop(Loc, Namespace); 311 } 312 PragmaDiagnostic(SourceLocation Loc,StringRef Namespace,diag::Mapping mapping,StringRef Str)313 virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 314 diag::Mapping mapping, StringRef Str) { 315 First->PragmaDiagnostic(Loc, Namespace, mapping, Str); 316 Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); 317 } 318 MacroExpands(const Token & MacroNameTok,const MacroInfo * MI,SourceRange Range)319 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, 320 SourceRange Range) { 321 First->MacroExpands(MacroNameTok, MI, Range); 322 Second->MacroExpands(MacroNameTok, MI, Range); 323 } 324 MacroDefined(const Token & MacroNameTok,const MacroInfo * MI)325 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { 326 First->MacroDefined(MacroNameTok, MI); 327 Second->MacroDefined(MacroNameTok, MI); 328 } 329 MacroUndefined(const Token & MacroNameTok,const MacroInfo * MI)330 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { 331 First->MacroUndefined(MacroNameTok, MI); 332 Second->MacroUndefined(MacroNameTok, MI); 333 } 334 Defined(const Token & MacroNameTok)335 virtual void Defined(const Token &MacroNameTok) { 336 First->Defined(MacroNameTok); 337 Second->Defined(MacroNameTok); 338 } 339 SourceRangeSkipped(SourceRange Range)340 virtual void SourceRangeSkipped(SourceRange Range) { 341 First->SourceRangeSkipped(Range); 342 Second->SourceRangeSkipped(Range); 343 } 344 345 /// If -- This hook is called whenever an #if is seen. If(SourceLocation Loc,SourceRange ConditionRange)346 virtual void If(SourceLocation Loc, SourceRange ConditionRange) { 347 First->If(Loc, ConditionRange); 348 Second->If(Loc, ConditionRange); 349 } 350 351 /// Elif -- This hook is called whenever an #if is seen. Elif(SourceLocation Loc,SourceRange ConditionRange,SourceLocation IfLoc)352 virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, 353 SourceLocation IfLoc) { 354 First->Elif(Loc, ConditionRange, IfLoc); 355 Second->Elif(Loc, ConditionRange, IfLoc); 356 } 357 358 /// Ifdef -- This hook is called whenever an #ifdef is seen. Ifdef(SourceLocation Loc,const Token & MacroNameTok)359 virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { 360 First->Ifdef(Loc, MacroNameTok); 361 Second->Ifdef(Loc, MacroNameTok); 362 } 363 364 /// Ifndef -- This hook is called whenever an #ifndef is seen. Ifndef(SourceLocation Loc,const Token & MacroNameTok)365 virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { 366 First->Ifndef(Loc, MacroNameTok); 367 Second->Ifndef(Loc, MacroNameTok); 368 } 369 370 /// Else -- This hook is called whenever an #else is seen. Else(SourceLocation Loc,SourceLocation IfLoc)371 virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { 372 First->Else(Loc, IfLoc); 373 Second->Else(Loc, IfLoc); 374 } 375 376 /// Endif -- This hook is called whenever an #endif is seen. Endif(SourceLocation Loc,SourceLocation IfLoc)377 virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { 378 First->Endif(Loc, IfLoc); 379 Second->Endif(Loc, IfLoc); 380 } 381 }; 382 383 } // end namespace clang 384 385 #endif 386