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