PPCallbacks.h revision 1c2e9332fa69727425a3a2b912e36e2ab62083f8
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  PPCallbacks *First, *Second;
228
229public:
230  PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
231    : First(_First), Second(_Second) {}
232  ~PPChainedCallbacks() {
233    delete Second;
234    delete First;
235  }
236
237  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
238                           SrcMgr::CharacteristicKind FileType,
239                           FileID PrevFID) {
240    First->FileChanged(Loc, Reason, FileType, PrevFID);
241    Second->FileChanged(Loc, Reason, FileType, PrevFID);
242  }
243
244  virtual void FileSkipped(const FileEntry &ParentFile,
245                           const Token &FilenameTok,
246                           SrcMgr::CharacteristicKind FileType) {
247    First->FileSkipped(ParentFile, FilenameTok, FileType);
248    Second->FileSkipped(ParentFile, FilenameTok, FileType);
249  }
250
251  virtual bool FileNotFound(StringRef FileName,
252                            SmallVectorImpl<char> &RecoveryPath) {
253    return First->FileNotFound(FileName, RecoveryPath) ||
254           Second->FileNotFound(FileName, RecoveryPath);
255  }
256
257  virtual void InclusionDirective(SourceLocation HashLoc,
258                                  const Token &IncludeTok,
259                                  StringRef FileName,
260                                  bool IsAngled,
261                                  const FileEntry *File,
262                                  SourceLocation EndLoc,
263                                  StringRef SearchPath,
264                                  StringRef RelativePath) {
265    First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
266                              EndLoc, SearchPath, RelativePath);
267    Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
268                               EndLoc, SearchPath, RelativePath);
269  }
270
271  virtual void EndOfMainFile() {
272    First->EndOfMainFile();
273    Second->EndOfMainFile();
274  }
275
276  virtual void Ident(SourceLocation Loc, const std::string &str) {
277    First->Ident(Loc, str);
278    Second->Ident(Loc, str);
279  }
280
281  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
282                             const std::string &Str) {
283    First->PragmaComment(Loc, Kind, Str);
284    Second->PragmaComment(Loc, Kind, Str);
285  }
286
287  virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
288    First->PragmaMessage(Loc, Str);
289    Second->PragmaMessage(Loc, Str);
290  }
291
292  virtual void PragmaDiagnosticPush(SourceLocation Loc,
293                                    StringRef Namespace) {
294    First->PragmaDiagnosticPush(Loc, Namespace);
295    Second->PragmaDiagnosticPush(Loc, Namespace);
296  }
297
298  virtual void PragmaDiagnosticPop(SourceLocation Loc,
299                                    StringRef Namespace) {
300    First->PragmaDiagnosticPop(Loc, Namespace);
301    Second->PragmaDiagnosticPop(Loc, Namespace);
302  }
303
304  virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
305                                diag::Mapping mapping, StringRef Str) {
306    First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
307    Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
308  }
309
310  virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
311                            SourceRange Range) {
312    First->MacroExpands(MacroNameTok, MI, Range);
313    Second->MacroExpands(MacroNameTok, MI, Range);
314  }
315
316  virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
317    First->MacroDefined(MacroNameTok, MI);
318    Second->MacroDefined(MacroNameTok, MI);
319  }
320
321  virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
322    First->MacroUndefined(MacroNameTok, MI);
323    Second->MacroUndefined(MacroNameTok, MI);
324  }
325
326  virtual void Defined(const Token &MacroNameTok) {
327    First->Defined(MacroNameTok);
328    Second->Defined(MacroNameTok);
329  }
330
331  virtual void SourceRangeSkipped(SourceRange Range) {
332    First->SourceRangeSkipped(Range);
333    Second->SourceRangeSkipped(Range);
334  }
335
336  /// If -- This hook is called whenever an #if is seen.
337  virtual void If(SourceRange Range) {
338    First->If(Range);
339    Second->If(Range);
340  }
341
342  /// Elif -- This hook is called whenever an #if is seen.
343  virtual void Elif(SourceRange Range) {
344    First->Elif(Range);
345    Second->Elif(Range);
346  }
347
348  /// Ifdef -- This hook is called whenever an #ifdef is seen.
349  virtual void Ifdef(const Token &MacroNameTok) {
350    First->Ifdef(MacroNameTok);
351    Second->Ifdef(MacroNameTok);
352  }
353
354  /// Ifndef -- This hook is called whenever an #ifndef is seen.
355  virtual void Ifndef(const Token &MacroNameTok) {
356    First->Ifndef(MacroNameTok);
357    Second->Ifndef(MacroNameTok);
358  }
359
360  /// Else -- This hook is called whenever an #else is seen.
361  virtual void Else() {
362    First->Else();
363    Second->Else();
364  }
365
366  /// Endif -- This hook is called whenever an #endif is seen.
367  virtual void Endif() {
368    First->Endif();
369    Second->Endif();
370  }
371};
372
373}  // end namespace clang
374
375#endif
376