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