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   /// \brief This callback is invoked whenever an inclusion directive of
     62   /// any kind (\c #include, \c #import, etc.) has been processed, regardless
     63   /// of whether the inclusion will actually result in an inclusion.
     64   ///
     65   /// \param HashLoc The location of the '#' that starts the inclusion
     66   /// directive.
     67   ///
     68   /// \param IncludeTok The token that indicates the kind of inclusion
     69   /// directive, e.g., 'include' or 'import'.
     70   ///
     71   /// \param FileName The name of the file being included, as written in the
     72   /// source code.
     73   ///
     74   /// \param IsAngled Whether the file name was enclosed in angle brackets;
     75   /// otherwise, it was enclosed in quotes.
     76   ///
     77   /// \param File The actual file that may be included by this inclusion
     78   /// directive.
     79   ///
     80   /// \param EndLoc The location of the last token within the inclusion
     81   /// directive.
     82   ///
     83   /// \param SearchPath Contains the search path which was used to find the file
     84   /// in the file system. If the file was found via an absolute include path,
     85   /// SearchPath will be empty. For framework includes, the SearchPath and
     86   /// RelativePath will be split up. For example, if an include of "Some/Some.h"
     87   /// is found via the framework path
     88   /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
     89   /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
     90   /// "Some.h".
     91   ///
     92   /// \param RelativePath The path relative to SearchPath, at which the include
     93   /// file was found. This is equal to FileName except for framework includes.
     94   virtual void InclusionDirective(SourceLocation HashLoc,
     95                                   const Token &IncludeTok,
     96                                   StringRef FileName,
     97                                   bool IsAngled,
     98                                   const FileEntry *File,
     99                                   SourceLocation EndLoc,
    100                                   StringRef SearchPath,
    101                                   StringRef RelativePath) {
    102   }
    103 
    104   /// EndOfMainFile - This callback is invoked when the end of the main file is
    105   /// reach, no subsequent callbacks will be made.
    106   virtual void EndOfMainFile() {
    107   }
    108 
    109   /// Ident - This callback is invoked when a #ident or #sccs directive is read.
    110   /// \param Loc The location of the directive.
    111   /// \param str The text of the directive.
    112   ///
    113   virtual void Ident(SourceLocation Loc, const std::string &str) {
    114   }
    115 
    116   /// PragmaComment - This callback is invoked when a #pragma comment directive
    117   /// is read.
    118   ///
    119   virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
    120                              const std::string &Str) {
    121   }
    122 
    123   /// PragmaMessage - This callback is invoked when a #pragma message directive
    124   /// is read.
    125   /// \param Loc The location of the message directive.
    126   /// \param str The text of the message directive.
    127   ///
    128   virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
    129   }
    130 
    131   /// PragmaDiagnosticPush - This callback is invoked when a
    132   /// #pragma gcc dianostic push directive is read.
    133   virtual void PragmaDiagnosticPush(SourceLocation Loc,
    134                                     StringRef Namespace) {
    135   }
    136 
    137   /// PragmaDiagnosticPop - This callback is invoked when a
    138   /// #pragma gcc dianostic pop directive is read.
    139   virtual void PragmaDiagnosticPop(SourceLocation Loc,
    140                                    StringRef Namespace) {
    141   }
    142 
    143   /// PragmaDiagnostic - This callback is invoked when a
    144   /// #pragma gcc dianostic directive is read.
    145   virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
    146                                 diag::Mapping mapping, StringRef Str) {
    147   }
    148 
    149   /// MacroExpands - This is called by
    150   /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
    151   /// found.
    152   virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
    153                             SourceRange Range) {
    154   }
    155 
    156   /// MacroDefined - This hook is called whenever a macro definition is seen.
    157   virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
    158   }
    159 
    160   /// MacroUndefined - This hook is called whenever a macro #undef is seen.
    161   /// MI is released immediately following this callback.
    162   virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
    163   }
    164 
    165   /// Defined - This hook is called whenever the 'defined' operator is seen.
    166   virtual void Defined(const Token &MacroNameTok) {
    167   }
    168 
    169   /// SourceRangeSkipped - This hook is called when a source range is skipped.
    170   /// \param Range The SourceRange that was skipped. The range begins at the
    171   /// #if/#else directive and ends after the #endif/#else directive.
    172   virtual void SourceRangeSkipped(SourceRange Range) {
    173   }
    174 
    175   /// If -- This hook is called whenever an #if is seen.
    176   /// \param Range The SourceRange of the expression being tested.
    177   // FIXME: better to pass in a list (or tree!) of Tokens.
    178   virtual void If(SourceRange Range) {
    179   }
    180 
    181   /// Elif -- This hook is called whenever an #elif is seen.
    182   /// \param Range The SourceRange of the expression being tested.
    183   // FIXME: better to pass in a list (or tree!) of Tokens.
    184   virtual void Elif(SourceRange Range) {
    185   }
    186 
    187   /// Ifdef -- This hook is called whenever an #ifdef is seen.
    188   /// \param Loc The location of the token being tested.
    189   /// \param II Information on the token being tested.
    190   virtual void Ifdef(const Token &MacroNameTok) {
    191   }
    192 
    193   /// Ifndef -- This hook is called whenever an #ifndef is seen.
    194   /// \param Loc The location of the token being tested.
    195   /// \param II Information on the token being tested.
    196   virtual void Ifndef(const Token &MacroNameTok) {
    197   }
    198 
    199   /// Else -- This hook is called whenever an #else is seen.
    200   virtual void Else() {
    201   }
    202 
    203   /// Endif -- This hook is called whenever an #endif is seen.
    204   virtual void Endif() {
    205   }
    206 };
    207 
    208 /// PPChainedCallbacks - Simple wrapper class for chaining callbacks.
    209 class PPChainedCallbacks : public PPCallbacks {
    210   PPCallbacks *First, *Second;
    211 
    212 public:
    213   PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
    214     : First(_First), Second(_Second) {}
    215   ~PPChainedCallbacks() {
    216     delete Second;
    217     delete First;
    218   }
    219 
    220   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
    221                            SrcMgr::CharacteristicKind FileType,
    222                            FileID PrevFID) {
    223     First->FileChanged(Loc, Reason, FileType, PrevFID);
    224     Second->FileChanged(Loc, Reason, FileType, PrevFID);
    225   }
    226 
    227   virtual void FileSkipped(const FileEntry &ParentFile,
    228                            const Token &FilenameTok,
    229                            SrcMgr::CharacteristicKind FileType) {
    230     First->FileSkipped(ParentFile, FilenameTok, FileType);
    231     Second->FileSkipped(ParentFile, FilenameTok, FileType);
    232   }
    233 
    234   virtual void InclusionDirective(SourceLocation HashLoc,
    235                                   const Token &IncludeTok,
    236                                   StringRef FileName,
    237                                   bool IsAngled,
    238                                   const FileEntry *File,
    239                                   SourceLocation EndLoc,
    240                                   StringRef SearchPath,
    241                                   StringRef RelativePath) {
    242     First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
    243                               EndLoc, SearchPath, RelativePath);
    244     Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
    245                                EndLoc, SearchPath, RelativePath);
    246   }
    247 
    248   virtual void EndOfMainFile() {
    249     First->EndOfMainFile();
    250     Second->EndOfMainFile();
    251   }
    252 
    253   virtual void Ident(SourceLocation Loc, const std::string &str) {
    254     First->Ident(Loc, str);
    255     Second->Ident(Loc, str);
    256   }
    257 
    258   virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
    259                              const std::string &Str) {
    260     First->PragmaComment(Loc, Kind, Str);
    261     Second->PragmaComment(Loc, Kind, Str);
    262   }
    263 
    264   virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
    265     First->PragmaMessage(Loc, Str);
    266     Second->PragmaMessage(Loc, Str);
    267   }
    268 
    269   virtual void PragmaDiagnosticPush(SourceLocation Loc,
    270                                     StringRef Namespace) {
    271     First->PragmaDiagnosticPush(Loc, Namespace);
    272     Second->PragmaDiagnosticPush(Loc, Namespace);
    273   }
    274 
    275   virtual void PragmaDiagnosticPop(SourceLocation Loc,
    276                                     StringRef Namespace) {
    277     First->PragmaDiagnosticPop(Loc, Namespace);
    278     Second->PragmaDiagnosticPop(Loc, Namespace);
    279   }
    280 
    281   virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
    282                                 diag::Mapping mapping, StringRef Str) {
    283     First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
    284     Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
    285   }
    286 
    287   virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
    288                             SourceRange Range) {
    289     First->MacroExpands(MacroNameTok, MI, Range);
    290     Second->MacroExpands(MacroNameTok, MI, Range);
    291   }
    292 
    293   virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
    294     First->MacroDefined(MacroNameTok, MI);
    295     Second->MacroDefined(MacroNameTok, MI);
    296   }
    297 
    298   virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
    299     First->MacroUndefined(MacroNameTok, MI);
    300     Second->MacroUndefined(MacroNameTok, MI);
    301   }
    302 
    303   virtual void Defined(const Token &MacroNameTok) {
    304     First->Defined(MacroNameTok);
    305     Second->Defined(MacroNameTok);
    306   }
    307 
    308   virtual void SourceRangeSkipped(SourceRange Range) {
    309     First->SourceRangeSkipped(Range);
    310     Second->SourceRangeSkipped(Range);
    311   }
    312 
    313   /// If -- This hook is called whenever an #if is seen.
    314   virtual void If(SourceRange Range) {
    315     First->If(Range);
    316     Second->If(Range);
    317   }
    318 
    319   /// Elif -- This hook is called whenever an #if is seen.
    320   virtual void Elif(SourceRange Range) {
    321     First->Elif(Range);
    322     Second->Elif(Range);
    323   }
    324 
    325   /// Ifdef -- This hook is called whenever an #ifdef is seen.
    326   virtual void Ifdef(const Token &MacroNameTok) {
    327     First->Ifdef(MacroNameTok);
    328     Second->Ifdef(MacroNameTok);
    329   }
    330 
    331   /// Ifndef -- This hook is called whenever an #ifndef is seen.
    332   virtual void Ifndef(const Token &MacroNameTok) {
    333     First->Ifndef(MacroNameTok);
    334     Second->Ifndef(MacroNameTok);
    335   }
    336 
    337   /// Else -- This hook is called whenever an #else is seen.
    338   virtual void Else() {
    339     First->Else();
    340     Second->Else();
    341   }
    342 
    343   /// Endif -- This hook is called whenever an #endif is seen.
    344   virtual void Endif() {
    345     First->Endif();
    346     Second->Endif();
    347   }
    348 };
    349 
    350 }  // end namespace clang
    351 
    352 #endif
    353