PPCallbacks.h revision 7412494982c8b50c90961302c3a718633b2c3ab7
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 "llvm/ADT/StringRef.h"
20#include <string>
21
22namespace clang {
23  class SourceLocation;
24  class Token;
25  class IdentifierInfo;
26  class MacroInfo;
27
28/// PPCallbacks - This interface provides a way to observe the actions of the
29/// preprocessor as it does its thing.  Clients can define their hooks here to
30/// implement preprocessor level tools.
31class PPCallbacks {
32public:
33  virtual ~PPCallbacks();
34
35  enum FileChangeReason {
36    EnterFile, ExitFile, SystemHeaderPragma, RenameFile
37  };
38
39  /// FileChanged - This callback is invoked whenever a source file is
40  /// entered or exited.  The SourceLocation indicates the new location, and
41  /// EnteringFile indicates whether this is because we are entering a new
42  /// #include'd file (when true) or whether we're exiting one because we ran
43  /// off the end (when false).
44  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
45                           SrcMgr::CharacteristicKind FileType) {
46  }
47
48  /// FileSkipped - This callback is invoked whenever a source file is
49  /// skipped as the result of header guard optimization.  ParentFile
50  /// is the file that #includes the skipped file.  FilenameTok is the
51  /// token in ParentFile that indicates the skipped file.
52  virtual void FileSkipped(const FileEntry &ParentFile,
53                           const Token &FilenameTok,
54                           SrcMgr::CharacteristicKind FileType) {
55  }
56
57  /// \brief This callback is invoked whenever an inclusion directive of
58  /// any kind (\c #include, \c #import, etc.) has been processed, regardless
59  /// of whether the inclusion will actually result in an inclusion.
60  ///
61  /// \param HashLoc The location of the '#' that starts the inclusion
62  /// directive.
63  ///
64  /// \param IncludeTok The token that indicates the kind of inclusion
65  /// directive, e.g., 'include' or 'import'.
66  ///
67  /// \param FileName The name of the file being included, as written in the
68  /// source code.
69  ///
70  /// \param IsAngled Whether the file name was enclosed in angle brackets;
71  /// otherwise, it was enclosed in quotes.
72  ///
73  /// \param File The actual file that may be included by this inclusion
74  /// directive.
75  ///
76  /// \param EndLoc The location of the last token within the inclusion
77  /// directive.
78  ///
79  /// \param SearchPath Contains the search path which was used to find the file
80  /// in the file system. If the file was found via an absolute include path,
81  /// SearchPath will be empty. For framework includes, the SearchPath and
82  /// RelativePath will be split up. For example, if an include of "Some/Some.h"
83  /// is found via the framework path
84  /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
85  /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
86  /// "Some.h".
87  ///
88  /// \param RelativePath The path relative to SearchPath, at which the include
89  /// file was found. This is equal to FileName except for framework includes.
90  virtual void InclusionDirective(SourceLocation HashLoc,
91                                  const Token &IncludeTok,
92                                  llvm::StringRef FileName,
93                                  bool IsAngled,
94                                  const FileEntry *File,
95                                  SourceLocation EndLoc,
96                                  llvm::StringRef SearchPath,
97                                  llvm::StringRef RelativePath) {
98  }
99
100  /// EndOfMainFile - This callback is invoked when the end of the main file is
101  /// reach, no subsequent callbacks will be made.
102  virtual void EndOfMainFile() {
103  }
104
105  /// Ident - This callback is invoked when a #ident or #sccs directive is read.
106  /// \param Loc The location of the directive.
107  /// \param str The text of the directive.
108  ///
109  virtual void Ident(SourceLocation Loc, const std::string &str) {
110  }
111
112  /// PragmaComment - This callback is invoked when a #pragma comment directive
113  /// is read.
114  ///
115  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
116                             const std::string &Str) {
117  }
118
119  /// PragmaMessage - This callback is invoked when a #pragma message directive
120  /// is read.
121  /// \param Loc The location of the message directive.
122  /// \param str The text of the message directive.
123  ///
124  virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) {
125  }
126
127  /// MacroExpands - This is called by
128  /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
129  /// found.
130  virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) {
131  }
132
133  /// MacroDefined - This hook is called whenever a macro definition is seen.
134  virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
135  }
136
137  /// MacroUndefined - This hook is called whenever a macro #undef is seen.
138  /// MI is released immediately following this callback.
139  virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
140  }
141
142  /// If -- This hook is called whenever an #if is seen.
143  /// \param Range The SourceRange of the expression being tested.
144  // FIXME: better to pass in a list (or tree!) of Tokens.
145  virtual void If(SourceRange Range) {
146  }
147
148  /// Elif -- This hook is called whenever an #elif is seen.
149  /// \param Range The SourceRange of the expression being tested.
150  // FIXME: better to pass in a list (or tree!) of Tokens.
151  virtual void Elif(SourceRange Range) {
152  }
153
154  /// Ifdef -- This hook is called whenever an #ifdef is seen.
155  /// \param Loc The location of the token being tested.
156  /// \param II Information on the token being tested.
157  virtual void Ifdef(const Token &MacroNameTok) {
158  }
159
160  /// Ifndef -- This hook is called whenever an #ifndef is seen.
161  /// \param Loc The location of the token being tested.
162  /// \param II Information on the token being tested.
163  virtual void Ifndef(const Token &MacroNameTok) {
164  }
165
166  /// Else -- This hook is called whenever an #else is seen.
167  virtual void Else() {
168  }
169
170  /// Endif -- This hook is called whenever an #endif is seen.
171  virtual void Endif() {
172  }
173};
174
175/// PPChainedCallbacks - Simple wrapper class for chaining callbacks.
176class PPChainedCallbacks : public PPCallbacks {
177  PPCallbacks *First, *Second;
178
179public:
180  PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
181    : First(_First), Second(_Second) {}
182  ~PPChainedCallbacks() {
183    delete Second;
184    delete First;
185  }
186
187  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
188                           SrcMgr::CharacteristicKind FileType) {
189    First->FileChanged(Loc, Reason, FileType);
190    Second->FileChanged(Loc, Reason, FileType);
191  }
192
193  virtual void FileSkipped(const FileEntry &ParentFile,
194                           const Token &FilenameTok,
195                           SrcMgr::CharacteristicKind FileType) {
196    First->FileSkipped(ParentFile, FilenameTok, FileType);
197    Second->FileSkipped(ParentFile, FilenameTok, FileType);
198  }
199
200  virtual void InclusionDirective(SourceLocation HashLoc,
201                                  const Token &IncludeTok,
202                                  llvm::StringRef FileName,
203                                  bool IsAngled,
204                                  const FileEntry *File,
205                                  SourceLocation EndLoc,
206                                  llvm::StringRef SearchPath,
207                                  llvm::StringRef RelativePath) {
208    First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
209                              EndLoc, SearchPath, RelativePath);
210    Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
211                               EndLoc, SearchPath, RelativePath);
212  }
213
214  virtual void EndOfMainFile() {
215    First->EndOfMainFile();
216    Second->EndOfMainFile();
217  }
218
219  virtual void Ident(SourceLocation Loc, const std::string &str) {
220    First->Ident(Loc, str);
221    Second->Ident(Loc, str);
222  }
223
224  virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
225                             const std::string &Str) {
226    First->PragmaComment(Loc, Kind, Str);
227    Second->PragmaComment(Loc, Kind, Str);
228  }
229
230  virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) {
231    First->PragmaMessage(Loc, Str);
232    Second->PragmaMessage(Loc, Str);
233  }
234
235  virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) {
236    First->MacroExpands(MacroNameTok, MI);
237    Second->MacroExpands(MacroNameTok, MI);
238  }
239
240  virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
241    First->MacroDefined(MacroNameTok, MI);
242    Second->MacroDefined(MacroNameTok, MI);
243  }
244
245  virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
246    First->MacroUndefined(MacroNameTok, MI);
247    Second->MacroUndefined(MacroNameTok, MI);
248  }
249
250  /// If -- This hook is called whenever an #if is seen.
251  virtual void If(SourceRange Range) {
252    First->If(Range);
253    Second->If(Range);
254  }
255
256  /// Elif -- This hook is called whenever an #if is seen.
257  virtual void Elif(SourceRange Range) {
258    First->Elif(Range);
259    Second->Elif(Range);
260  }
261
262  /// Ifdef -- This hook is called whenever an #ifdef is seen.
263  virtual void Ifdef(const Token &MacroNameTok) {
264    First->Ifdef(MacroNameTok);
265    Second->Ifdef(MacroNameTok);
266  }
267
268  /// Ifndef -- This hook is called whenever an #ifndef is seen.
269  virtual void Ifndef(const Token &MacroNameTok) {
270    First->Ifndef(MacroNameTok);
271    Second->Ifndef(MacroNameTok);
272  }
273
274  /// Else -- This hook is called whenever an #else is seen.
275  virtual void Else() {
276    First->Else();
277    Second->Else();
278  }
279
280  /// Endif -- This hook is called whenever an #endif is seen.
281  virtual void Endif() {
282    First->Endif();
283    Second->Endif();
284  }
285};
286
287}  // end namespace clang
288
289#endif
290