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