clang API Documentation

PPCallbacks.h
Go to the documentation of this file.
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 /// \file
00011 /// \brief Defines the PPCallbacks interface.
00012 ///
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_LEX_PPCALLBACKS_H
00016 #define LLVM_CLANG_LEX_PPCALLBACKS_H
00017 
00018 #include "clang/Basic/DiagnosticIDs.h"
00019 #include "clang/Basic/SourceLocation.h"
00020 #include "clang/Lex/DirectoryLookup.h"
00021 #include "clang/Lex/ModuleLoader.h"
00022 #include "clang/Lex/Pragma.h"
00023 #include "llvm/ADT/StringRef.h"
00024 #include <string>
00025 
00026 namespace clang {
00027   class SourceLocation;
00028   class Token;
00029   class IdentifierInfo;
00030   class MacroDirective;
00031   class MacroArgs;
00032 
00033 /// \brief This interface provides a way to observe the actions of the
00034 /// preprocessor as it does its thing.
00035 ///
00036 /// Clients can define their hooks here to implement preprocessor level tools.
00037 class PPCallbacks {
00038 public:
00039   virtual ~PPCallbacks();
00040 
00041   enum FileChangeReason {
00042     EnterFile, ExitFile, SystemHeaderPragma, RenameFile
00043   };
00044 
00045   /// \brief Callback invoked whenever a source file is entered or exited.
00046   ///
00047   /// \param Loc Indicates the new location.
00048   /// \param PrevFID the file that was exited if \p Reason is ExitFile.
00049   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
00050                            SrcMgr::CharacteristicKind FileType,
00051                            FileID PrevFID = FileID()) {
00052   }
00053 
00054   /// \brief Callback invoked whenever a source file is skipped as the result
00055   /// of header guard optimization.
00056   ///
00057   /// \param ParentFile The file that \#included the skipped file.
00058   ///
00059   /// \param FilenameTok The token in ParentFile that indicates the
00060   /// skipped file.
00061   virtual void FileSkipped(const FileEntry &ParentFile,
00062                            const Token &FilenameTok,
00063                            SrcMgr::CharacteristicKind FileType) {
00064   }
00065 
00066   /// \brief Callback invoked whenever an inclusion directive results in a
00067   /// file-not-found error.
00068   ///
00069   /// \param FileName The name of the file being included, as written in the 
00070   /// source code.
00071   ///
00072   /// \param RecoveryPath If this client indicates that it can recover from 
00073   /// this missing file, the client should set this as an additional header
00074   /// search patch.
00075   ///
00076   /// \returns true to indicate that the preprocessor should attempt to recover
00077   /// by adding \p RecoveryPath as a header search path.
00078   virtual bool FileNotFound(StringRef FileName,
00079                             SmallVectorImpl<char> &RecoveryPath) {
00080     return false;
00081   }
00082 
00083   /// \brief Callback invoked whenever an inclusion directive of
00084   /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
00085   /// of whether the inclusion will actually result in an inclusion.
00086   ///
00087   /// \param HashLoc The location of the '#' that starts the inclusion 
00088   /// directive.
00089   ///
00090   /// \param IncludeTok The token that indicates the kind of inclusion 
00091   /// directive, e.g., 'include' or 'import'.
00092   ///
00093   /// \param FileName The name of the file being included, as written in the 
00094   /// source code.
00095   ///
00096   /// \param IsAngled Whether the file name was enclosed in angle brackets;
00097   /// otherwise, it was enclosed in quotes.
00098   ///
00099   /// \param FilenameRange The character range of the quotes or angle brackets
00100   /// for the written file name.
00101   ///
00102   /// \param File The actual file that may be included by this inclusion 
00103   /// directive.
00104   ///
00105   /// \param SearchPath Contains the search path which was used to find the file
00106   /// in the file system. If the file was found via an absolute include path,
00107   /// SearchPath will be empty. For framework includes, the SearchPath and
00108   /// RelativePath will be split up. For example, if an include of "Some/Some.h"
00109   /// is found via the framework path
00110   /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
00111   /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
00112   /// "Some.h".
00113   ///
00114   /// \param RelativePath The path relative to SearchPath, at which the include
00115   /// file was found. This is equal to FileName except for framework includes.
00116   ///
00117   /// \param Imported The module, whenever an inclusion directive was
00118   /// automatically turned into a module import or null otherwise.
00119   ///
00120   virtual void InclusionDirective(SourceLocation HashLoc,
00121                                   const Token &IncludeTok,
00122                                   StringRef FileName,
00123                                   bool IsAngled,
00124                                   CharSourceRange FilenameRange,
00125                                   const FileEntry *File,
00126                                   StringRef SearchPath,
00127                                   StringRef RelativePath,
00128                                   const Module *Imported) {
00129   }
00130 
00131   /// \brief Callback invoked whenever there was an explicit module-import
00132   /// syntax.
00133   ///
00134   /// \param ImportLoc The location of import directive token.
00135   ///
00136   /// \param Path The identifiers (and their locations) of the module
00137   /// "path", e.g., "std.vector" would be split into "std" and "vector".
00138   ///
00139   /// \param Imported The imported module; can be null if importing failed.
00140   ///
00141   virtual void moduleImport(SourceLocation ImportLoc,
00142                             ModuleIdPath Path,
00143                             const Module *Imported) {
00144   }
00145 
00146   /// \brief Callback invoked when the end of the main file is reached.
00147   ///
00148   /// No subsequent callbacks will be made.
00149   virtual void EndOfMainFile() {
00150   }
00151 
00152   /// \brief Callback invoked when a \#ident or \#sccs directive is read.
00153   /// \param Loc The location of the directive.
00154   /// \param str The text of the directive.
00155   ///
00156   virtual void Ident(SourceLocation Loc, const std::string &str) {
00157   }
00158 
00159   /// \brief Callback invoked when start reading any pragma directive.
00160   virtual void PragmaDirective(SourceLocation Loc,
00161                                PragmaIntroducerKind Introducer) {
00162   }
00163 
00164   /// \brief Callback invoked when a \#pragma comment directive is read.
00165   virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
00166                              const std::string &Str) {
00167   }
00168 
00169   /// \brief Callback invoked when a \#pragma detect_mismatch directive is
00170   /// read.
00171   virtual void PragmaDetectMismatch(SourceLocation Loc,
00172                                     const std::string &Name,
00173                                     const std::string &Value) {
00174   }
00175 
00176   /// \brief Callback invoked when a \#pragma clang __debug directive is read.
00177   /// \param Loc The location of the debug directive.
00178   /// \param DebugType The identifier following __debug.
00179   virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) {
00180   }
00181 
00182   /// \brief Determines the kind of \#pragma invoking a call to PragmaMessage.
00183   enum PragmaMessageKind {
00184     /// \brief \#pragma message has been invoked.
00185     PMK_Message,
00186 
00187     /// \brief \#pragma GCC warning has been invoked.
00188     PMK_Warning,
00189 
00190     /// \brief \#pragma GCC error has been invoked.
00191     PMK_Error
00192   };
00193 
00194   /// \brief Callback invoked when a \#pragma message directive is read.
00195   /// \param Loc The location of the message directive.
00196   /// \param Namespace The namespace of the message directive.
00197   /// \param Kind The type of the message directive.
00198   /// \param Str The text of the message directive.
00199   virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
00200                              PragmaMessageKind Kind, StringRef Str) {
00201   }
00202 
00203   /// \brief Callback invoked when a \#pragma gcc dianostic push directive
00204   /// is read.
00205   virtual void PragmaDiagnosticPush(SourceLocation Loc,
00206                                     StringRef Namespace) {
00207   }
00208 
00209   /// \brief Callback invoked when a \#pragma gcc dianostic pop directive
00210   /// is read.
00211   virtual void PragmaDiagnosticPop(SourceLocation Loc,
00212                                    StringRef Namespace) {
00213   }
00214 
00215   /// \brief Callback invoked when a \#pragma gcc dianostic directive is read.
00216   virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
00217                                 diag::Severity mapping, StringRef Str) {}
00218 
00219   /// \brief Called when an OpenCL extension is either disabled or
00220   /// enabled with a pragma.
00221   virtual void PragmaOpenCLExtension(SourceLocation NameLoc, 
00222                                      const IdentifierInfo *Name,
00223                                      SourceLocation StateLoc, unsigned State) {
00224   }
00225 
00226   /// \brief Callback invoked when a \#pragma warning directive is read.
00227   virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
00228                              ArrayRef<int> Ids) {
00229   }
00230 
00231   /// \brief Callback invoked when a \#pragma warning(push) directive is read.
00232   virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
00233   }
00234 
00235   /// \brief Callback invoked when a \#pragma warning(pop) directive is read.
00236   virtual void PragmaWarningPop(SourceLocation Loc) {
00237   }
00238 
00239   /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
00240   /// macro invocation is found.
00241   virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
00242                             SourceRange Range, const MacroArgs *Args) {
00243   }
00244 
00245   /// \brief Hook called whenever a macro definition is seen.
00246   virtual void MacroDefined(const Token &MacroNameTok,
00247                             const MacroDirective *MD) {
00248   }
00249 
00250   /// \brief Hook called whenever a macro \#undef is seen.
00251   ///
00252   /// MD is released immediately following this callback.
00253   virtual void MacroUndefined(const Token &MacroNameTok,
00254                               const MacroDirective *MD) {
00255   }
00256   
00257   /// \brief Hook called whenever the 'defined' operator is seen.
00258   /// \param MD The MacroDirective if the name was a macro, null otherwise.
00259   virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
00260                        SourceRange Range) {
00261   }
00262   
00263   /// \brief Hook called when a source range is skipped.
00264   /// \param Range The SourceRange that was skipped. The range begins at the
00265   /// \#if/\#else directive and ends after the \#endif/\#else directive.
00266   virtual void SourceRangeSkipped(SourceRange Range) {
00267   }
00268 
00269   enum ConditionValueKind {
00270     CVK_NotEvaluated, CVK_False, CVK_True
00271   };
00272 
00273   /// \brief Hook called whenever an \#if is seen.
00274   /// \param Loc the source location of the directive.
00275   /// \param ConditionRange The SourceRange of the expression being tested.
00276   /// \param ConditionValue The evaluated value of the condition.
00277   ///
00278   // FIXME: better to pass in a list (or tree!) of Tokens.
00279   virtual void If(SourceLocation Loc, SourceRange ConditionRange,
00280                   ConditionValueKind ConditionValue) {
00281   }
00282 
00283   /// \brief Hook called whenever an \#elif is seen.
00284   /// \param Loc the source location of the directive.
00285   /// \param ConditionRange The SourceRange of the expression being tested.
00286   /// \param ConditionValue The evaluated value of the condition.
00287   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
00288   // FIXME: better to pass in a list (or tree!) of Tokens.
00289   virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
00290                     ConditionValueKind ConditionValue, SourceLocation IfLoc) {
00291   }
00292 
00293   /// \brief Hook called whenever an \#ifdef is seen.
00294   /// \param Loc the source location of the directive.
00295   /// \param MacroNameTok Information on the token being tested.
00296   /// \param MD The MacroDirective if the name was a macro, null otherwise.
00297   virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
00298                      const MacroDirective *MD) {
00299   }
00300 
00301   /// \brief Hook called whenever an \#ifndef is seen.
00302   /// \param Loc the source location of the directive.
00303   /// \param MacroNameTok Information on the token being tested.
00304   /// \param MD The MacroDirective if the name was a macro, null otherwise.
00305   virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
00306                       const MacroDirective *MD) {
00307   }
00308 
00309   /// \brief Hook called whenever an \#else is seen.
00310   /// \param Loc the source location of the directive.
00311   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
00312   virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
00313   }
00314 
00315   /// \brief Hook called whenever an \#endif is seen.
00316   /// \param Loc the source location of the directive.
00317   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
00318   virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
00319   }
00320 };
00321 
00322 /// \brief Simple wrapper class for chaining callbacks.
00323 class PPChainedCallbacks : public PPCallbacks {
00324   virtual void anchor();
00325   std::unique_ptr<PPCallbacks> First, Second;
00326 
00327 public:
00328   PPChainedCallbacks(std::unique_ptr<PPCallbacks> _First,
00329                      std::unique_ptr<PPCallbacks> _Second)
00330     : First(std::move(_First)), Second(std::move(_Second)) {}
00331 
00332   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
00333                    SrcMgr::CharacteristicKind FileType,
00334                    FileID PrevFID) override {
00335     First->FileChanged(Loc, Reason, FileType, PrevFID);
00336     Second->FileChanged(Loc, Reason, FileType, PrevFID);
00337   }
00338 
00339   void FileSkipped(const FileEntry &ParentFile,
00340                    const Token &FilenameTok,
00341                    SrcMgr::CharacteristicKind FileType) override {
00342     First->FileSkipped(ParentFile, FilenameTok, FileType);
00343     Second->FileSkipped(ParentFile, FilenameTok, FileType);
00344   }
00345 
00346   bool FileNotFound(StringRef FileName,
00347                     SmallVectorImpl<char> &RecoveryPath) override {
00348     return First->FileNotFound(FileName, RecoveryPath) ||
00349            Second->FileNotFound(FileName, RecoveryPath);
00350   }
00351 
00352   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
00353                           StringRef FileName, bool IsAngled,
00354                           CharSourceRange FilenameRange, const FileEntry *File,
00355                           StringRef SearchPath, StringRef RelativePath,
00356                           const Module *Imported) override {
00357     First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
00358                               FilenameRange, File, SearchPath, RelativePath,
00359                               Imported);
00360     Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
00361                                FilenameRange, File, SearchPath, RelativePath,
00362                                Imported);
00363   }
00364 
00365   void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
00366                     const Module *Imported) override {
00367     First->moduleImport(ImportLoc, Path, Imported);
00368     Second->moduleImport(ImportLoc, Path, Imported);
00369   }
00370 
00371   void EndOfMainFile() override {
00372     First->EndOfMainFile();
00373     Second->EndOfMainFile();
00374   }
00375 
00376   void Ident(SourceLocation Loc, const std::string &str) override {
00377     First->Ident(Loc, str);
00378     Second->Ident(Loc, str);
00379   }
00380 
00381   void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
00382                      const std::string &Str) override {
00383     First->PragmaComment(Loc, Kind, Str);
00384     Second->PragmaComment(Loc, Kind, Str);
00385   }
00386 
00387   void PragmaDetectMismatch(SourceLocation Loc, const std::string &Name,
00388                             const std::string &Value) override {
00389     First->PragmaDetectMismatch(Loc, Name, Value);
00390     Second->PragmaDetectMismatch(Loc, Name, Value);
00391   }
00392 
00393   void PragmaMessage(SourceLocation Loc, StringRef Namespace,
00394                      PragmaMessageKind Kind, StringRef Str) override {
00395     First->PragmaMessage(Loc, Namespace, Kind, Str);
00396     Second->PragmaMessage(Loc, Namespace, Kind, Str);
00397   }
00398 
00399   void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override {
00400     First->PragmaDiagnosticPush(Loc, Namespace);
00401     Second->PragmaDiagnosticPush(Loc, Namespace);
00402   }
00403 
00404   void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override {
00405     First->PragmaDiagnosticPop(Loc, Namespace);
00406     Second->PragmaDiagnosticPop(Loc, Namespace);
00407   }
00408 
00409   void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
00410                         diag::Severity mapping, StringRef Str) override {
00411     First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
00412     Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
00413   }
00414 
00415   void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name,
00416                              SourceLocation StateLoc, unsigned State) override {
00417     First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
00418     Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
00419   }
00420 
00421   void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
00422                      ArrayRef<int> Ids) override {
00423     First->PragmaWarning(Loc, WarningSpec, Ids);
00424     Second->PragmaWarning(Loc, WarningSpec, Ids);
00425   }
00426 
00427   void PragmaWarningPush(SourceLocation Loc, int Level) override {
00428     First->PragmaWarningPush(Loc, Level);
00429     Second->PragmaWarningPush(Loc, Level);
00430   }
00431 
00432   void PragmaWarningPop(SourceLocation Loc) override {
00433     First->PragmaWarningPop(Loc);
00434     Second->PragmaWarningPop(Loc);
00435   }
00436 
00437   void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
00438                     SourceRange Range, const MacroArgs *Args) override {
00439     First->MacroExpands(MacroNameTok, MD, Range, Args);
00440     Second->MacroExpands(MacroNameTok, MD, Range, Args);
00441   }
00442 
00443   void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override {
00444     First->MacroDefined(MacroNameTok, MD);
00445     Second->MacroDefined(MacroNameTok, MD);
00446   }
00447 
00448   void MacroUndefined(const Token &MacroNameTok,
00449                       const MacroDirective *MD) override {
00450     First->MacroUndefined(MacroNameTok, MD);
00451     Second->MacroUndefined(MacroNameTok, MD);
00452   }
00453 
00454   void Defined(const Token &MacroNameTok, const MacroDirective *MD,
00455                SourceRange Range) override {
00456     First->Defined(MacroNameTok, MD, Range);
00457     Second->Defined(MacroNameTok, MD, Range);
00458   }
00459 
00460   void SourceRangeSkipped(SourceRange Range) override {
00461     First->SourceRangeSkipped(Range);
00462     Second->SourceRangeSkipped(Range);
00463   }
00464 
00465   /// \brief Hook called whenever an \#if is seen.
00466   void If(SourceLocation Loc, SourceRange ConditionRange,
00467           ConditionValueKind ConditionValue) override {
00468     First->If(Loc, ConditionRange, ConditionValue);
00469     Second->If(Loc, ConditionRange, ConditionValue);
00470   }
00471 
00472   /// \brief Hook called whenever an \#elif is seen.
00473   void Elif(SourceLocation Loc, SourceRange ConditionRange,
00474             ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
00475     First->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
00476     Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
00477   }
00478 
00479   /// \brief Hook called whenever an \#ifdef is seen.
00480   void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
00481              const MacroDirective *MD) override {
00482     First->Ifdef(Loc, MacroNameTok, MD);
00483     Second->Ifdef(Loc, MacroNameTok, MD);
00484   }
00485 
00486   /// \brief Hook called whenever an \#ifndef is seen.
00487   void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
00488               const MacroDirective *MD) override {
00489     First->Ifndef(Loc, MacroNameTok, MD);
00490     Second->Ifndef(Loc, MacroNameTok, MD);
00491   }
00492 
00493   /// \brief Hook called whenever an \#else is seen.
00494   void Else(SourceLocation Loc, SourceLocation IfLoc) override {
00495     First->Else(Loc, IfLoc);
00496     Second->Else(Loc, IfLoc);
00497   }
00498 
00499   /// \brief Hook called whenever an \#endif is seen.
00500   void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
00501     First->Endif(Loc, IfLoc);
00502     Second->Endif(Loc, IfLoc);
00503   }
00504 };
00505 
00506 }  // end namespace clang
00507 
00508 #endif