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