1 //===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- 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 /// \file 10 /// 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/Basic/DiagnosticIDs.h" 18 #include "clang/Basic/IdentifierTable.h" 19 #include "clang/Basic/SourceLocation.h" 20 #include "clang/Basic/SourceManager.h" 21 #include "clang/Lex/ModuleLoader.h" 22 #include "clang/Lex/Pragma.h" 23 #include "llvm/ADT/StringRef.h" 24 25 namespace clang { 26 class Token; 27 class IdentifierInfo; 28 class MacroDefinition; 29 class MacroDirective; 30 class MacroArgs; 31 struct LexEmbedParametersResult; 32 33 /// This interface provides a way to observe the actions of the 34 /// preprocessor as it does its thing. 35 /// 36 /// Clients can define their hooks here to implement preprocessor level tools. 37 class PPCallbacks { 38 public: 39 virtual ~PPCallbacks(); 40 41 enum FileChangeReason { 42 EnterFile, ExitFile, SystemHeaderPragma, RenameFile 43 }; 44 45 /// Callback invoked whenever a source file is entered or exited. 46 /// 47 /// \param Loc Indicates the new location. 48 /// \param PrevFID the file that was exited if \p Reason is ExitFile or the 49 /// the file before the new one entered for \p Reason EnterFile. 50 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 51 SrcMgr::CharacteristicKind FileType, 52 FileID PrevFID = FileID()) { 53 } 54 55 enum class LexedFileChangeReason { EnterFile, ExitFile }; 56 57 /// Callback invoked whenever the \p Lexer moves to a different file for 58 /// lexing. Unlike \p FileChanged line number directives and other related 59 /// pragmas do not trigger callbacks to \p LexedFileChanged. 60 /// 61 /// \param FID The \p FileID that the \p Lexer moved to. 62 /// 63 /// \param Reason Whether the \p Lexer entered a new file or exited one. 64 /// 65 /// \param FileType The \p CharacteristicKind of the file the \p Lexer moved 66 /// to. 67 /// 68 /// \param PrevFID The \p FileID the \p Lexer was using before the change. 69 /// 70 /// \param Loc The location where the \p Lexer entered a new file from or the 71 /// location that the \p Lexer moved into after exiting a file. LexedFileChanged(FileID FID,LexedFileChangeReason Reason,SrcMgr::CharacteristicKind FileType,FileID PrevFID,SourceLocation Loc)72 virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, 73 SrcMgr::CharacteristicKind FileType, 74 FileID PrevFID, SourceLocation Loc) {} 75 76 /// Callback invoked whenever a source file is skipped as the result 77 /// of header guard optimization. 78 /// 79 /// \param SkippedFile The file that is skipped instead of entering \#include 80 /// 81 /// \param FilenameTok The file name token in \#include "FileName" directive 82 /// or macro expanded file name token from \#include MACRO(PARAMS) directive. 83 /// Note that FilenameTok contains corresponding quotes/angles symbols. FileSkipped(const FileEntryRef & SkippedFile,const Token & FilenameTok,SrcMgr::CharacteristicKind FileType)84 virtual void FileSkipped(const FileEntryRef &SkippedFile, 85 const Token &FilenameTok, 86 SrcMgr::CharacteristicKind FileType) {} 87 88 /// Callback invoked whenever the preprocessor cannot find a file for an 89 /// embed directive. 90 /// 91 /// \param FileName The name of the file being included, as written in the 92 /// source code. 93 /// 94 /// \returns true to indicate that the preprocessor should skip this file 95 /// and not issue any diagnostic. EmbedFileNotFound(StringRef FileName)96 virtual bool EmbedFileNotFound(StringRef FileName) { return false; } 97 98 /// Callback invoked whenever an embed directive has been processed, 99 /// regardless of whether the embed will actually find a file. 100 /// 101 /// \param HashLoc The location of the '#' that starts the embed directive. 102 /// 103 /// \param FileName The name of the file being included, as written in the 104 /// source code. 105 /// 106 /// \param IsAngled Whether the file name was enclosed in angle brackets; 107 /// otherwise, it was enclosed in quotes. 108 /// 109 /// \param File The actual file that may be included by this embed directive. 110 /// 111 /// \param Params The parameters used by the directive. EmbedDirective(SourceLocation HashLoc,StringRef FileName,bool IsAngled,OptionalFileEntryRef File,const LexEmbedParametersResult & Params)112 virtual void EmbedDirective(SourceLocation HashLoc, StringRef FileName, 113 bool IsAngled, OptionalFileEntryRef File, 114 const LexEmbedParametersResult &Params) {} 115 116 /// Callback invoked whenever the preprocessor cannot find a file for an 117 /// inclusion directive. 118 /// 119 /// \param FileName The name of the file being included, as written in the 120 /// source code. 121 /// 122 /// \returns true to indicate that the preprocessor should skip this file 123 /// and not issue any diagnostic. FileNotFound(StringRef FileName)124 virtual bool FileNotFound(StringRef FileName) { return false; } 125 126 /// Callback invoked whenever an inclusion directive of 127 /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless 128 /// of whether the inclusion will actually result in an inclusion. 129 /// 130 /// \param HashLoc The location of the '#' that starts the inclusion 131 /// directive. 132 /// 133 /// \param IncludeTok The token that indicates the kind of inclusion 134 /// directive, e.g., 'include' or 'import'. 135 /// 136 /// \param FileName The name of the file being included, as written in the 137 /// source code. 138 /// 139 /// \param IsAngled Whether the file name was enclosed in angle brackets; 140 /// otherwise, it was enclosed in quotes. 141 /// 142 /// \param FilenameRange The character range of the quotes or angle brackets 143 /// for the written file name. 144 /// 145 /// \param File The actual file that may be included by this inclusion 146 /// directive. 147 /// 148 /// \param SearchPath Contains the search path which was used to find the file 149 /// in the file system. If the file was found via an absolute include path, 150 /// SearchPath will be empty. For framework includes, the SearchPath and 151 /// RelativePath will be split up. For example, if an include of "Some/Some.h" 152 /// is found via the framework path 153 /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be 154 /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be 155 /// "Some.h". 156 /// 157 /// \param RelativePath The path relative to SearchPath, at which the include 158 /// file was found. This is equal to FileName except for framework includes. 159 /// 160 /// \param SuggestedModule The module suggested for this header, if any. 161 /// 162 /// \param ModuleImported Whether this include was translated into import of 163 /// \p SuggestedModule. 164 /// 165 /// \param FileType The characteristic kind, indicates whether a file or 166 /// directory holds normal user code, system code, or system code which is 167 /// implicitly 'extern "C"' in C++ mode. 168 /// InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,OptionalFileEntryRef File,StringRef SearchPath,StringRef RelativePath,const Module * SuggestedModule,bool ModuleImported,SrcMgr::CharacteristicKind FileType)169 virtual void InclusionDirective(SourceLocation HashLoc, 170 const Token &IncludeTok, StringRef FileName, 171 bool IsAngled, CharSourceRange FilenameRange, 172 OptionalFileEntryRef File, 173 StringRef SearchPath, StringRef RelativePath, 174 const Module *SuggestedModule, 175 bool ModuleImported, 176 SrcMgr::CharacteristicKind FileType) {} 177 178 /// Callback invoked whenever a submodule was entered. 179 /// 180 /// \param M The submodule we have entered. 181 /// 182 /// \param ImportLoc The location of import directive token. 183 /// 184 /// \param ForPragma If entering from pragma directive. 185 /// EnteredSubmodule(Module * M,SourceLocation ImportLoc,bool ForPragma)186 virtual void EnteredSubmodule(Module *M, SourceLocation ImportLoc, 187 bool ForPragma) { } 188 189 /// Callback invoked whenever a submodule was left. 190 /// 191 /// \param M The submodule we have left. 192 /// 193 /// \param ImportLoc The location of import directive token. 194 /// 195 /// \param ForPragma If entering from pragma directive. 196 /// LeftSubmodule(Module * M,SourceLocation ImportLoc,bool ForPragma)197 virtual void LeftSubmodule(Module *M, SourceLocation ImportLoc, 198 bool ForPragma) { } 199 200 /// Callback invoked whenever there was an explicit module-import 201 /// syntax. 202 /// 203 /// \param ImportLoc The location of import directive token. 204 /// 205 /// \param Path The identifiers (and their locations) of the module 206 /// "path", e.g., "std.vector" would be split into "std" and "vector". 207 /// 208 /// \param Imported The imported module; can be null if importing failed. 209 /// moduleImport(SourceLocation ImportLoc,ModuleIdPath Path,const Module * Imported)210 virtual void moduleImport(SourceLocation ImportLoc, 211 ModuleIdPath Path, 212 const Module *Imported) { 213 } 214 215 /// Callback invoked when the end of the main file is reached. 216 /// 217 /// No subsequent callbacks will be made. EndOfMainFile()218 virtual void EndOfMainFile() { 219 } 220 221 /// Callback invoked when a \#ident or \#sccs directive is read. 222 /// \param Loc The location of the directive. 223 /// \param str The text of the directive. 224 /// Ident(SourceLocation Loc,StringRef str)225 virtual void Ident(SourceLocation Loc, StringRef str) { 226 } 227 228 /// Callback invoked when start reading any pragma directive. PragmaDirective(SourceLocation Loc,PragmaIntroducerKind Introducer)229 virtual void PragmaDirective(SourceLocation Loc, 230 PragmaIntroducerKind Introducer) { 231 } 232 233 /// Callback invoked when a \#pragma comment directive is read. PragmaComment(SourceLocation Loc,const IdentifierInfo * Kind,StringRef Str)234 virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 235 StringRef Str) { 236 } 237 238 /// Callback invoked when a \#pragma mark comment is read. PragmaMark(SourceLocation Loc,StringRef Trivia)239 virtual void PragmaMark(SourceLocation Loc, StringRef Trivia) { 240 } 241 242 /// Callback invoked when a \#pragma detect_mismatch directive is 243 /// read. PragmaDetectMismatch(SourceLocation Loc,StringRef Name,StringRef Value)244 virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name, 245 StringRef Value) { 246 } 247 248 /// Callback invoked when a \#pragma clang __debug directive is read. 249 /// \param Loc The location of the debug directive. 250 /// \param DebugType The identifier following __debug. PragmaDebug(SourceLocation Loc,StringRef DebugType)251 virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) { 252 } 253 254 /// Determines the kind of \#pragma invoking a call to PragmaMessage. 255 enum PragmaMessageKind { 256 /// \#pragma message has been invoked. 257 PMK_Message, 258 259 /// \#pragma GCC warning has been invoked. 260 PMK_Warning, 261 262 /// \#pragma GCC error has been invoked. 263 PMK_Error 264 }; 265 266 /// Callback invoked when a \#pragma message directive is read. 267 /// \param Loc The location of the message directive. 268 /// \param Namespace The namespace of the message directive. 269 /// \param Kind The type of the message directive. 270 /// \param Str The text of the message directive. PragmaMessage(SourceLocation Loc,StringRef Namespace,PragmaMessageKind Kind,StringRef Str)271 virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace, 272 PragmaMessageKind Kind, StringRef Str) { 273 } 274 275 /// Callback invoked when a \#pragma gcc diagnostic push directive 276 /// is read. PragmaDiagnosticPush(SourceLocation Loc,StringRef Namespace)277 virtual void PragmaDiagnosticPush(SourceLocation Loc, 278 StringRef Namespace) { 279 } 280 281 /// Callback invoked when a \#pragma gcc diagnostic pop directive 282 /// is read. PragmaDiagnosticPop(SourceLocation Loc,StringRef Namespace)283 virtual void PragmaDiagnosticPop(SourceLocation Loc, 284 StringRef Namespace) { 285 } 286 287 /// Callback invoked when a \#pragma gcc diagnostic directive is read. PragmaDiagnostic(SourceLocation Loc,StringRef Namespace,diag::Severity mapping,StringRef Str)288 virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 289 diag::Severity mapping, StringRef Str) {} 290 291 /// Called when an OpenCL extension is either disabled or 292 /// enabled with a pragma. PragmaOpenCLExtension(SourceLocation NameLoc,const IdentifierInfo * Name,SourceLocation StateLoc,unsigned State)293 virtual void PragmaOpenCLExtension(SourceLocation NameLoc, 294 const IdentifierInfo *Name, 295 SourceLocation StateLoc, unsigned State) { 296 } 297 298 /// Callback invoked when a \#pragma warning directive is read. 299 enum PragmaWarningSpecifier { 300 PWS_Default, 301 PWS_Disable, 302 PWS_Error, 303 PWS_Once, 304 PWS_Suppress, 305 PWS_Level1, 306 PWS_Level2, 307 PWS_Level3, 308 PWS_Level4, 309 }; PragmaWarning(SourceLocation Loc,PragmaWarningSpecifier WarningSpec,ArrayRef<int> Ids)310 virtual void PragmaWarning(SourceLocation Loc, 311 PragmaWarningSpecifier WarningSpec, 312 ArrayRef<int> Ids) {} 313 314 /// Callback invoked when a \#pragma warning(push) directive is read. PragmaWarningPush(SourceLocation Loc,int Level)315 virtual void PragmaWarningPush(SourceLocation Loc, int Level) { 316 } 317 318 /// Callback invoked when a \#pragma warning(pop) directive is read. PragmaWarningPop(SourceLocation Loc)319 virtual void PragmaWarningPop(SourceLocation Loc) { 320 } 321 322 /// Callback invoked when a \#pragma execution_character_set(push) directive 323 /// is read. PragmaExecCharsetPush(SourceLocation Loc,StringRef Str)324 virtual void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) {} 325 326 /// Callback invoked when a \#pragma execution_character_set(pop) directive 327 /// is read. PragmaExecCharsetPop(SourceLocation Loc)328 virtual void PragmaExecCharsetPop(SourceLocation Loc) {} 329 330 /// Callback invoked when a \#pragma clang assume_nonnull begin directive 331 /// is read. PragmaAssumeNonNullBegin(SourceLocation Loc)332 virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {} 333 334 /// Callback invoked when a \#pragma clang assume_nonnull end directive 335 /// is read. PragmaAssumeNonNullEnd(SourceLocation Loc)336 virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {} 337 338 /// Called by Preprocessor::HandleMacroExpandedIdentifier when a 339 /// macro invocation is found. MacroExpands(const Token & MacroNameTok,const MacroDefinition & MD,SourceRange Range,const MacroArgs * Args)340 virtual void MacroExpands(const Token &MacroNameTok, 341 const MacroDefinition &MD, SourceRange Range, 342 const MacroArgs *Args) {} 343 344 /// Hook called whenever a macro definition is seen. MacroDefined(const Token & MacroNameTok,const MacroDirective * MD)345 virtual void MacroDefined(const Token &MacroNameTok, 346 const MacroDirective *MD) { 347 } 348 349 /// Hook called whenever a macro \#undef is seen. 350 /// \param MacroNameTok The active Token 351 /// \param MD A MacroDefinition for the named macro. 352 /// \param Undef New MacroDirective if the macro was defined, null otherwise. 353 /// 354 /// MD is released immediately following this callback. MacroUndefined(const Token & MacroNameTok,const MacroDefinition & MD,const MacroDirective * Undef)355 virtual void MacroUndefined(const Token &MacroNameTok, 356 const MacroDefinition &MD, 357 const MacroDirective *Undef) { 358 } 359 360 /// Hook called whenever the 'defined' operator is seen. 361 /// \param MD The MacroDirective if the name was a macro, null otherwise. Defined(const Token & MacroNameTok,const MacroDefinition & MD,SourceRange Range)362 virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD, 363 SourceRange Range) { 364 } 365 366 /// Hook called when a '__has_embed' directive is read. HasEmbed(SourceLocation Loc,StringRef FileName,bool IsAngled,OptionalFileEntryRef File)367 virtual void HasEmbed(SourceLocation Loc, StringRef FileName, bool IsAngled, 368 OptionalFileEntryRef File) {} 369 370 /// Hook called when a '__has_include' or '__has_include_next' directive is 371 /// read. 372 virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled, 373 OptionalFileEntryRef File, 374 SrcMgr::CharacteristicKind FileType); 375 376 /// Hook called when a source range is skipped. 377 /// \param Range The SourceRange that was skipped. The range begins at the 378 /// \#if/\#else directive and ends after the \#endif/\#else directive. 379 /// \param EndifLoc The end location of the 'endif' token, which may precede 380 /// the range skipped by the directive (e.g excluding comments after an 381 /// 'endif'). SourceRangeSkipped(SourceRange Range,SourceLocation EndifLoc)382 virtual void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) { 383 } 384 385 enum ConditionValueKind { 386 CVK_NotEvaluated, CVK_False, CVK_True 387 }; 388 389 /// Hook called whenever an \#if is seen. 390 /// \param Loc the source location of the directive. 391 /// \param ConditionRange The SourceRange of the expression being tested. 392 /// \param ConditionValue The evaluated value of the condition. 393 /// 394 // FIXME: better to pass in a list (or tree!) of Tokens. If(SourceLocation Loc,SourceRange ConditionRange,ConditionValueKind ConditionValue)395 virtual void If(SourceLocation Loc, SourceRange ConditionRange, 396 ConditionValueKind ConditionValue) { 397 } 398 399 /// Hook called whenever an \#elif is seen. 400 /// \param Loc the source location of the directive. 401 /// \param ConditionRange The SourceRange of the expression being tested. 402 /// \param ConditionValue The evaluated value of the condition. 403 /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. 404 // FIXME: better to pass in a list (or tree!) of Tokens. Elif(SourceLocation Loc,SourceRange ConditionRange,ConditionValueKind ConditionValue,SourceLocation IfLoc)405 virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, 406 ConditionValueKind ConditionValue, SourceLocation IfLoc) { 407 } 408 409 /// Hook called whenever an \#ifdef is seen. 410 /// \param Loc the source location of the directive. 411 /// \param MacroNameTok Information on the token being tested. 412 /// \param MD The MacroDefinition if the name was a macro, null otherwise. Ifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)413 virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, 414 const MacroDefinition &MD) { 415 } 416 417 /// Hook called whenever an \#elifdef branch is taken. 418 /// \param Loc the source location of the directive. 419 /// \param MacroNameTok Information on the token being tested. 420 /// \param MD The MacroDefinition if the name was a macro, null otherwise. Elifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)421 virtual void Elifdef(SourceLocation Loc, const Token &MacroNameTok, 422 const MacroDefinition &MD) { 423 } 424 /// Hook called whenever an \#elifdef is skipped. 425 /// \param Loc the source location of the directive. 426 /// \param ConditionRange The SourceRange of the expression being tested. 427 /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. 428 // FIXME: better to pass in a list (or tree!) of Tokens. Elifdef(SourceLocation Loc,SourceRange ConditionRange,SourceLocation IfLoc)429 virtual void Elifdef(SourceLocation Loc, SourceRange ConditionRange, 430 SourceLocation IfLoc) { 431 } 432 433 /// Hook called whenever an \#ifndef is seen. 434 /// \param Loc the source location of the directive. 435 /// \param MacroNameTok Information on the token being tested. 436 /// \param MD The MacroDefiniton if the name was a macro, null otherwise. Ifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)437 virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, 438 const MacroDefinition &MD) { 439 } 440 441 /// Hook called whenever an \#elifndef branch is taken. 442 /// \param Loc the source location of the directive. 443 /// \param MacroNameTok Information on the token being tested. 444 /// \param MD The MacroDefinition if the name was a macro, null otherwise. Elifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)445 virtual void Elifndef(SourceLocation Loc, const Token &MacroNameTok, 446 const MacroDefinition &MD) { 447 } 448 /// Hook called whenever an \#elifndef is skipped. 449 /// \param Loc the source location of the directive. 450 /// \param ConditionRange The SourceRange of the expression being tested. 451 /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. 452 // FIXME: better to pass in a list (or tree!) of Tokens. Elifndef(SourceLocation Loc,SourceRange ConditionRange,SourceLocation IfLoc)453 virtual void Elifndef(SourceLocation Loc, SourceRange ConditionRange, 454 SourceLocation IfLoc) { 455 } 456 457 /// Hook called whenever an \#else is seen. 458 /// \param Loc the source location of the directive. 459 /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. Else(SourceLocation Loc,SourceLocation IfLoc)460 virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { 461 } 462 463 /// Hook called whenever an \#endif is seen. 464 /// \param Loc the source location of the directive. 465 /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. Endif(SourceLocation Loc,SourceLocation IfLoc)466 virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { 467 } 468 }; 469 470 /// Simple wrapper class for chaining callbacks. 471 class PPChainedCallbacks : public PPCallbacks { 472 std::unique_ptr<PPCallbacks> First, Second; 473 474 public: PPChainedCallbacks(std::unique_ptr<PPCallbacks> _First,std::unique_ptr<PPCallbacks> _Second)475 PPChainedCallbacks(std::unique_ptr<PPCallbacks> _First, 476 std::unique_ptr<PPCallbacks> _Second) 477 : First(std::move(_First)), Second(std::move(_Second)) {} 478 479 ~PPChainedCallbacks() override; 480 FileChanged(SourceLocation Loc,FileChangeReason Reason,SrcMgr::CharacteristicKind FileType,FileID PrevFID)481 void FileChanged(SourceLocation Loc, FileChangeReason Reason, 482 SrcMgr::CharacteristicKind FileType, 483 FileID PrevFID) override { 484 First->FileChanged(Loc, Reason, FileType, PrevFID); 485 Second->FileChanged(Loc, Reason, FileType, PrevFID); 486 } 487 LexedFileChanged(FileID FID,LexedFileChangeReason Reason,SrcMgr::CharacteristicKind FileType,FileID PrevFID,SourceLocation Loc)488 void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, 489 SrcMgr::CharacteristicKind FileType, FileID PrevFID, 490 SourceLocation Loc) override { 491 First->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc); 492 Second->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc); 493 } 494 FileSkipped(const FileEntryRef & SkippedFile,const Token & FilenameTok,SrcMgr::CharacteristicKind FileType)495 void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, 496 SrcMgr::CharacteristicKind FileType) override { 497 First->FileSkipped(SkippedFile, FilenameTok, FileType); 498 Second->FileSkipped(SkippedFile, FilenameTok, FileType); 499 } 500 EmbedFileNotFound(StringRef FileName)501 bool EmbedFileNotFound(StringRef FileName) override { 502 bool Skip = First->FileNotFound(FileName); 503 // Make sure to invoke the second callback, no matter if the first already 504 // returned true to skip the file. 505 Skip |= Second->FileNotFound(FileName); 506 return Skip; 507 } 508 EmbedDirective(SourceLocation HashLoc,StringRef FileName,bool IsAngled,OptionalFileEntryRef File,const LexEmbedParametersResult & Params)509 void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled, 510 OptionalFileEntryRef File, 511 const LexEmbedParametersResult &Params) override { 512 First->EmbedDirective(HashLoc, FileName, IsAngled, File, Params); 513 Second->EmbedDirective(HashLoc, FileName, IsAngled, File, Params); 514 } 515 FileNotFound(StringRef FileName)516 bool FileNotFound(StringRef FileName) override { 517 bool Skip = First->FileNotFound(FileName); 518 // Make sure to invoke the second callback, no matter if the first already 519 // returned true to skip the file. 520 Skip |= Second->FileNotFound(FileName); 521 return Skip; 522 } 523 InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,OptionalFileEntryRef File,StringRef SearchPath,StringRef RelativePath,const Module * SuggestedModule,bool ModuleImported,SrcMgr::CharacteristicKind FileType)524 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 525 StringRef FileName, bool IsAngled, 526 CharSourceRange FilenameRange, 527 OptionalFileEntryRef File, StringRef SearchPath, 528 StringRef RelativePath, const Module *SuggestedModule, 529 bool ModuleImported, 530 SrcMgr::CharacteristicKind FileType) override { 531 First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, 532 FilenameRange, File, SearchPath, RelativePath, 533 SuggestedModule, ModuleImported, FileType); 534 Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, 535 FilenameRange, File, SearchPath, RelativePath, 536 SuggestedModule, ModuleImported, FileType); 537 } 538 EnteredSubmodule(Module * M,SourceLocation ImportLoc,bool ForPragma)539 void EnteredSubmodule(Module *M, SourceLocation ImportLoc, 540 bool ForPragma) override { 541 First->EnteredSubmodule(M, ImportLoc, ForPragma); 542 Second->EnteredSubmodule(M, ImportLoc, ForPragma); 543 } 544 LeftSubmodule(Module * M,SourceLocation ImportLoc,bool ForPragma)545 void LeftSubmodule(Module *M, SourceLocation ImportLoc, 546 bool ForPragma) override { 547 First->LeftSubmodule(M, ImportLoc, ForPragma); 548 Second->LeftSubmodule(M, ImportLoc, ForPragma); 549 } 550 moduleImport(SourceLocation ImportLoc,ModuleIdPath Path,const Module * Imported)551 void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, 552 const Module *Imported) override { 553 First->moduleImport(ImportLoc, Path, Imported); 554 Second->moduleImport(ImportLoc, Path, Imported); 555 } 556 EndOfMainFile()557 void EndOfMainFile() override { 558 First->EndOfMainFile(); 559 Second->EndOfMainFile(); 560 } 561 Ident(SourceLocation Loc,StringRef str)562 void Ident(SourceLocation Loc, StringRef str) override { 563 First->Ident(Loc, str); 564 Second->Ident(Loc, str); 565 } 566 PragmaDirective(SourceLocation Loc,PragmaIntroducerKind Introducer)567 void PragmaDirective(SourceLocation Loc, 568 PragmaIntroducerKind Introducer) override { 569 First->PragmaDirective(Loc, Introducer); 570 Second->PragmaDirective(Loc, Introducer); 571 } 572 PragmaComment(SourceLocation Loc,const IdentifierInfo * Kind,StringRef Str)573 void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 574 StringRef Str) override { 575 First->PragmaComment(Loc, Kind, Str); 576 Second->PragmaComment(Loc, Kind, Str); 577 } 578 PragmaMark(SourceLocation Loc,StringRef Trivia)579 void PragmaMark(SourceLocation Loc, StringRef Trivia) override { 580 First->PragmaMark(Loc, Trivia); 581 Second->PragmaMark(Loc, Trivia); 582 } 583 PragmaDetectMismatch(SourceLocation Loc,StringRef Name,StringRef Value)584 void PragmaDetectMismatch(SourceLocation Loc, StringRef Name, 585 StringRef Value) override { 586 First->PragmaDetectMismatch(Loc, Name, Value); 587 Second->PragmaDetectMismatch(Loc, Name, Value); 588 } 589 PragmaDebug(SourceLocation Loc,StringRef DebugType)590 void PragmaDebug(SourceLocation Loc, StringRef DebugType) override { 591 First->PragmaDebug(Loc, DebugType); 592 Second->PragmaDebug(Loc, DebugType); 593 } 594 PragmaMessage(SourceLocation Loc,StringRef Namespace,PragmaMessageKind Kind,StringRef Str)595 void PragmaMessage(SourceLocation Loc, StringRef Namespace, 596 PragmaMessageKind Kind, StringRef Str) override { 597 First->PragmaMessage(Loc, Namespace, Kind, Str); 598 Second->PragmaMessage(Loc, Namespace, Kind, Str); 599 } 600 PragmaDiagnosticPush(SourceLocation Loc,StringRef Namespace)601 void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override { 602 First->PragmaDiagnosticPush(Loc, Namespace); 603 Second->PragmaDiagnosticPush(Loc, Namespace); 604 } 605 PragmaDiagnosticPop(SourceLocation Loc,StringRef Namespace)606 void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override { 607 First->PragmaDiagnosticPop(Loc, Namespace); 608 Second->PragmaDiagnosticPop(Loc, Namespace); 609 } 610 PragmaDiagnostic(SourceLocation Loc,StringRef Namespace,diag::Severity mapping,StringRef Str)611 void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 612 diag::Severity mapping, StringRef Str) override { 613 First->PragmaDiagnostic(Loc, Namespace, mapping, Str); 614 Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); 615 } 616 HasEmbed(SourceLocation Loc,StringRef FileName,bool IsAngled,OptionalFileEntryRef File)617 void HasEmbed(SourceLocation Loc, StringRef FileName, bool IsAngled, 618 OptionalFileEntryRef File) override { 619 First->HasEmbed(Loc, FileName, IsAngled, File); 620 Second->HasEmbed(Loc, FileName, IsAngled, File); 621 } 622 623 void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled, 624 OptionalFileEntryRef File, 625 SrcMgr::CharacteristicKind FileType) override; 626 PragmaOpenCLExtension(SourceLocation NameLoc,const IdentifierInfo * Name,SourceLocation StateLoc,unsigned State)627 void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name, 628 SourceLocation StateLoc, unsigned State) override { 629 First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State); 630 Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State); 631 } 632 PragmaWarning(SourceLocation Loc,PragmaWarningSpecifier WarningSpec,ArrayRef<int> Ids)633 void PragmaWarning(SourceLocation Loc, PragmaWarningSpecifier WarningSpec, 634 ArrayRef<int> Ids) override { 635 First->PragmaWarning(Loc, WarningSpec, Ids); 636 Second->PragmaWarning(Loc, WarningSpec, Ids); 637 } 638 PragmaWarningPush(SourceLocation Loc,int Level)639 void PragmaWarningPush(SourceLocation Loc, int Level) override { 640 First->PragmaWarningPush(Loc, Level); 641 Second->PragmaWarningPush(Loc, Level); 642 } 643 PragmaWarningPop(SourceLocation Loc)644 void PragmaWarningPop(SourceLocation Loc) override { 645 First->PragmaWarningPop(Loc); 646 Second->PragmaWarningPop(Loc); 647 } 648 PragmaExecCharsetPush(SourceLocation Loc,StringRef Str)649 void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override { 650 First->PragmaExecCharsetPush(Loc, Str); 651 Second->PragmaExecCharsetPush(Loc, Str); 652 } 653 PragmaExecCharsetPop(SourceLocation Loc)654 void PragmaExecCharsetPop(SourceLocation Loc) override { 655 First->PragmaExecCharsetPop(Loc); 656 Second->PragmaExecCharsetPop(Loc); 657 } 658 PragmaAssumeNonNullBegin(SourceLocation Loc)659 void PragmaAssumeNonNullBegin(SourceLocation Loc) override { 660 First->PragmaAssumeNonNullBegin(Loc); 661 Second->PragmaAssumeNonNullBegin(Loc); 662 } 663 PragmaAssumeNonNullEnd(SourceLocation Loc)664 void PragmaAssumeNonNullEnd(SourceLocation Loc) override { 665 First->PragmaAssumeNonNullEnd(Loc); 666 Second->PragmaAssumeNonNullEnd(Loc); 667 } 668 MacroExpands(const Token & MacroNameTok,const MacroDefinition & MD,SourceRange Range,const MacroArgs * Args)669 void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, 670 SourceRange Range, const MacroArgs *Args) override { 671 First->MacroExpands(MacroNameTok, MD, Range, Args); 672 Second->MacroExpands(MacroNameTok, MD, Range, Args); 673 } 674 MacroDefined(const Token & MacroNameTok,const MacroDirective * MD)675 void MacroDefined(const Token &MacroNameTok, 676 const MacroDirective *MD) override { 677 First->MacroDefined(MacroNameTok, MD); 678 Second->MacroDefined(MacroNameTok, MD); 679 } 680 MacroUndefined(const Token & MacroNameTok,const MacroDefinition & MD,const MacroDirective * Undef)681 void MacroUndefined(const Token &MacroNameTok, 682 const MacroDefinition &MD, 683 const MacroDirective *Undef) override { 684 First->MacroUndefined(MacroNameTok, MD, Undef); 685 Second->MacroUndefined(MacroNameTok, MD, Undef); 686 } 687 Defined(const Token & MacroNameTok,const MacroDefinition & MD,SourceRange Range)688 void Defined(const Token &MacroNameTok, const MacroDefinition &MD, 689 SourceRange Range) override { 690 First->Defined(MacroNameTok, MD, Range); 691 Second->Defined(MacroNameTok, MD, Range); 692 } 693 SourceRangeSkipped(SourceRange Range,SourceLocation EndifLoc)694 void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { 695 First->SourceRangeSkipped(Range, EndifLoc); 696 Second->SourceRangeSkipped(Range, EndifLoc); 697 } 698 699 /// Hook called whenever an \#if is seen. If(SourceLocation Loc,SourceRange ConditionRange,ConditionValueKind ConditionValue)700 void If(SourceLocation Loc, SourceRange ConditionRange, 701 ConditionValueKind ConditionValue) override { 702 First->If(Loc, ConditionRange, ConditionValue); 703 Second->If(Loc, ConditionRange, ConditionValue); 704 } 705 706 /// Hook called whenever an \#elif is seen. Elif(SourceLocation Loc,SourceRange ConditionRange,ConditionValueKind ConditionValue,SourceLocation IfLoc)707 void Elif(SourceLocation Loc, SourceRange ConditionRange, 708 ConditionValueKind ConditionValue, SourceLocation IfLoc) override { 709 First->Elif(Loc, ConditionRange, ConditionValue, IfLoc); 710 Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc); 711 } 712 713 /// Hook called whenever an \#ifdef is seen. Ifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)714 void Ifdef(SourceLocation Loc, const Token &MacroNameTok, 715 const MacroDefinition &MD) override { 716 First->Ifdef(Loc, MacroNameTok, MD); 717 Second->Ifdef(Loc, MacroNameTok, MD); 718 } 719 720 /// Hook called whenever an \#elifdef is taken. Elifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)721 void Elifdef(SourceLocation Loc, const Token &MacroNameTok, 722 const MacroDefinition &MD) override { 723 First->Elifdef(Loc, MacroNameTok, MD); 724 Second->Elifdef(Loc, MacroNameTok, MD); 725 } 726 /// Hook called whenever an \#elifdef is skipped. Elifdef(SourceLocation Loc,SourceRange ConditionRange,SourceLocation IfLoc)727 void Elifdef(SourceLocation Loc, SourceRange ConditionRange, 728 SourceLocation IfLoc) override { 729 First->Elifdef(Loc, ConditionRange, IfLoc); 730 Second->Elifdef(Loc, ConditionRange, IfLoc); 731 } 732 733 /// Hook called whenever an \#ifndef is seen. Ifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)734 void Ifndef(SourceLocation Loc, const Token &MacroNameTok, 735 const MacroDefinition &MD) override { 736 First->Ifndef(Loc, MacroNameTok, MD); 737 Second->Ifndef(Loc, MacroNameTok, MD); 738 } 739 740 /// Hook called whenever an \#elifndef is taken. Elifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)741 void Elifndef(SourceLocation Loc, const Token &MacroNameTok, 742 const MacroDefinition &MD) override { 743 First->Elifndef(Loc, MacroNameTok, MD); 744 Second->Elifndef(Loc, MacroNameTok, MD); 745 } 746 /// Hook called whenever an \#elifndef is skipped. Elifndef(SourceLocation Loc,SourceRange ConditionRange,SourceLocation IfLoc)747 void Elifndef(SourceLocation Loc, SourceRange ConditionRange, 748 SourceLocation IfLoc) override { 749 First->Elifndef(Loc, ConditionRange, IfLoc); 750 Second->Elifndef(Loc, ConditionRange, IfLoc); 751 } 752 753 /// Hook called whenever an \#else is seen. Else(SourceLocation Loc,SourceLocation IfLoc)754 void Else(SourceLocation Loc, SourceLocation IfLoc) override { 755 First->Else(Loc, IfLoc); 756 Second->Else(Loc, IfLoc); 757 } 758 759 /// Hook called whenever an \#endif is seen. Endif(SourceLocation Loc,SourceLocation IfLoc)760 void Endif(SourceLocation Loc, SourceLocation IfLoc) override { 761 First->Endif(Loc, IfLoc); 762 Second->Endif(Loc, IfLoc); 763 } 764 }; 765 766 } // end namespace clang 767 768 #endif 769