Home | History | Annotate | Line # | Download | only in Lex
      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 
     31 /// This interface provides a way to observe the actions of the
     32 /// preprocessor as it does its thing.
     33 ///
     34 /// Clients can define their hooks here to implement preprocessor level tools.
     35 class PPCallbacks {
     36 public:
     37   virtual ~PPCallbacks();
     38 
     39   enum FileChangeReason {
     40     EnterFile, ExitFile, SystemHeaderPragma, RenameFile
     41   };
     42 
     43   /// Callback invoked whenever a source file is entered or exited.
     44   ///
     45   /// \param Loc Indicates the new location.
     46   /// \param PrevFID the file that was exited if \p Reason is ExitFile.
     47   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
     48                            SrcMgr::CharacteristicKind FileType,
     49                            FileID PrevFID = FileID()) {
     50   }
     51 
     52   /// Callback invoked whenever a source file is skipped as the result
     53   /// of header guard optimization.
     54   ///
     55   /// \param SkippedFile The file that is skipped instead of entering \#include
     56   ///
     57   /// \param FilenameTok The file name token in \#include "FileName" directive
     58   /// or macro expanded file name token from \#include MACRO(PARAMS) directive.
     59   /// Note that FilenameTok contains corresponding quotes/angles symbols.
     60   virtual void FileSkipped(const FileEntryRef &SkippedFile,
     61                            const Token &FilenameTok,
     62                            SrcMgr::CharacteristicKind FileType) {}
     63 
     64   /// Callback invoked whenever an inclusion directive results in a
     65   /// file-not-found error.
     66   ///
     67   /// \param FileName The name of the file being included, as written in the
     68   /// source code.
     69   ///
     70   /// \param RecoveryPath If this client indicates that it can recover from
     71   /// this missing file, the client should set this as an additional header
     72   /// search patch.
     73   ///
     74   /// \returns true to indicate that the preprocessor should attempt to recover
     75   /// by adding \p RecoveryPath as a header search path.
     76   virtual bool FileNotFound(StringRef FileName,
     77                             SmallVectorImpl<char> &RecoveryPath) {
     78     return false;
     79   }
     80 
     81   /// Callback invoked whenever an inclusion directive of
     82   /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
     83   /// of whether the inclusion will actually result in an inclusion.
     84   ///
     85   /// \param HashLoc The location of the '#' that starts the inclusion
     86   /// directive.
     87   ///
     88   /// \param IncludeTok The token that indicates the kind of inclusion
     89   /// directive, e.g., 'include' or 'import'.
     90   ///
     91   /// \param FileName The name of the file being included, as written in the
     92   /// source code.
     93   ///
     94   /// \param IsAngled Whether the file name was enclosed in angle brackets;
     95   /// otherwise, it was enclosed in quotes.
     96   ///
     97   /// \param FilenameRange The character range of the quotes or angle brackets
     98   /// for the written file name.
     99   ///
    100   /// \param File The actual file that may be included by this inclusion
    101   /// directive.
    102   ///
    103   /// \param SearchPath Contains the search path which was used to find the file
    104   /// in the file system. If the file was found via an absolute include path,
    105   /// SearchPath will be empty. For framework includes, the SearchPath and
    106   /// RelativePath will be split up. For example, if an include of "Some/Some.h"
    107   /// is found via the framework path
    108   /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
    109   /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
    110   /// "Some.h".
    111   ///
    112   /// \param RelativePath The path relative to SearchPath, at which the include
    113   /// file was found. This is equal to FileName except for framework includes.
    114   ///
    115   /// \param Imported The module, whenever an inclusion directive was
    116   /// automatically turned into a module import or null otherwise.
    117   ///
    118   /// \param FileType The characteristic kind, indicates whether a file or
    119   /// directory holds normal user code, system code, or system code which is
    120   /// implicitly 'extern "C"' in C++ mode.
    121   ///
    122   virtual void InclusionDirective(SourceLocation HashLoc,
    123                                   const Token &IncludeTok,
    124                                   StringRef FileName,
    125                                   bool IsAngled,
    126                                   CharSourceRange FilenameRange,
    127                                   const FileEntry *File,
    128                                   StringRef SearchPath,
    129                                   StringRef RelativePath,
    130                                   const Module *Imported,
    131                                   SrcMgr::CharacteristicKind FileType) {
    132   }
    133 
    134   /// Callback invoked whenever a submodule was entered.
    135   ///
    136   /// \param M The submodule we have entered.
    137   ///
    138   /// \param ImportLoc The location of import directive token.
    139   ///
    140   /// \param ForPragma If entering from pragma directive.
    141   ///
    142   virtual void EnteredSubmodule(Module *M, SourceLocation ImportLoc,
    143                                 bool ForPragma) { }
    144 
    145   /// Callback invoked whenever a submodule was left.
    146   ///
    147   /// \param M The submodule we have left.
    148   ///
    149   /// \param ImportLoc The location of import directive token.
    150   ///
    151   /// \param ForPragma If entering from pragma directive.
    152   ///
    153   virtual void LeftSubmodule(Module *M, SourceLocation ImportLoc,
    154                              bool ForPragma) { }
    155 
    156   /// Callback invoked whenever there was an explicit module-import
    157   /// syntax.
    158   ///
    159   /// \param ImportLoc The location of import directive token.
    160   ///
    161   /// \param Path The identifiers (and their locations) of the module
    162   /// "path", e.g., "std.vector" would be split into "std" and "vector".
    163   ///
    164   /// \param Imported The imported module; can be null if importing failed.
    165   ///
    166   virtual void moduleImport(SourceLocation ImportLoc,
    167                             ModuleIdPath Path,
    168                             const Module *Imported) {
    169   }
    170 
    171   /// Callback invoked when the end of the main file is reached.
    172   ///
    173   /// No subsequent callbacks will be made.
    174   virtual void EndOfMainFile() {
    175   }
    176 
    177   /// Callback invoked when a \#ident or \#sccs directive is read.
    178   /// \param Loc The location of the directive.
    179   /// \param str The text of the directive.
    180   ///
    181   virtual void Ident(SourceLocation Loc, StringRef str) {
    182   }
    183 
    184   /// Callback invoked when start reading any pragma directive.
    185   virtual void PragmaDirective(SourceLocation Loc,
    186                                PragmaIntroducerKind Introducer) {
    187   }
    188 
    189   /// Callback invoked when a \#pragma comment directive is read.
    190   virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
    191                              StringRef Str) {
    192   }
    193 
    194   /// Callback invoked when a \#pragma detect_mismatch directive is
    195   /// read.
    196   virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
    197                                     StringRef Value) {
    198   }
    199 
    200   /// Callback invoked when a \#pragma clang __debug directive is read.
    201   /// \param Loc The location of the debug directive.
    202   /// \param DebugType The identifier following __debug.
    203   virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) {
    204   }
    205 
    206   /// Determines the kind of \#pragma invoking a call to PragmaMessage.
    207   enum PragmaMessageKind {
    208     /// \#pragma message has been invoked.
    209     PMK_Message,
    210 
    211     /// \#pragma GCC warning has been invoked.
    212     PMK_Warning,
    213 
    214     /// \#pragma GCC error has been invoked.
    215     PMK_Error
    216   };
    217 
    218   /// Callback invoked when a \#pragma message directive is read.
    219   /// \param Loc The location of the message directive.
    220   /// \param Namespace The namespace of the message directive.
    221   /// \param Kind The type of the message directive.
    222   /// \param Str The text of the message directive.
    223   virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
    224                              PragmaMessageKind Kind, StringRef Str) {
    225   }
    226 
    227   /// Callback invoked when a \#pragma gcc diagnostic push directive
    228   /// is read.
    229   virtual void PragmaDiagnosticPush(SourceLocation Loc,
    230                                     StringRef Namespace) {
    231   }
    232 
    233   /// Callback invoked when a \#pragma gcc diagnostic pop directive
    234   /// is read.
    235   virtual void PragmaDiagnosticPop(SourceLocation Loc,
    236                                    StringRef Namespace) {
    237   }
    238 
    239   /// Callback invoked when a \#pragma gcc diagnostic directive is read.
    240   virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
    241                                 diag::Severity mapping, StringRef Str) {}
    242 
    243   /// Called when an OpenCL extension is either disabled or
    244   /// enabled with a pragma.
    245   virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
    246                                      const IdentifierInfo *Name,
    247                                      SourceLocation StateLoc, unsigned State) {
    248   }
    249 
    250   /// Callback invoked when a \#pragma warning directive is read.
    251   virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
    252                              ArrayRef<int> Ids) {
    253   }
    254 
    255   /// Callback invoked when a \#pragma warning(push) directive is read.
    256   virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
    257   }
    258 
    259   /// Callback invoked when a \#pragma warning(pop) directive is read.
    260   virtual void PragmaWarningPop(SourceLocation Loc) {
    261   }
    262 
    263   /// Callback invoked when a \#pragma execution_character_set(push) directive
    264   /// is read.
    265   virtual void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) {}
    266 
    267   /// Callback invoked when a \#pragma execution_character_set(pop) directive
    268   /// is read.
    269   virtual void PragmaExecCharsetPop(SourceLocation Loc) {}
    270 
    271   /// Callback invoked when a \#pragma clang assume_nonnull begin directive
    272   /// is read.
    273   virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {}
    274 
    275   /// Callback invoked when a \#pragma clang assume_nonnull end directive
    276   /// is read.
    277   virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {}
    278 
    279   /// Called by Preprocessor::HandleMacroExpandedIdentifier when a
    280   /// macro invocation is found.
    281   virtual void MacroExpands(const Token &MacroNameTok,
    282                             const MacroDefinition &MD, SourceRange Range,
    283                             const MacroArgs *Args) {}
    284 
    285   /// Hook called whenever a macro definition is seen.
    286   virtual void MacroDefined(const Token &MacroNameTok,
    287                             const MacroDirective *MD) {
    288   }
    289 
    290   /// Hook called whenever a macro \#undef is seen.
    291   /// \param MacroNameTok The active Token
    292   /// \param MD A MacroDefinition for the named macro.
    293   /// \param Undef New MacroDirective if the macro was defined, null otherwise.
    294   ///
    295   /// MD is released immediately following this callback.
    296   virtual void MacroUndefined(const Token &MacroNameTok,
    297                               const MacroDefinition &MD,
    298                               const MacroDirective *Undef) {
    299   }
    300 
    301   /// Hook called whenever the 'defined' operator is seen.
    302   /// \param MD The MacroDirective if the name was a macro, null otherwise.
    303   virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
    304                        SourceRange Range) {
    305   }
    306 
    307   /// Hook called when a '__has_include' or '__has_include_next' directive is
    308   /// read.
    309   virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
    310                           Optional<FileEntryRef> File,
    311                           SrcMgr::CharacteristicKind FileType);
    312 
    313   /// Hook called when a source range is skipped.
    314   /// \param Range The SourceRange that was skipped. The range begins at the
    315   /// \#if/\#else directive and ends after the \#endif/\#else directive.
    316   /// \param EndifLoc The end location of the 'endif' token, which may precede
    317   /// the range skipped by the directive (e.g excluding comments after an
    318   /// 'endif').
    319   virtual void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) {
    320   }
    321 
    322   enum ConditionValueKind {
    323     CVK_NotEvaluated, CVK_False, CVK_True
    324   };
    325 
    326   /// Hook called whenever an \#if is seen.
    327   /// \param Loc the source location of the directive.
    328   /// \param ConditionRange The SourceRange of the expression being tested.
    329   /// \param ConditionValue The evaluated value of the condition.
    330   ///
    331   // FIXME: better to pass in a list (or tree!) of Tokens.
    332   virtual void If(SourceLocation Loc, SourceRange ConditionRange,
    333                   ConditionValueKind ConditionValue) {
    334   }
    335 
    336   /// Hook called whenever an \#elif is seen.
    337   /// \param Loc the source location of the directive.
    338   /// \param ConditionRange The SourceRange of the expression being tested.
    339   /// \param ConditionValue The evaluated value of the condition.
    340   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
    341   // FIXME: better to pass in a list (or tree!) of Tokens.
    342   virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
    343                     ConditionValueKind ConditionValue, SourceLocation IfLoc) {
    344   }
    345 
    346   /// Hook called whenever an \#ifdef is seen.
    347   /// \param Loc the source location of the directive.
    348   /// \param MacroNameTok Information on the token being tested.
    349   /// \param MD The MacroDefinition if the name was a macro, null otherwise.
    350   virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
    351                      const MacroDefinition &MD) {
    352   }
    353 
    354   /// Hook called whenever an \#ifndef is seen.
    355   /// \param Loc the source location of the directive.
    356   /// \param MacroNameTok Information on the token being tested.
    357   /// \param MD The MacroDefiniton if the name was a macro, null otherwise.
    358   virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
    359                       const MacroDefinition &MD) {
    360   }
    361 
    362   /// Hook called whenever an \#else is seen.
    363   /// \param Loc the source location of the directive.
    364   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
    365   virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
    366   }
    367 
    368   /// Hook called whenever an \#endif is seen.
    369   /// \param Loc the source location of the directive.
    370   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
    371   virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
    372   }
    373 };
    374 
    375 /// Simple wrapper class for chaining callbacks.
    376 class PPChainedCallbacks : public PPCallbacks {
    377   std::unique_ptr<PPCallbacks> First, Second;
    378 
    379 public:
    380   PPChainedCallbacks(std::unique_ptr<PPCallbacks> _First,
    381                      std::unique_ptr<PPCallbacks> _Second)
    382     : First(std::move(_First)), Second(std::move(_Second)) {}
    383 
    384   ~PPChainedCallbacks() override;
    385 
    386   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
    387                    SrcMgr::CharacteristicKind FileType,
    388                    FileID PrevFID) override {
    389     First->FileChanged(Loc, Reason, FileType, PrevFID);
    390     Second->FileChanged(Loc, Reason, FileType, PrevFID);
    391   }
    392 
    393   void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
    394                    SrcMgr::CharacteristicKind FileType) override {
    395     First->FileSkipped(SkippedFile, FilenameTok, FileType);
    396     Second->FileSkipped(SkippedFile, FilenameTok, FileType);
    397   }
    398 
    399   bool FileNotFound(StringRef FileName,
    400                     SmallVectorImpl<char> &RecoveryPath) override {
    401     return First->FileNotFound(FileName, RecoveryPath) ||
    402            Second->FileNotFound(FileName, RecoveryPath);
    403   }
    404 
    405   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
    406                           StringRef FileName, bool IsAngled,
    407                           CharSourceRange FilenameRange, const FileEntry *File,
    408                           StringRef SearchPath, StringRef RelativePath,
    409                           const Module *Imported,
    410                           SrcMgr::CharacteristicKind FileType) override {
    411     First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
    412                               FilenameRange, File, SearchPath, RelativePath,
    413                               Imported, FileType);
    414     Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
    415                                FilenameRange, File, SearchPath, RelativePath,
    416                                Imported, FileType);
    417   }
    418 
    419   void EnteredSubmodule(Module *M, SourceLocation ImportLoc,
    420                         bool ForPragma) override {
    421     First->EnteredSubmodule(M, ImportLoc, ForPragma);
    422     Second->EnteredSubmodule(M, ImportLoc, ForPragma);
    423   }
    424 
    425   void LeftSubmodule(Module *M, SourceLocation ImportLoc,
    426                      bool ForPragma) override {
    427     First->LeftSubmodule(M, ImportLoc, ForPragma);
    428     Second->LeftSubmodule(M, ImportLoc, ForPragma);
    429   }
    430 
    431   void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
    432                     const Module *Imported) override {
    433     First->moduleImport(ImportLoc, Path, Imported);
    434     Second->moduleImport(ImportLoc, Path, Imported);
    435   }
    436 
    437   void EndOfMainFile() override {
    438     First->EndOfMainFile();
    439     Second->EndOfMainFile();
    440   }
    441 
    442   void Ident(SourceLocation Loc, StringRef str) override {
    443     First->Ident(Loc, str);
    444     Second->Ident(Loc, str);
    445   }
    446 
    447   void PragmaDirective(SourceLocation Loc,
    448                        PragmaIntroducerKind Introducer) override {
    449     First->PragmaDirective(Loc, Introducer);
    450     Second->PragmaDirective(Loc, Introducer);
    451   }
    452 
    453   void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
    454                      StringRef Str) override {
    455     First->PragmaComment(Loc, Kind, Str);
    456     Second->PragmaComment(Loc, Kind, Str);
    457   }
    458 
    459   void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
    460                             StringRef Value) override {
    461     First->PragmaDetectMismatch(Loc, Name, Value);
    462     Second->PragmaDetectMismatch(Loc, Name, Value);
    463   }
    464 
    465   void PragmaDebug(SourceLocation Loc, StringRef DebugType) override {
    466     First->PragmaDebug(Loc, DebugType);
    467     Second->PragmaDebug(Loc, DebugType);
    468   }
    469 
    470   void PragmaMessage(SourceLocation Loc, StringRef Namespace,
    471                      PragmaMessageKind Kind, StringRef Str) override {
    472     First->PragmaMessage(Loc, Namespace, Kind, Str);
    473     Second->PragmaMessage(Loc, Namespace, Kind, Str);
    474   }
    475 
    476   void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override {
    477     First->PragmaDiagnosticPush(Loc, Namespace);
    478     Second->PragmaDiagnosticPush(Loc, Namespace);
    479   }
    480 
    481   void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override {
    482     First->PragmaDiagnosticPop(Loc, Namespace);
    483     Second->PragmaDiagnosticPop(Loc, Namespace);
    484   }
    485 
    486   void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
    487                         diag::Severity mapping, StringRef Str) override {
    488     First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
    489     Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
    490   }
    491 
    492   void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
    493                   Optional<FileEntryRef> File,
    494                   SrcMgr::CharacteristicKind FileType) override;
    495 
    496   void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name,
    497                              SourceLocation StateLoc, unsigned State) override {
    498     First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
    499     Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
    500   }
    501 
    502   void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
    503                      ArrayRef<int> Ids) override {
    504     First->PragmaWarning(Loc, WarningSpec, Ids);
    505     Second->PragmaWarning(Loc, WarningSpec, Ids);
    506   }
    507 
    508   void PragmaWarningPush(SourceLocation Loc, int Level) override {
    509     First->PragmaWarningPush(Loc, Level);
    510     Second->PragmaWarningPush(Loc, Level);
    511   }
    512 
    513   void PragmaWarningPop(SourceLocation Loc) override {
    514     First->PragmaWarningPop(Loc);
    515     Second->PragmaWarningPop(Loc);
    516   }
    517 
    518   void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override {
    519     First->PragmaExecCharsetPush(Loc, Str);
    520     Second->PragmaExecCharsetPush(Loc, Str);
    521   }
    522 
    523   void PragmaExecCharsetPop(SourceLocation Loc) override {
    524     First->PragmaExecCharsetPop(Loc);
    525     Second->PragmaExecCharsetPop(Loc);
    526   }
    527 
    528   void PragmaAssumeNonNullBegin(SourceLocation Loc) override {
    529     First->PragmaAssumeNonNullBegin(Loc);
    530     Second->PragmaAssumeNonNullBegin(Loc);
    531   }
    532 
    533   void PragmaAssumeNonNullEnd(SourceLocation Loc) override {
    534     First->PragmaAssumeNonNullEnd(Loc);
    535     Second->PragmaAssumeNonNullEnd(Loc);
    536   }
    537 
    538   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
    539                     SourceRange Range, const MacroArgs *Args) override {
    540     First->MacroExpands(MacroNameTok, MD, Range, Args);
    541     Second->MacroExpands(MacroNameTok, MD, Range, Args);
    542   }
    543 
    544   void MacroDefined(const Token &MacroNameTok,
    545                     const MacroDirective *MD) override {
    546     First->MacroDefined(MacroNameTok, MD);
    547     Second->MacroDefined(MacroNameTok, MD);
    548   }
    549 
    550   void MacroUndefined(const Token &MacroNameTok,
    551                       const MacroDefinition &MD,
    552                       const MacroDirective *Undef) override {
    553     First->MacroUndefined(MacroNameTok, MD, Undef);
    554     Second->MacroUndefined(MacroNameTok, MD, Undef);
    555   }
    556 
    557   void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
    558                SourceRange Range) override {
    559     First->Defined(MacroNameTok, MD, Range);
    560     Second->Defined(MacroNameTok, MD, Range);
    561   }
    562 
    563   void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override {
    564     First->SourceRangeSkipped(Range, EndifLoc);
    565     Second->SourceRangeSkipped(Range, EndifLoc);
    566   }
    567 
    568   /// Hook called whenever an \#if is seen.
    569   void If(SourceLocation Loc, SourceRange ConditionRange,
    570           ConditionValueKind ConditionValue) override {
    571     First->If(Loc, ConditionRange, ConditionValue);
    572     Second->If(Loc, ConditionRange, ConditionValue);
    573   }
    574 
    575   /// Hook called whenever an \#elif is seen.
    576   void Elif(SourceLocation Loc, SourceRange ConditionRange,
    577             ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
    578     First->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
    579     Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
    580   }
    581 
    582   /// Hook called whenever an \#ifdef is seen.
    583   void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
    584              const MacroDefinition &MD) override {
    585     First->Ifdef(Loc, MacroNameTok, MD);
    586     Second->Ifdef(Loc, MacroNameTok, MD);
    587   }
    588 
    589   /// Hook called whenever an \#ifndef is seen.
    590   void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
    591               const MacroDefinition &MD) override {
    592     First->Ifndef(Loc, MacroNameTok, MD);
    593     Second->Ifndef(Loc, MacroNameTok, MD);
    594   }
    595 
    596   /// Hook called whenever an \#else is seen.
    597   void Else(SourceLocation Loc, SourceLocation IfLoc) override {
    598     First->Else(Loc, IfLoc);
    599     Second->Else(Loc, IfLoc);
    600   }
    601 
    602   /// Hook called whenever an \#endif is seen.
    603   void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
    604     First->Endif(Loc, IfLoc);
    605     Second->Endif(Loc, IfLoc);
    606   }
    607 };
    608 
    609 }  // end namespace clang
    610 
    611 #endif
    612