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