PPCallbacks.h revision 076eea20b80024fc63bbd71fb019375983680ea6
1cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org//===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- C++ -*-===//
2cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org//
3cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org//                     The LLVM Compiler Infrastructure
4cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org//
5cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org// This file is distributed under the University of Illinois Open Source
6cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org// License. See LICENSE.TXT for details.
7cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org//
8cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org//===----------------------------------------------------------------------===//
9cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org///
10cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// \file
11cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// \brief Defines the PPCallbacks interface.
12cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org///
13cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org//===----------------------------------------------------------------------===//
14cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
15cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#ifndef LLVM_CLANG_LEX_PPCALLBACKS_H
16cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#define LLVM_CLANG_LEX_PPCALLBACKS_H
17cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
18cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#include "clang/Basic/DiagnosticIDs.h"
19cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#include "clang/Basic/SourceLocation.h"
20cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#include "clang/Lex/DirectoryLookup.h"
21cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#include "clang/Lex/ModuleLoader.h"
22cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#include "llvm/ADT/StringRef.h"
23cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#include <string>
24cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
25cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.orgnamespace clang {
26cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  class SourceLocation;
27cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  class Token;
28cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  class IdentifierInfo;
29cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  class MacroDirective;
30cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
31cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// \brief This interface provides a way to observe the actions of the
32cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// preprocessor as it does its thing.
33cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org///
34cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org/// Clients can define their hooks here to implement preprocessor level tools.
35cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.orgclass PPCallbacks {
36cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.orgpublic:
37cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  virtual ~PPCallbacks();
38cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
39cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  enum FileChangeReason {
40cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    EnterFile, ExitFile, SystemHeaderPragma, RenameFile
41cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  };
42cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
43cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \brief Callback invoked whenever a source file is entered or exited.
44cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
45cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param Loc Indicates the new location.
46cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param PrevFID the file that was exited if \p Reason is ExitFile.
47cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
48cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org                           SrcMgr::CharacteristicKind FileType,
49cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org                           FileID PrevFID = FileID()) {
50cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
51cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
52cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \brief Callback invoked whenever a source file is skipped as the result
53cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// of header guard optimization.
54cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
55cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param ParentFile The file that \#included the skipped file.
56cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
57cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param FilenameTok The token in ParentFile that indicates the
58cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// skipped file.
59cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  virtual void FileSkipped(const FileEntry &ParentFile,
60cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org                           const Token &FilenameTok,
61cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org                           SrcMgr::CharacteristicKind FileType) {
62cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
63cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
64cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \brief Callback invoked whenever an inclusion directive results in a
65cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// file-not-found error.
66cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
67cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param FileName The name of the file being included, as written in the
68cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// source code.
69cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
70cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param RecoveryPath If this client indicates that it can recover from
71cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// this missing file, the client should set this as an additional header
72cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// search patch.
73cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
74cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \returns true to indicate that the preprocessor should attempt to recover
75cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// by adding \p RecoveryPath as a header search path.
76cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  virtual bool FileNotFound(StringRef FileName,
77cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org                            SmallVectorImpl<char> &RecoveryPath) {
78cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    return false;
79cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
80cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
81cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \brief Callback invoked whenever an inclusion directive of
82cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
83cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// of whether the inclusion will actually result in an inclusion.
84cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
85cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param HashLoc The location of the '#' that starts the inclusion
86cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// directive.
87cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
88cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param IncludeTok The token that indicates the kind of inclusion
89cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// directive, e.g., 'include' or 'import'.
90cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
91cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param FileName The name of the file being included, as written in the
92cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// source code.
93cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
94cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param IsAngled Whether the file name was enclosed in angle brackets;
95cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// otherwise, it was enclosed in quotes.
96cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
97cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param FilenameRange The character range of the quotes or angle brackets
98cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// for the written file name.
99cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  ///
100cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// \param File The actual file that may be included by this inclusion
101cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  /// directive.
102  ///
103  /// \param SearchPath Contains the search path which was used to find the file
104  /// in the file system. If the file was found via an absolute include path,
105  /// SearchPath will be empty. For framework includes, the SearchPath and
106  /// RelativePath will be split up. For example, if an include of "Some/Some.h"
107  /// is found via the framework path
108  /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
109  /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
110  /// "Some.h".
111  ///
112  /// \param RelativePath The path relative to SearchPath, at which the include
113  /// file was found. This is equal to FileName except for framework includes.
114  ///
115  /// \param Imported The module, whenever an inclusion directive was
116  /// automatically turned into a module import or null otherwise.
117  ///
118  virtual void InclusionDirective(SourceLocation HashLoc,
119                                  const Token &IncludeTok,
120                                  StringRef FileName,
121                                  bool IsAngled,
122                                  CharSourceRange FilenameRange,
123                                  const FileEntry *File,
124                                  StringRef SearchPath,
125                                  StringRef RelativePath,
126                                  const Module *Imported) {
127  }
128
129  /// \brief Callback invoked whenever there was an explicit module-import
130  /// syntax.
131  ///
132  /// \param ImportLoc The location of import directive token.
133  ///
134  /// \param Path The identifiers (and their locations) of the module
135  /// "path", e.g., "std.vector" would be split into "std" and "vector".
136  ///
137  /// \param Imported The imported module; can be null if importing failed.
138  ///
139  virtual void moduleImport(SourceLocation ImportLoc,
140                            ModuleIdPath Path,
141                            const Module *Imported) {
142  }
143
144  /// \brief Callback invoked when the end of the main file is reached.
145  ///
146  /// No subsequent callbacks will be made.
147  virtual void EndOfMainFile() {
148  }
149
150  /// \brief Callback invoked when a \#ident or \#sccs directive is read.
151  /// \param Loc The location of the directive.
152  /// \param str The text of the directive.
153  ///
154  virtual void Ident(SourceLocation Loc, const std::string &str) {
155  }
156
157  /// \brief Callback invoked when a \#pragma comment directive is read.
158  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
159                             const std::string &Str) {
160  }
161
162  /// \brief Callback invoked when a \#pragma clang __debug directive is read.
163  /// \param Loc The location of the debug directive.
164  /// \param DebugType The identifier following __debug.
165  virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) {
166  }
167
168  /// \brief Determines the kind of \#pragma invoking a call to PragmaMessage.
169  enum PragmaMessageKind {
170    /// \brief \#pragma message has been invoked.
171    PMK_Message,
172
173    /// \brief \#pragma GCC warning has been invoked.
174    PMK_Warning,
175
176    /// \brief \#pragma GCC error has been invoked.
177    PMK_Error
178  };
179
180  /// \brief Callback invoked when a \#pragma message directive is read.
181  /// \param Loc The location of the message directive.
182  /// \param Namespace The namespace of the message directive.
183  /// \param Kind The type of the message directive.
184  /// \param Str The text of the message directive.
185  virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
186                             PragmaMessageKind Kind, StringRef Str) {
187  }
188
189  /// \brief Callback invoked when a \#pragma gcc dianostic push directive
190  /// is read.
191  virtual void PragmaDiagnosticPush(SourceLocation Loc,
192                                    StringRef Namespace) {
193  }
194
195  /// \brief Callback invoked when a \#pragma gcc dianostic pop directive
196  /// is read.
197  virtual void PragmaDiagnosticPop(SourceLocation Loc,
198                                   StringRef Namespace) {
199  }
200
201  /// \brief Callback invoked when a \#pragma gcc dianostic directive is read.
202  virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
203                                diag::Mapping mapping, StringRef Str) {
204  }
205
206  /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
207  /// macro invocation is found.
208  virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
209                            SourceRange Range) {
210  }
211
212  /// \brief Hook called whenever a macro definition is seen.
213  virtual void MacroDefined(const Token &MacroNameTok,
214                            const MacroDirective *MD) {
215  }
216
217  /// \brief Hook called whenever a macro \#undef is seen.
218  ///
219  /// MD is released immediately following this callback.
220  virtual void MacroUndefined(const Token &MacroNameTok,
221                              const MacroDirective *MD) {
222  }
223
224  /// \brief Hook called whenever the 'defined' operator is seen.
225  /// \param MD The MacroDirective if the name was a macro, null otherwise.
226  virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) {
227  }
228
229  /// \brief Hook called when a source range is skipped.
230  /// \param Range The SourceRange that was skipped. The range begins at the
231  /// \#if/\#else directive and ends after the \#endif/\#else directive.
232  virtual void SourceRangeSkipped(SourceRange Range) {
233  }
234
235  /// \brief Hook called whenever an \#if is seen.
236  /// \param Loc the source location of the directive.
237  /// \param ConditionRange The SourceRange of the expression being tested.
238  ///
239  // FIXME: better to pass in a list (or tree!) of Tokens.
240  virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
241  }
242
243  /// \brief Hook called whenever an \#elif is seen.
244  /// \param Loc the source location of the directive.
245  /// \param ConditionRange The SourceRange of the expression being tested.
246  /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
247  // FIXME: better to pass in a list (or tree!) of Tokens.
248  virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
249                    SourceLocation IfLoc) {
250  }
251
252  /// \brief Hook called whenever an \#ifdef is seen.
253  /// \param Loc the source location of the directive.
254  /// \param MacroNameTok Information on the token being tested.
255  /// \param MD The MacroDirective if the name was a macro, null otherwise.
256  virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
257                     const MacroDirective *MD) {
258  }
259
260  /// \brief Hook called whenever an \#ifndef is seen.
261  /// \param Loc the source location of the directive.
262  /// \param MacroNameTok Information on the token being tested.
263  /// \param MD The MacroDirective if the name was a macro, null otherwise.
264  virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
265                      const MacroDirective *MD) {
266  }
267
268  /// \brief Hook called whenever an \#else is seen.
269  /// \param Loc the source location of the directive.
270  /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
271  virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
272  }
273
274  /// \brief Hook called whenever an \#endif is seen.
275  /// \param Loc the source location of the directive.
276  /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
277  virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
278  }
279};
280
281/// \brief Simple wrapper class for chaining callbacks.
282class PPChainedCallbacks : public PPCallbacks {
283  virtual void anchor();
284  PPCallbacks *First, *Second;
285
286public:
287  PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
288    : First(_First), Second(_Second) {}
289  ~PPChainedCallbacks() {
290    delete Second;
291    delete First;
292  }
293
294  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
295                           SrcMgr::CharacteristicKind FileType,
296                           FileID PrevFID) {
297    First->FileChanged(Loc, Reason, FileType, PrevFID);
298    Second->FileChanged(Loc, Reason, FileType, PrevFID);
299  }
300
301  virtual void FileSkipped(const FileEntry &ParentFile,
302                           const Token &FilenameTok,
303                           SrcMgr::CharacteristicKind FileType) {
304    First->FileSkipped(ParentFile, FilenameTok, FileType);
305    Second->FileSkipped(ParentFile, FilenameTok, FileType);
306  }
307
308  virtual bool FileNotFound(StringRef FileName,
309                            SmallVectorImpl<char> &RecoveryPath) {
310    return First->FileNotFound(FileName, RecoveryPath) ||
311           Second->FileNotFound(FileName, RecoveryPath);
312  }
313
314  virtual void InclusionDirective(SourceLocation HashLoc,
315                                  const Token &IncludeTok,
316                                  StringRef FileName,
317                                  bool IsAngled,
318                                  CharSourceRange FilenameRange,
319                                  const FileEntry *File,
320                                  StringRef SearchPath,
321                                  StringRef RelativePath,
322                                  const Module *Imported) {
323    First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
324                              FilenameRange, File, SearchPath, RelativePath,
325                              Imported);
326    Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
327                               FilenameRange, File, SearchPath, RelativePath,
328                               Imported);
329  }
330
331  virtual void moduleImport(SourceLocation ImportLoc,
332                            ModuleIdPath Path,
333                            const Module *Imported) {
334    First->moduleImport(ImportLoc, Path, Imported);
335    Second->moduleImport(ImportLoc, Path, Imported);
336  }
337
338  virtual void EndOfMainFile() {
339    First->EndOfMainFile();
340    Second->EndOfMainFile();
341  }
342
343  virtual void Ident(SourceLocation Loc, const std::string &str) {
344    First->Ident(Loc, str);
345    Second->Ident(Loc, str);
346  }
347
348  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
349                             const std::string &Str) {
350    First->PragmaComment(Loc, Kind, Str);
351    Second->PragmaComment(Loc, Kind, Str);
352  }
353
354  virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
355                             PragmaMessageKind Kind, StringRef Str) {
356    First->PragmaMessage(Loc, Namespace, Kind, Str);
357    Second->PragmaMessage(Loc, Namespace, Kind, Str);
358  }
359
360  virtual void PragmaDiagnosticPush(SourceLocation Loc,
361                                    StringRef Namespace) {
362    First->PragmaDiagnosticPush(Loc, Namespace);
363    Second->PragmaDiagnosticPush(Loc, Namespace);
364  }
365
366  virtual void PragmaDiagnosticPop(SourceLocation Loc,
367                                    StringRef Namespace) {
368    First->PragmaDiagnosticPop(Loc, Namespace);
369    Second->PragmaDiagnosticPop(Loc, Namespace);
370  }
371
372  virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
373                                diag::Mapping mapping, StringRef Str) {
374    First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
375    Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
376  }
377
378  virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
379                            SourceRange Range) {
380    First->MacroExpands(MacroNameTok, MD, Range);
381    Second->MacroExpands(MacroNameTok, MD, Range);
382  }
383
384  virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {
385    First->MacroDefined(MacroNameTok, MD);
386    Second->MacroDefined(MacroNameTok, MD);
387  }
388
389  virtual void MacroUndefined(const Token &MacroNameTok,
390                              const MacroDirective *MD) {
391    First->MacroUndefined(MacroNameTok, MD);
392    Second->MacroUndefined(MacroNameTok, MD);
393  }
394
395  virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) {
396    First->Defined(MacroNameTok, MD);
397    Second->Defined(MacroNameTok, MD);
398  }
399
400  virtual void SourceRangeSkipped(SourceRange Range) {
401    First->SourceRangeSkipped(Range);
402    Second->SourceRangeSkipped(Range);
403  }
404
405  /// \brief Hook called whenever an \#if is seen.
406  virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
407    First->If(Loc, ConditionRange);
408    Second->If(Loc, ConditionRange);
409  }
410
411  /// \brief Hook called whenever an \#if is seen.
412  virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
413                    SourceLocation IfLoc) {
414    First->Elif(Loc, ConditionRange, IfLoc);
415    Second->Elif(Loc, ConditionRange, IfLoc);
416  }
417
418  /// \brief Hook called whenever an \#ifdef is seen.
419  virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
420                     const MacroDirective *MD) {
421    First->Ifdef(Loc, MacroNameTok, MD);
422    Second->Ifdef(Loc, MacroNameTok, MD);
423  }
424
425  /// \brief Hook called whenever an \#ifndef is seen.
426  virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
427                      const MacroDirective *MD) {
428    First->Ifndef(Loc, MacroNameTok, MD);
429    Second->Ifndef(Loc, MacroNameTok, MD);
430  }
431
432  /// \brief Hook called whenever an \#else is seen.
433  virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
434    First->Else(Loc, IfLoc);
435    Second->Else(Loc, IfLoc);
436  }
437
438  /// \brief Hook called whenever an \#endif is seen.
439  virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
440    First->Endif(Loc, IfLoc);
441    Second->Endif(Loc, IfLoc);
442  }
443};
444
445}  // end namespace clang
446
447#endif
448