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