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