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 /// \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/Basic/DiagnosticIDs.h"
     19 #include "clang/Basic/SourceLocation.h"
     20 #include "clang/Lex/DirectoryLookup.h"
     21 #include "clang/Lex/ModuleLoader.h"
     22 #include "llvm/ADT/StringRef.h"
     23 #include <string>
     24 
     25 namespace clang {
     26   class SourceLocation;
     27   class Token;
     28   class IdentifierInfo;
     29   class MacroDirective;
     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.
     35 class PPCallbacks {
     36 public:
     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 MacroDirective *MD,
    188                             SourceRange Range) {
    189   }
    190 
    191   /// \brief Hook called whenever a macro definition is seen.
    192   virtual void MacroDefined(const Token &MacroNameTok,
    193                             const MacroDirective *MD) {
    194   }
    195 
    196   /// \brief Hook called whenever a macro \#undef is seen.
    197   ///
    198   /// MD is released immediately following this callback.
    199   virtual void MacroUndefined(const Token &MacroNameTok,
    200                               const MacroDirective *MD) {
    201   }
    202 
    203   /// \brief Hook called whenever the 'defined' operator is seen.
    204   /// \param MD The MacroDirective if the name was a macro, null otherwise.
    205   virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) {
    206   }
    207 
    208   /// \brief Hook called when a source range is skipped.
    209   /// \param Range The SourceRange that was skipped. The range begins at the
    210   /// \#if/\#else directive and ends after the \#endif/\#else directive.
    211   virtual void SourceRangeSkipped(SourceRange Range) {
    212   }
    213 
    214   /// \brief Hook called whenever an \#if is seen.
    215   /// \param Loc the source location of the directive.
    216   /// \param ConditionRange The SourceRange of the expression being tested.
    217   ///
    218   // FIXME: better to pass in a list (or tree!) of Tokens.
    219   virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
    220   }
    221 
    222   /// \brief Hook called whenever an \#elif is seen.
    223   /// \param Loc the source location of the directive.
    224   /// \param ConditionRange The SourceRange of the expression being tested.
    225   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
    226   // FIXME: better to pass in a list (or tree!) of Tokens.
    227   virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
    228                     SourceLocation IfLoc) {
    229   }
    230 
    231   /// \brief Hook called whenever an \#ifdef is seen.
    232   /// \param Loc the source location of the directive.
    233   /// \param MacroNameTok Information on the token being tested.
    234   /// \param MD The MacroDirective if the name was a macro, null otherwise.
    235   virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
    236                      const MacroDirective *MD) {
    237   }
    238 
    239   /// \brief Hook called whenever an \#ifndef is seen.
    240   /// \param Loc the source location of the directive.
    241   /// \param MacroNameTok Information on the token being tested.
    242   /// \param MD The MacroDirective if the name was a macro, null otherwise.
    243   virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
    244                       const MacroDirective *MD) {
    245   }
    246 
    247   /// \brief Hook called whenever an \#else is seen.
    248   /// \param Loc the source location of the directive.
    249   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
    250   virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
    251   }
    252 
    253   /// \brief Hook called whenever an \#endif is seen.
    254   /// \param Loc the source location of the directive.
    255   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
    256   virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
    257   }
    258 };
    259 
    260 /// \brief Simple wrapper class for chaining callbacks.
    261 class PPChainedCallbacks : public PPCallbacks {
    262   virtual void anchor();
    263   PPCallbacks *First, *Second;
    264 
    265 public:
    266   PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
    267     : First(_First), Second(_Second) {}
    268   ~PPChainedCallbacks() {
    269     delete Second;
    270     delete First;
    271   }
    272 
    273   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
    274                            SrcMgr::CharacteristicKind FileType,
    275                            FileID PrevFID) {
    276     First->FileChanged(Loc, Reason, FileType, PrevFID);
    277     Second->FileChanged(Loc, Reason, FileType, PrevFID);
    278   }
    279 
    280   virtual void FileSkipped(const FileEntry &ParentFile,
    281                            const Token &FilenameTok,
    282                            SrcMgr::CharacteristicKind FileType) {
    283     First->FileSkipped(ParentFile, FilenameTok, FileType);
    284     Second->FileSkipped(ParentFile, FilenameTok, FileType);
    285   }
    286 
    287   virtual bool FileNotFound(StringRef FileName,
    288                             SmallVectorImpl<char> &RecoveryPath) {
    289     return First->FileNotFound(FileName, RecoveryPath) ||
    290            Second->FileNotFound(FileName, RecoveryPath);
    291   }
    292 
    293   virtual void InclusionDirective(SourceLocation HashLoc,
    294                                   const Token &IncludeTok,
    295                                   StringRef FileName,
    296                                   bool IsAngled,
    297                                   CharSourceRange FilenameRange,
    298                                   const FileEntry *File,
    299                                   StringRef SearchPath,
    300                                   StringRef RelativePath,
    301                                   const Module *Imported) {
    302     First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
    303                               FilenameRange, File, SearchPath, RelativePath,
    304                               Imported);
    305     Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
    306                                FilenameRange, File, SearchPath, RelativePath,
    307                                Imported);
    308   }
    309 
    310   virtual void moduleImport(SourceLocation ImportLoc,
    311                             ModuleIdPath Path,
    312                             const Module *Imported) {
    313     First->moduleImport(ImportLoc, Path, Imported);
    314     Second->moduleImport(ImportLoc, Path, Imported);
    315   }
    316 
    317   virtual void EndOfMainFile() {
    318     First->EndOfMainFile();
    319     Second->EndOfMainFile();
    320   }
    321 
    322   virtual void Ident(SourceLocation Loc, const std::string &str) {
    323     First->Ident(Loc, str);
    324     Second->Ident(Loc, str);
    325   }
    326 
    327   virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
    328                              const std::string &Str) {
    329     First->PragmaComment(Loc, Kind, Str);
    330     Second->PragmaComment(Loc, Kind, Str);
    331   }
    332 
    333   virtual void PragmaMessage(SourceLocation Loc, StringRef Str) {
    334     First->PragmaMessage(Loc, Str);
    335     Second->PragmaMessage(Loc, Str);
    336   }
    337 
    338   virtual void PragmaDiagnosticPush(SourceLocation Loc,
    339                                     StringRef Namespace) {
    340     First->PragmaDiagnosticPush(Loc, Namespace);
    341     Second->PragmaDiagnosticPush(Loc, Namespace);
    342   }
    343 
    344   virtual void PragmaDiagnosticPop(SourceLocation Loc,
    345                                     StringRef Namespace) {
    346     First->PragmaDiagnosticPop(Loc, Namespace);
    347     Second->PragmaDiagnosticPop(Loc, Namespace);
    348   }
    349 
    350   virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
    351                                 diag::Mapping mapping, StringRef Str) {
    352     First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
    353     Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
    354   }
    355 
    356   virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
    357                             SourceRange Range) {
    358     First->MacroExpands(MacroNameTok, MD, Range);
    359     Second->MacroExpands(MacroNameTok, MD, Range);
    360   }
    361 
    362   virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {
    363     First->MacroDefined(MacroNameTok, MD);
    364     Second->MacroDefined(MacroNameTok, MD);
    365   }
    366 
    367   virtual void MacroUndefined(const Token &MacroNameTok,
    368                               const MacroDirective *MD) {
    369     First->MacroUndefined(MacroNameTok, MD);
    370     Second->MacroUndefined(MacroNameTok, MD);
    371   }
    372 
    373   virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) {
    374     First->Defined(MacroNameTok, MD);
    375     Second->Defined(MacroNameTok, MD);
    376   }
    377 
    378   virtual void SourceRangeSkipped(SourceRange Range) {
    379     First->SourceRangeSkipped(Range);
    380     Second->SourceRangeSkipped(Range);
    381   }
    382 
    383   /// \brief Hook called whenever an \#if is seen.
    384   virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
    385     First->If(Loc, ConditionRange);
    386     Second->If(Loc, ConditionRange);
    387   }
    388 
    389   /// \brief Hook called whenever an \#if is seen.
    390   virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
    391                     SourceLocation IfLoc) {
    392     First->Elif(Loc, ConditionRange, IfLoc);
    393     Second->Elif(Loc, ConditionRange, IfLoc);
    394   }
    395 
    396   /// \brief Hook called whenever an \#ifdef is seen.
    397   virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
    398                      const MacroDirective *MD) {
    399     First->Ifdef(Loc, MacroNameTok, MD);
    400     Second->Ifdef(Loc, MacroNameTok, MD);
    401   }
    402 
    403   /// \brief Hook called whenever an \#ifndef is seen.
    404   virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
    405                       const MacroDirective *MD) {
    406     First->Ifndef(Loc, MacroNameTok, MD);
    407     Second->Ifndef(Loc, MacroNameTok, MD);
    408   }
    409 
    410   /// \brief Hook called whenever an \#else is seen.
    411   virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
    412     First->Else(Loc, IfLoc);
    413     Second->Else(Loc, IfLoc);
    414   }
    415 
    416   /// \brief Hook called whenever an \#endif is seen.
    417   virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
    418     First->Endif(Loc, IfLoc);
    419     Second->Endif(Loc, IfLoc);
    420   }
    421 };
    422 
    423 }  // end namespace clang
    424 
    425 #endif
    426