clang API Documentation
00001 //===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the PPCallbacks interface. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CLANG_LEX_PPCALLBACKS_H 00015 #define LLVM_CLANG_LEX_PPCALLBACKS_H 00016 00017 #include "clang/Lex/DirectoryLookup.h" 00018 #include "clang/Basic/SourceLocation.h" 00019 #include "clang/Basic/DiagnosticIDs.h" 00020 #include "llvm/ADT/StringRef.h" 00021 #include <string> 00022 00023 namespace clang { 00024 class SourceLocation; 00025 class Token; 00026 class IdentifierInfo; 00027 class MacroInfo; 00028 00029 /// PPCallbacks - This interface provides a way to observe the actions of the 00030 /// preprocessor as it does its thing. Clients can define their hooks here to 00031 /// implement preprocessor level tools. 00032 class PPCallbacks { 00033 public: 00034 virtual ~PPCallbacks(); 00035 00036 enum FileChangeReason { 00037 EnterFile, ExitFile, SystemHeaderPragma, RenameFile 00038 }; 00039 00040 /// FileChanged - This callback is invoked whenever a source file is 00041 /// entered or exited. The SourceLocation indicates the new location, and 00042 /// EnteringFile indicates whether this is because we are entering a new 00043 /// #include'd file (when true) or whether we're exiting one because we ran 00044 /// off the end (when false). 00045 /// 00046 /// \param PrevFID the file that was exited if \arg Reason is ExitFile. 00047 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 00048 SrcMgr::CharacteristicKind FileType, 00049 FileID PrevFID = FileID()) { 00050 } 00051 00052 /// FileSkipped - This callback is invoked whenever a source file is 00053 /// skipped as the result of header guard optimization. ParentFile 00054 /// is the file that #includes the skipped file. FilenameTok is the 00055 /// token in ParentFile that indicates the skipped file. 00056 virtual void FileSkipped(const FileEntry &ParentFile, 00057 const Token &FilenameTok, 00058 SrcMgr::CharacteristicKind FileType) { 00059 } 00060 00061 /// FileNotFound - This callback is invoked whenever an inclusion directive 00062 /// results in a file-not-found error. 00063 /// 00064 /// \param FileName The name of the file being included, as written in the 00065 /// source code. 00066 /// 00067 /// \param RecoveryPath If this client indicates that it can recover from 00068 /// this missing file, the client should set this as an additional header 00069 /// search patch. 00070 /// 00071 /// \returns true to indicate that the preprocessor should attempt to recover 00072 /// by adding \p RecoveryPath as a header search path. 00073 virtual bool FileNotFound(StringRef FileName, 00074 SmallVectorImpl<char> &RecoveryPath) { 00075 return false; 00076 } 00077 00078 /// \brief This callback is invoked whenever an inclusion directive of 00079 /// any kind (\c #include, \c #import, etc.) has been processed, regardless 00080 /// of whether the inclusion will actually result in an inclusion. 00081 /// 00082 /// \param HashLoc The location of the '#' that starts the inclusion 00083 /// directive. 00084 /// 00085 /// \param IncludeTok The token that indicates the kind of inclusion 00086 /// directive, e.g., 'include' or 'import'. 00087 /// 00088 /// \param FileName The name of the file being included, as written in the 00089 /// source code. 00090 /// 00091 /// \param IsAngled Whether the file name was enclosed in angle brackets; 00092 /// otherwise, it was enclosed in quotes. 00093 /// 00094 /// \param File The actual file that may be included by this inclusion 00095 /// directive. 00096 /// 00097 /// \param EndLoc The location of the last token within the inclusion 00098 /// directive. 00099 /// 00100 /// \param SearchPath Contains the search path which was used to find the file 00101 /// in the file system. If the file was found via an absolute include path, 00102 /// SearchPath will be empty. For framework includes, the SearchPath and 00103 /// RelativePath will be split up. For example, if an include of "Some/Some.h" 00104 /// is found via the framework path 00105 /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be 00106 /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be 00107 /// "Some.h". 00108 /// 00109 /// \param RelativePath The path relative to SearchPath, at which the include 00110 /// file was found. This is equal to FileName except for framework includes. 00111 virtual void InclusionDirective(SourceLocation HashLoc, 00112 const Token &IncludeTok, 00113 StringRef FileName, 00114 bool IsAngled, 00115 const FileEntry *File, 00116 SourceLocation EndLoc, 00117 StringRef SearchPath, 00118 StringRef RelativePath) { 00119 } 00120 00121 /// EndOfMainFile - This callback is invoked when the end of the main file is 00122 /// reach, no subsequent callbacks will be made. 00123 virtual void EndOfMainFile() { 00124 } 00125 00126 /// Ident - This callback is invoked when a #ident or #sccs directive is read. 00127 /// \param Loc The location of the directive. 00128 /// \param str The text of the directive. 00129 /// 00130 virtual void Ident(SourceLocation Loc, const std::string &str) { 00131 } 00132 00133 /// PragmaComment - This callback is invoked when a #pragma comment directive 00134 /// is read. 00135 /// 00136 virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 00137 const std::string &Str) { 00138 } 00139 00140 /// PragmaMessage - This callback is invoked when a #pragma message directive 00141 /// is read. 00142 /// \param Loc The location of the message directive. 00143 /// \param str The text of the message directive. 00144 /// 00145 virtual void PragmaMessage(SourceLocation Loc, StringRef Str) { 00146 } 00147 00148 /// PragmaDiagnosticPush - This callback is invoked when a 00149 /// #pragma gcc dianostic push directive is read. 00150 virtual void PragmaDiagnosticPush(SourceLocation Loc, 00151 StringRef Namespace) { 00152 } 00153 00154 /// PragmaDiagnosticPop - This callback is invoked when a 00155 /// #pragma gcc dianostic pop directive is read. 00156 virtual void PragmaDiagnosticPop(SourceLocation Loc, 00157 StringRef Namespace) { 00158 } 00159 00160 /// PragmaDiagnostic - This callback is invoked when a 00161 /// #pragma gcc dianostic directive is read. 00162 virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 00163 diag::Mapping mapping, StringRef Str) { 00164 } 00165 00166 /// MacroExpands - This is called by 00167 /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is 00168 /// found. 00169 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, 00170 SourceRange Range) { 00171 } 00172 00173 /// MacroDefined - This hook is called whenever a macro definition is seen. 00174 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { 00175 } 00176 00177 /// MacroUndefined - This hook is called whenever a macro #undef is seen. 00178 /// MI is released immediately following this callback. 00179 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { 00180 } 00181 00182 /// Defined - This hook is called whenever the 'defined' operator is seen. 00183 virtual void Defined(const Token &MacroNameTok) { 00184 } 00185 00186 /// SourceRangeSkipped - This hook is called when a source range is skipped. 00187 /// \param Range The SourceRange that was skipped. The range begins at the 00188 /// #if/#else directive and ends after the #endif/#else directive. 00189 virtual void SourceRangeSkipped(SourceRange Range) { 00190 } 00191 00192 /// If -- This hook is called whenever an #if is seen. 00193 /// \param Loc the source location of the directive. 00194 /// \param ConditionRange The SourceRange of the expression being tested. 00195 // FIXME: better to pass in a list (or tree!) of Tokens. 00196 virtual void If(SourceLocation Loc, SourceRange ConditionRange) { 00197 } 00198 00199 /// Elif -- This hook is called whenever an #elif is seen. 00200 /// \param Loc the source location of the directive. 00201 /// \param ConditionRange The SourceRange of the expression being tested. 00202 /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. 00203 // FIXME: better to pass in a list (or tree!) of Tokens. 00204 virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, 00205 SourceLocation IfLoc) { 00206 } 00207 00208 /// Ifdef -- This hook is called whenever an #ifdef is seen. 00209 /// \param Loc the source location of the directive. 00210 /// \param II Information on the token being tested. 00211 virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { 00212 } 00213 00214 /// Ifndef -- This hook is called whenever an #ifndef is seen. 00215 /// \param Loc the source location of the directive. 00216 /// \param II Information on the token being tested. 00217 virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { 00218 } 00219 00220 /// Else -- This hook is called whenever an #else is seen. 00221 /// \param Loc the source location of the directive. 00222 /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. 00223 virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { 00224 } 00225 00226 /// Endif -- This hook is called whenever an #endif is seen. 00227 /// \param Loc the source location of the directive. 00228 /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. 00229 virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { 00230 } 00231 }; 00232 00233 /// PPChainedCallbacks - Simple wrapper class for chaining callbacks. 00234 class PPChainedCallbacks : public PPCallbacks { 00235 virtual void anchor(); 00236 PPCallbacks *First, *Second; 00237 00238 public: 00239 PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second) 00240 : First(_First), Second(_Second) {} 00241 ~PPChainedCallbacks() { 00242 delete Second; 00243 delete First; 00244 } 00245 00246 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 00247 SrcMgr::CharacteristicKind FileType, 00248 FileID PrevFID) { 00249 First->FileChanged(Loc, Reason, FileType, PrevFID); 00250 Second->FileChanged(Loc, Reason, FileType, PrevFID); 00251 } 00252 00253 virtual void FileSkipped(const FileEntry &ParentFile, 00254 const Token &FilenameTok, 00255 SrcMgr::CharacteristicKind FileType) { 00256 First->FileSkipped(ParentFile, FilenameTok, FileType); 00257 Second->FileSkipped(ParentFile, FilenameTok, FileType); 00258 } 00259 00260 virtual bool FileNotFound(StringRef FileName, 00261 SmallVectorImpl<char> &RecoveryPath) { 00262 return First->FileNotFound(FileName, RecoveryPath) || 00263 Second->FileNotFound(FileName, RecoveryPath); 00264 } 00265 00266 virtual void InclusionDirective(SourceLocation HashLoc, 00267 const Token &IncludeTok, 00268 StringRef FileName, 00269 bool IsAngled, 00270 const FileEntry *File, 00271 SourceLocation EndLoc, 00272 StringRef SearchPath, 00273 StringRef RelativePath) { 00274 First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, 00275 EndLoc, SearchPath, RelativePath); 00276 Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, 00277 EndLoc, SearchPath, RelativePath); 00278 } 00279 00280 virtual void EndOfMainFile() { 00281 First->EndOfMainFile(); 00282 Second->EndOfMainFile(); 00283 } 00284 00285 virtual void Ident(SourceLocation Loc, const std::string &str) { 00286 First->Ident(Loc, str); 00287 Second->Ident(Loc, str); 00288 } 00289 00290 virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 00291 const std::string &Str) { 00292 First->PragmaComment(Loc, Kind, Str); 00293 Second->PragmaComment(Loc, Kind, Str); 00294 } 00295 00296 virtual void PragmaMessage(SourceLocation Loc, StringRef Str) { 00297 First->PragmaMessage(Loc, Str); 00298 Second->PragmaMessage(Loc, Str); 00299 } 00300 00301 virtual void PragmaDiagnosticPush(SourceLocation Loc, 00302 StringRef Namespace) { 00303 First->PragmaDiagnosticPush(Loc, Namespace); 00304 Second->PragmaDiagnosticPush(Loc, Namespace); 00305 } 00306 00307 virtual void PragmaDiagnosticPop(SourceLocation Loc, 00308 StringRef Namespace) { 00309 First->PragmaDiagnosticPop(Loc, Namespace); 00310 Second->PragmaDiagnosticPop(Loc, Namespace); 00311 } 00312 00313 virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 00314 diag::Mapping mapping, StringRef Str) { 00315 First->PragmaDiagnostic(Loc, Namespace, mapping, Str); 00316 Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); 00317 } 00318 00319 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, 00320 SourceRange Range) { 00321 First->MacroExpands(MacroNameTok, MI, Range); 00322 Second->MacroExpands(MacroNameTok, MI, Range); 00323 } 00324 00325 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { 00326 First->MacroDefined(MacroNameTok, MI); 00327 Second->MacroDefined(MacroNameTok, MI); 00328 } 00329 00330 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { 00331 First->MacroUndefined(MacroNameTok, MI); 00332 Second->MacroUndefined(MacroNameTok, MI); 00333 } 00334 00335 virtual void Defined(const Token &MacroNameTok) { 00336 First->Defined(MacroNameTok); 00337 Second->Defined(MacroNameTok); 00338 } 00339 00340 virtual void SourceRangeSkipped(SourceRange Range) { 00341 First->SourceRangeSkipped(Range); 00342 Second->SourceRangeSkipped(Range); 00343 } 00344 00345 /// If -- This hook is called whenever an #if is seen. 00346 virtual void If(SourceLocation Loc, SourceRange ConditionRange) { 00347 First->If(Loc, ConditionRange); 00348 Second->If(Loc, ConditionRange); 00349 } 00350 00351 /// Elif -- This hook is called whenever an #if is seen. 00352 virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, 00353 SourceLocation IfLoc) { 00354 First->Elif(Loc, ConditionRange, IfLoc); 00355 Second->Elif(Loc, ConditionRange, IfLoc); 00356 } 00357 00358 /// Ifdef -- This hook is called whenever an #ifdef is seen. 00359 virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { 00360 First->Ifdef(Loc, MacroNameTok); 00361 Second->Ifdef(Loc, MacroNameTok); 00362 } 00363 00364 /// Ifndef -- This hook is called whenever an #ifndef is seen. 00365 virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { 00366 First->Ifndef(Loc, MacroNameTok); 00367 Second->Ifndef(Loc, MacroNameTok); 00368 } 00369 00370 /// Else -- This hook is called whenever an #else is seen. 00371 virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { 00372 First->Else(Loc, IfLoc); 00373 Second->Else(Loc, IfLoc); 00374 } 00375 00376 /// Endif -- This hook is called whenever an #endif is seen. 00377 virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { 00378 First->Endif(Loc, IfLoc); 00379 Second->Endif(Loc, IfLoc); 00380 } 00381 }; 00382 00383 } // end namespace clang 00384 00385 #endif