zcov: / include/clang/Lex/MultipleIncludeOpt.h


Files: 1 Branches Taken: 100.0% 8 / 8
Generated: 2010-02-10 01:31 Branches Executed: 100.0% 8 / 8
Line Coverage: 100.0% 29 / 29


Programs: 10 Runs 15090


       1                 : //===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- 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 MultipleIncludeOpt interface.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H
      15                 : #define LLVM_CLANG_MULTIPLEINCLUDEOPT_H
      16                 : 
      17                 : namespace clang {
      18                 : class IdentifierInfo;
      19                 : 
      20                 : /// MultipleIncludeOpt - This class implements the simple state machine that the
      21                 : /// Lexer class uses to detect files subject to the 'multiple-include'
      22                 : /// optimization.  The public methods in this class are triggered by various
      23                 : /// events that occur when a file is lexed, and after the entire file is lexed,
      24                 : /// information about which macro (if any) controls the header is returned.
      25                 : class MultipleIncludeOpt {
      26                 :   /// ReadAnyTokens - This is set to false when a file is first opened and true
      27                 :   /// any time a token is returned to the client or a (non-multiple-include)
      28                 :   /// directive is parsed.  When the final #endif is parsed this is reset back
      29                 :   /// to false, that way any tokens before the first #ifdef or after the last
      30                 :   /// #endif can be easily detected.
      31                 :   bool ReadAnyTokens;
      32                 : 
      33                 :   /// ReadAnyTokens - This is set to false when a file is first opened and true
      34                 :   /// any time a token is returned to the client or a (non-multiple-include)
      35                 :   /// directive is parsed.  When the final #endif is parsed this is reset back
      36                 :   /// to false, that way any tokens before the first #ifdef or after the last
      37                 :   /// #endif can be easily detected.
      38                 :   bool DidMacroExpansion;
      39                 : 
      40                 :   /// TheMacro - The controlling macro for a file, if valid.
      41                 :   ///
      42                 :   const IdentifierInfo *TheMacro;
      43                 : public:
      44           144591:   MultipleIncludeOpt() {
      45           144591:     ReadAnyTokens = false;
      46           144591:     DidMacroExpansion = false;
      47           144591:     TheMacro = 0;
      48           144591:   }
      49                 : 
      50                 :   /// Invalidate - Permenantly mark this file as not being suitable for the
      51                 :   /// include-file optimization.
      52              908:   void Invalidate() {
      53                 :     // If we have read tokens but have no controlling macro, the state-machine
      54                 :     // below can never "accept".
      55              908:     ReadAnyTokens = true;
      56              908:     TheMacro = 0;
      57              908:   }
      58                 : 
      59                 :   /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the
      60                 :   /// top of the file when reading preprocessor directives.  Otherwise, reading
      61                 :   /// the "ifndef x" would count as reading tokens.
      62           288096:   bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
      63                 : 
      64                 :   // If a token is read, remember that we have seen a side-effect in this file.
      65          2394946:   void ReadToken() { ReadAnyTokens = true; }
      66                 : 
      67                 :   /// ExpandedMacro - When a macro is expanded with this lexer as the current
      68                 :   /// buffer, this method is called to disable the MIOpt if needed.
      69             6809:   void ExpandedMacro() { DidMacroExpansion = true; }
      70                 : 
      71                 :   /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the
      72                 :   /// "#if !defined" equivalent) without any preceding tokens, this method is
      73                 :   /// called.
      74                 :   ///
      75                 :   /// Note, we don't care about the input value of 'ReadAnyTokens'.  The caller
      76                 :   /// ensures that this is only called if there are no tokens read before the
      77                 :   /// #ifndef.  The caller is required to do this, because reading the #if line
      78                 :   /// obviously reads in in tokens.
      79              356:   void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
      80                 :     // If the macro is already set, this is after the top-level #endif.
                        5: branch 0 taken
                      351: branch 1 taken
      81              356:     if (TheMacro)
      82                5:       return Invalidate();
      83                 : 
      84                 :     // If we have already expanded a macro by the end of the #ifndef line, then
      85                 :     // there is a macro expansion *in* the #ifndef line.  This means that the
      86                 :     // condition could evaluate differently when subsequently #included.  Reject
      87                 :     // this.
                        1: branch 0 taken
                      350: branch 1 taken
      88              351:     if (DidMacroExpansion)
      89                1:       return Invalidate();
      90                 : 
      91                 :     // Remember that we're in the #if and that we have the macro.
      92              350:     ReadAnyTokens = true;
      93              350:     TheMacro = M;
      94                 :   }
      95                 : 
      96                 :   /// EnterTopLevelConditional - This is invoked when a top level conditional
      97                 :   /// (except #ifndef) is found.
      98              615:   void EnterTopLevelConditional() {
      99                 :     /// If a conditional directive (except #ifndef) is found at the top level,
     100                 :     /// there is a chunk of the file not guarded by the controlling macro.
     101              615:     Invalidate();
     102              615:   }
     103                 : 
     104                 :   /// ExitTopLevelConditional - This method is called when the lexer exits the
     105                 :   /// top-level conditional.
     106              590:   void ExitTopLevelConditional() {
     107                 :     // If we have a macro, that means the top of the file was ok.  Set our state
     108                 :     // back to "not having read any tokens" so we can detect anything after the
     109                 :     // #endif.
                      287: branch 0 taken
                      303: branch 1 taken
     110              590:     if (!TheMacro) return Invalidate();
     111                 : 
     112                 :     // At this point, we haven't "read any tokens" but we do have a controlling
     113                 :     // macro.
     114              303:     ReadAnyTokens = false;
     115                 :   }
     116                 : 
     117                 :   /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if
     118                 :   /// there is a controlling macro, return it.
     119             5618:   const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
     120                 :     // If we haven't read any tokens after the #endif, return the controlling
     121                 :     // macro if it's valid (if it isn't, it will be null).
                      412: branch 0 taken
                     5206: branch 1 taken
     122             5618:     if (!ReadAnyTokens)
     123              412:       return TheMacro;
     124             5206:     return 0;
     125                 :   }
     126                 : };
     127                 : 
     128                 : }  // end namespace clang
     129                 : 
     130                 : #endif

Generated: 2010-02-10 01:31 by zcov