Home | History | Annotate | Download | only in Lex
      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.
     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.
     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.
    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.
    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   ///
    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   ///
    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   ///
    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.
    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.
    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.
    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.
    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.
    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.
    179   virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
    180   }
    181 
    182   /// Defined - This hook is called whenever the 'defined' operator is seen.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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:
    239   PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
    240     : First(_First), Second(_Second) {}
    241   ~PPChainedCallbacks() {
    242     delete Second;
    243     delete First;
    244   }
    245 
    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 
    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 
    260   virtual bool FileNotFound(StringRef FileName,
    261                             SmallVectorImpl<char> &RecoveryPath) {
    262     return First->FileNotFound(FileName, RecoveryPath) ||
    263            Second->FileNotFound(FileName, RecoveryPath);
    264   }
    265 
    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 
    280   virtual void EndOfMainFile() {
    281     First->EndOfMainFile();
    282     Second->EndOfMainFile();
    283   }
    284 
    285   virtual void Ident(SourceLocation Loc, const std::string &str) {
    286     First->Ident(Loc, str);
    287     Second->Ident(Loc, str);
    288   }
    289 
    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 
    296   virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
    297     First->PragmaMessage(Loc, Str);
    298     Second->PragmaMessage(Loc, Str);
    299   }
    300 
    301   virtual void PragmaDiagnosticPush(SourceLocation Loc,
    302                                     StringRef Namespace) {
    303     First->PragmaDiagnosticPush(Loc, Namespace);
    304     Second->PragmaDiagnosticPush(Loc, Namespace);
    305   }
    306 
    307   virtual void PragmaDiagnosticPop(SourceLocation Loc,
    308                                     StringRef Namespace) {
    309     First->PragmaDiagnosticPop(Loc, Namespace);
    310     Second->PragmaDiagnosticPop(Loc, Namespace);
    311   }
    312 
    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 
    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 
    325   virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
    326     First->MacroDefined(MacroNameTok, MI);
    327     Second->MacroDefined(MacroNameTok, MI);
    328   }
    329 
    330   virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
    331     First->MacroUndefined(MacroNameTok, MI);
    332     Second->MacroUndefined(MacroNameTok, MI);
    333   }
    334 
    335   virtual void Defined(const Token &MacroNameTok) {
    336     First->Defined(MacroNameTok);
    337     Second->Defined(MacroNameTok);
    338   }
    339 
    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.
    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.
    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.
    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.
    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.
    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.
    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