| 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, , 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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 | /// |
| 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 | /// |
| 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 | /// |
| 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 | /// |
| 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. |
| 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 | /// |
| 225 | virtual void Ident(SourceLocation Loc, StringRef str) { |
| 226 | } |
| 227 | |
| 228 | /// Callback invoked when start reading any pragma directive. |
| 229 | virtual void PragmaDirective(SourceLocation Loc, |
| 230 | PragmaIntroducerKind Introducer) { |
| 231 | } |
| 232 | |
| 233 | /// Callback invoked when a \#pragma comment directive is read. |
| 234 | virtual void (SourceLocation Loc, const IdentifierInfo *Kind, |
| 235 | StringRef Str) { |
| 236 | } |
| 237 | |
| 238 | /// Callback invoked when a \#pragma mark comment is read. |
| 239 | virtual void PragmaMark(SourceLocation Loc, StringRef Trivia) { |
| 240 | } |
| 241 | |
| 242 | /// Callback invoked when a \#pragma detect_mismatch directive is |
| 243 | /// read. |
| 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. |
| 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. |
| 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. |
| 277 | virtual void PragmaDiagnosticPush(SourceLocation Loc, |
| 278 | StringRef Namespace) { |
| 279 | } |
| 280 | |
| 281 | /// Callback invoked when a \#pragma gcc diagnostic pop directive |
| 282 | /// is read. |
| 283 | virtual void PragmaDiagnosticPop(SourceLocation Loc, |
| 284 | StringRef Namespace) { |
| 285 | } |
| 286 | |
| 287 | /// Callback invoked when a \#pragma gcc diagnostic directive is read. |
| 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. |
| 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 | }; |
| 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. |
| 315 | virtual void PragmaWarningPush(SourceLocation Loc, int Level) { |
| 316 | } |
| 317 | |
| 318 | /// Callback invoked when a \#pragma warning(pop) directive is read. |
| 319 | virtual void PragmaWarningPop(SourceLocation Loc) { |
| 320 | } |
| 321 | |
| 322 | /// Callback invoked when a \#pragma execution_character_set(push) directive |
| 323 | /// is read. |
| 324 | virtual void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) {} |
| 325 | |
| 326 | /// Callback invoked when a \#pragma execution_character_set(pop) directive |
| 327 | /// is read. |
| 328 | virtual void PragmaExecCharsetPop(SourceLocation Loc) {} |
| 329 | |
| 330 | /// Callback invoked when a \#pragma clang assume_nonnull begin directive |
| 331 | /// is read. |
| 332 | virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {} |
| 333 | |
| 334 | /// Callback invoked when a \#pragma clang assume_nonnull end directive |
| 335 | /// is read. |
| 336 | virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {} |
| 337 | |
| 338 | /// Called by Preprocessor::HandleMacroExpandedIdentifier when a |
| 339 | /// macro invocation is found. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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'). |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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: |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 557 | void EndOfMainFile() override { |
| 558 | First->EndOfMainFile(); |
| 559 | Second->EndOfMainFile(); |
| 560 | } |
| 561 | |
| 562 | void Ident(SourceLocation Loc, StringRef str) override { |
| 563 | First->Ident(Loc, str); |
| 564 | Second->Ident(Loc, str); |
| 565 | } |
| 566 | |
| 567 | void PragmaDirective(SourceLocation Loc, |
| 568 | PragmaIntroducerKind Introducer) override { |
| 569 | First->PragmaDirective(Loc, Introducer); |
| 570 | Second->PragmaDirective(Loc, Introducer); |
| 571 | } |
| 572 | |
| 573 | void (SourceLocation Loc, const IdentifierInfo *Kind, |
| 574 | StringRef Str) override { |
| 575 | First->PragmaComment(Loc, Kind, Str); |
| 576 | Second->PragmaComment(Loc, Kind, Str); |
| 577 | } |
| 578 | |
| 579 | void PragmaMark(SourceLocation Loc, StringRef Trivia) override { |
| 580 | First->PragmaMark(Loc, Trivia); |
| 581 | Second->PragmaMark(Loc, Trivia); |
| 582 | } |
| 583 | |
| 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 | |
| 590 | void PragmaDebug(SourceLocation Loc, StringRef DebugType) override { |
| 591 | First->PragmaDebug(Loc, DebugType); |
| 592 | Second->PragmaDebug(Loc, DebugType); |
| 593 | } |
| 594 | |
| 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 | |
| 601 | void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override { |
| 602 | First->PragmaDiagnosticPush(Loc, Namespace); |
| 603 | Second->PragmaDiagnosticPush(Loc, Namespace); |
| 604 | } |
| 605 | |
| 606 | void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override { |
| 607 | First->PragmaDiagnosticPop(Loc, Namespace); |
| 608 | Second->PragmaDiagnosticPop(Loc, Namespace); |
| 609 | } |
| 610 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 639 | void PragmaWarningPush(SourceLocation Loc, int Level) override { |
| 640 | First->PragmaWarningPush(Loc, Level); |
| 641 | Second->PragmaWarningPush(Loc, Level); |
| 642 | } |
| 643 | |
| 644 | void PragmaWarningPop(SourceLocation Loc) override { |
| 645 | First->PragmaWarningPop(Loc); |
| 646 | Second->PragmaWarningPop(Loc); |
| 647 | } |
| 648 | |
| 649 | void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override { |
| 650 | First->PragmaExecCharsetPush(Loc, Str); |
| 651 | Second->PragmaExecCharsetPush(Loc, Str); |
| 652 | } |
| 653 | |
| 654 | void PragmaExecCharsetPop(SourceLocation Loc) override { |
| 655 | First->PragmaExecCharsetPop(Loc); |
| 656 | Second->PragmaExecCharsetPop(Loc); |
| 657 | } |
| 658 | |
| 659 | void PragmaAssumeNonNullBegin(SourceLocation Loc) override { |
| 660 | First->PragmaAssumeNonNullBegin(Loc); |
| 661 | Second->PragmaAssumeNonNullBegin(Loc); |
| 662 | } |
| 663 | |
| 664 | void PragmaAssumeNonNullEnd(SourceLocation Loc) override { |
| 665 | First->PragmaAssumeNonNullEnd(Loc); |
| 666 | Second->PragmaAssumeNonNullEnd(Loc); |
| 667 | } |
| 668 | |
| 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 | |
| 675 | void MacroDefined(const Token &MacroNameTok, |
| 676 | const MacroDirective *MD) override { |
| 677 | First->MacroDefined(MacroNameTok, MD); |
| 678 | Second->MacroDefined(MacroNameTok, MD); |
| 679 | } |
| 680 | |
| 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 | |
| 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 | |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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 | |