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