MultipleIncludeOpt.h revision 071662d971e51ac64e0fe16d3baf9d85894b09a5
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/// \file 11/// \brief Defines the MultipleIncludeOpt interface. 12 13#ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H 14#define LLVM_CLANG_MULTIPLEINCLUDEOPT_H 15 16namespace clang { 17class IdentifierInfo; 18 19/// \brief Implements the simple state machine that the Lexer class uses to 20/// detect files subject to the 'multiple-include' optimization. 21/// 22/// 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. 25class 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; 43public: 44 MultipleIncludeOpt() { 45 ReadAnyTokens = false; 46 DidMacroExpansion = false; 47 TheMacro = 0; 48 } 49 50 /// Invalidate - Permanently mark this file as not being suitable for the 51 /// include-file optimization. 52 void Invalidate() { 53 // If we have read tokens but have no controlling macro, the state-machine 54 // below can never "accept". 55 ReadAnyTokens = true; 56 TheMacro = 0; 57 } 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 bool getHasReadAnyTokensVal() const { return ReadAnyTokens; } 63 64 // If a token is read, remember that we have seen a side-effect in this file. 65 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 void ExpandedMacro() { DidMacroExpansion = true; } 70 71 /// \brief Called when entering a top-level \#ifndef directive (or the 72 /// "\#if !defined" equivalent) without any preceding tokens. 73 /// 74 /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller 75 /// ensures that this is only called if there are no tokens read before the 76 /// \#ifndef. The caller is required to do this, because reading the \#if 77 /// line obviously reads in in tokens. 78 void EnterTopLevelIFNDEF(const IdentifierInfo *M) { 79 // If the macro is already set, this is after the top-level #endif. 80 if (TheMacro) 81 return Invalidate(); 82 83 // If we have already expanded a macro by the end of the #ifndef line, then 84 // there is a macro expansion *in* the #ifndef line. This means that the 85 // condition could evaluate differently when subsequently #included. Reject 86 // this. 87 if (DidMacroExpansion) 88 return Invalidate(); 89 90 // Remember that we're in the #if and that we have the macro. 91 ReadAnyTokens = true; 92 TheMacro = M; 93 } 94 95 /// \brief Invoked when a top level conditional (except \#ifndef) is found. 96 void EnterTopLevelConditional() { 97 /// If a conditional directive (except #ifndef) is found at the top level, 98 /// there is a chunk of the file not guarded by the controlling macro. 99 Invalidate(); 100 } 101 102 /// \brief Called when the lexer exits the top-level conditional. 103 void ExitTopLevelConditional() { 104 // If we have a macro, that means the top of the file was ok. Set our state 105 // back to "not having read any tokens" so we can detect anything after the 106 // #endif. 107 if (!TheMacro) return Invalidate(); 108 109 // At this point, we haven't "read any tokens" but we do have a controlling 110 // macro. 111 ReadAnyTokens = false; 112 } 113 114 /// \brief Once the entire file has been lexed, if there is a controlling 115 /// macro, return it. 116 const IdentifierInfo *GetControllingMacroAtEndOfFile() const { 117 // If we haven't read any tokens after the #endif, return the controlling 118 // macro if it's valid (if it isn't, it will be null). 119 if (!ReadAnyTokens) 120 return TheMacro; 121 return 0; 122 } 123}; 124 125} // end namespace clang 126 127#endif 128