PPCallbacks.h revision c892c5fa92db137ff68d95afb13fe969d17f4fb2
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  /// \brief This callback is invoked whenever an inclusion directive of
62  /// any kind (\c #include, \c #import, etc.) has been processed, regardless
63  /// of whether the inclusion will actually result in an inclusion.
64  ///
65  /// \param HashLoc The location of the '#' that starts the inclusion
66  /// directive.
67  ///
68  /// \param IncludeTok The token that indicates the kind of inclusion
69  /// directive, e.g., 'include' or 'import'.
70  ///
71  /// \param FileName The name of the file being included, as written in the
72  /// source code.
73  ///
74  /// \param IsAngled Whether the file name was enclosed in angle brackets;
75  /// otherwise, it was enclosed in quotes.
76  ///
77  /// \param File The actual file that may be included by this inclusion
78  /// directive.
79  ///
80  /// \param EndLoc The location of the last token within the inclusion
81  /// directive.
82  ///
83  /// \param SearchPath Contains the search path which was used to find the file
84  /// in the file system. If the file was found via an absolute include path,
85  /// SearchPath will be empty. For framework includes, the SearchPath and
86  /// RelativePath will be split up. For example, if an include of "Some/Some.h"
87  /// is found via the framework path
88  /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
89  /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
90  /// "Some.h".
91  ///
92  /// \param RelativePath The path relative to SearchPath, at which the include
93  /// file was found. This is equal to FileName except for framework includes.
94  virtual void InclusionDirective(SourceLocation HashLoc,
95                                  const Token &IncludeTok,
96                                  StringRef FileName,
97                                  bool IsAngled,
98                                  const FileEntry *File,
99                                  SourceLocation EndLoc,
100                                  StringRef SearchPath,
101                                  StringRef RelativePath) {
102  }
103
104  /// EndOfMainFile - This callback is invoked when the end of the main file is
105  /// reach, no subsequent callbacks will be made.
106  virtual void EndOfMainFile() {
107  }
108
109  /// Ident - This callback is invoked when a #ident or #sccs directive is read.
110  /// \param Loc The location of the directive.
111  /// \param str The text of the directive.
112  ///
113  virtual void Ident(SourceLocation Loc, const std::string &str) {
114  }
115
116  /// PragmaComment - This callback is invoked when a #pragma comment directive
117  /// is read.
118  ///
119  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
120                             const std::string &Str) {
121  }
122
123  /// PragmaMessage - This callback is invoked when a #pragma message directive
124  /// is read.
125  /// \param Loc The location of the message directive.
126  /// \param str The text of the message directive.
127  ///
128  virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
129  }
130
131  /// PragmaDiagnosticPush - This callback is invoked when a
132  /// #pragma gcc dianostic push directive is read.
133  virtual void PragmaDiagnosticPush(SourceLocation Loc,
134                                    StringRef Namespace) {
135  }
136
137  /// PragmaDiagnosticPop - This callback is invoked when a
138  /// #pragma gcc dianostic pop directive is read.
139  virtual void PragmaDiagnosticPop(SourceLocation Loc,
140                                   StringRef Namespace) {
141  }
142
143  /// PragmaDiagnostic - This callback is invoked when a
144  /// #pragma gcc dianostic directive is read.
145  virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
146                                diag::Mapping mapping, StringRef Str) {
147  }
148
149  /// MacroExpands - This is called by
150  /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
151  /// found.
152  virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
153                            SourceRange Range) {
154  }
155
156  /// MacroDefined - This hook is called whenever a macro definition is seen.
157  virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
158  }
159
160  /// MacroUndefined - This hook is called whenever a macro #undef is seen.
161  /// MI is released immediately following this callback.
162  virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
163  }
164
165  /// SourceRangeSkipped - This hook is called when a source range is skipped.
166  /// \param Range The SourceRange that was skipped. The range begins at the
167  /// #if/#else directive and ends after the #endif/#else directive.
168  virtual void SourceRangeSkipped(SourceRange Range) {
169  }
170
171  /// If -- This hook is called whenever an #if is seen.
172  /// \param Range The SourceRange of the expression being tested.
173  // FIXME: better to pass in a list (or tree!) of Tokens.
174  virtual void If(SourceRange Range) {
175  }
176
177  /// Elif -- This hook is called whenever an #elif is seen.
178  /// \param Range The SourceRange of the expression being tested.
179  // FIXME: better to pass in a list (or tree!) of Tokens.
180  virtual void Elif(SourceRange Range) {
181  }
182
183  /// Ifdef -- This hook is called whenever an #ifdef is seen.
184  /// \param Loc The location of the token being tested.
185  /// \param II Information on the token being tested.
186  virtual void Ifdef(const Token &MacroNameTok) {
187  }
188
189  /// Ifndef -- This hook is called whenever an #ifndef is seen.
190  /// \param Loc The location of the token being tested.
191  /// \param II Information on the token being tested.
192  virtual void Ifndef(const Token &MacroNameTok) {
193  }
194
195  /// Else -- This hook is called whenever an #else is seen.
196  virtual void Else() {
197  }
198
199  /// Endif -- This hook is called whenever an #endif is seen.
200  virtual void Endif() {
201  }
202};
203
204/// PPChainedCallbacks - Simple wrapper class for chaining callbacks.
205class PPChainedCallbacks : public PPCallbacks {
206  PPCallbacks *First, *Second;
207
208public:
209  PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
210    : First(_First), Second(_Second) {}
211  ~PPChainedCallbacks() {
212    delete Second;
213    delete First;
214  }
215
216  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
217                           SrcMgr::CharacteristicKind FileType,
218                           FileID PrevFID) {
219    First->FileChanged(Loc, Reason, FileType, PrevFID);
220    Second->FileChanged(Loc, Reason, FileType, PrevFID);
221  }
222
223  virtual void FileSkipped(const FileEntry &ParentFile,
224                           const Token &FilenameTok,
225                           SrcMgr::CharacteristicKind FileType) {
226    First->FileSkipped(ParentFile, FilenameTok, FileType);
227    Second->FileSkipped(ParentFile, FilenameTok, FileType);
228  }
229
230  virtual void InclusionDirective(SourceLocation HashLoc,
231                                  const Token &IncludeTok,
232                                  StringRef FileName,
233                                  bool IsAngled,
234                                  const FileEntry *File,
235                                  SourceLocation EndLoc,
236                                  StringRef SearchPath,
237                                  StringRef RelativePath) {
238    First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
239                              EndLoc, SearchPath, RelativePath);
240    Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
241                               EndLoc, SearchPath, RelativePath);
242  }
243
244  virtual void EndOfMainFile() {
245    First->EndOfMainFile();
246    Second->EndOfMainFile();
247  }
248
249  virtual void Ident(SourceLocation Loc, const std::string &str) {
250    First->Ident(Loc, str);
251    Second->Ident(Loc, str);
252  }
253
254  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
255                             const std::string &Str) {
256    First->PragmaComment(Loc, Kind, Str);
257    Second->PragmaComment(Loc, Kind, Str);
258  }
259
260  virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
261    First->PragmaMessage(Loc, Str);
262    Second->PragmaMessage(Loc, Str);
263  }
264
265  virtual void PragmaDiagnosticPush(SourceLocation Loc,
266                                    StringRef Namespace) {
267    First->PragmaDiagnosticPush(Loc, Namespace);
268    Second->PragmaDiagnosticPush(Loc, Namespace);
269  }
270
271  virtual void PragmaDiagnosticPop(SourceLocation Loc,
272                                    StringRef Namespace) {
273    First->PragmaDiagnosticPop(Loc, Namespace);
274    Second->PragmaDiagnosticPop(Loc, Namespace);
275  }
276
277  virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
278                                diag::Mapping mapping, StringRef Str) {
279    First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
280    Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
281  }
282
283  virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
284                            SourceRange Range) {
285    First->MacroExpands(MacroNameTok, MI, Range);
286    Second->MacroExpands(MacroNameTok, MI, Range);
287  }
288
289  virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
290    First->MacroDefined(MacroNameTok, MI);
291    Second->MacroDefined(MacroNameTok, MI);
292  }
293
294  virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
295    First->MacroUndefined(MacroNameTok, MI);
296    Second->MacroUndefined(MacroNameTok, MI);
297  }
298
299  virtual void SourceRangeSkipped(SourceRange Range) {
300    First->SourceRangeSkipped(Range);
301    Second->SourceRangeSkipped(Range);
302  }
303
304  /// If -- This hook is called whenever an #if is seen.
305  virtual void If(SourceRange Range) {
306    First->If(Range);
307    Second->If(Range);
308  }
309
310  /// Elif -- This hook is called whenever an #if is seen.
311  virtual void Elif(SourceRange Range) {
312    First->Elif(Range);
313    Second->Elif(Range);
314  }
315
316  /// Ifdef -- This hook is called whenever an #ifdef is seen.
317  virtual void Ifdef(const Token &MacroNameTok) {
318    First->Ifdef(MacroNameTok);
319    Second->Ifdef(MacroNameTok);
320  }
321
322  /// Ifndef -- This hook is called whenever an #ifndef is seen.
323  virtual void Ifndef(const Token &MacroNameTok) {
324    First->Ifndef(MacroNameTok);
325    Second->Ifndef(MacroNameTok);
326  }
327
328  /// Else -- This hook is called whenever an #else is seen.
329  virtual void Else() {
330    First->Else();
331    Second->Else();
332  }
333
334  /// Endif -- This hook is called whenever an #endif is seen.
335  virtual void Endif() {
336    First->Endif();
337    Second->Endif();
338  }
339};
340
341}  // end namespace clang
342
343#endif
344