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