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