clang API Documentation
00001 //===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the MultipleIncludeOpt interface. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H 00015 #define LLVM_CLANG_MULTIPLEINCLUDEOPT_H 00016 00017 namespace clang { 00018 class IdentifierInfo; 00019 00020 /// MultipleIncludeOpt - This class implements the simple state machine that the 00021 /// Lexer class uses to detect files subject to the 'multiple-include' 00022 /// optimization. The public methods in this class are triggered by various 00023 /// events that occur when a file is lexed, and after the entire file is lexed, 00024 /// information about which macro (if any) controls the header is returned. 00025 class MultipleIncludeOpt { 00026 /// ReadAnyTokens - This is set to false when a file is first opened and true 00027 /// any time a token is returned to the client or a (non-multiple-include) 00028 /// directive is parsed. When the final #endif is parsed this is reset back 00029 /// to false, that way any tokens before the first #ifdef or after the last 00030 /// #endif can be easily detected. 00031 bool ReadAnyTokens; 00032 00033 /// ReadAnyTokens - This is set to false when a file is first opened and true 00034 /// any time a token is returned to the client or a (non-multiple-include) 00035 /// directive is parsed. When the final #endif is parsed this is reset back 00036 /// to false, that way any tokens before the first #ifdef or after the last 00037 /// #endif can be easily detected. 00038 bool DidMacroExpansion; 00039 00040 /// TheMacro - The controlling macro for a file, if valid. 00041 /// 00042 const IdentifierInfo *TheMacro; 00043 public: 00044 MultipleIncludeOpt() { 00045 ReadAnyTokens = false; 00046 DidMacroExpansion = false; 00047 TheMacro = 0; 00048 } 00049 00050 /// Invalidate - Permanently mark this file as not being suitable for the 00051 /// include-file optimization. 00052 void Invalidate() { 00053 // If we have read tokens but have no controlling macro, the state-machine 00054 // below can never "accept". 00055 ReadAnyTokens = true; 00056 TheMacro = 0; 00057 } 00058 00059 /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the 00060 /// top of the file when reading preprocessor directives. Otherwise, reading 00061 /// the "ifndef x" would count as reading tokens. 00062 bool getHasReadAnyTokensVal() const { return ReadAnyTokens; } 00063 00064 // If a token is read, remember that we have seen a side-effect in this file. 00065 void ReadToken() { ReadAnyTokens = true; } 00066 00067 /// ExpandedMacro - When a macro is expanded with this lexer as the current 00068 /// buffer, this method is called to disable the MIOpt if needed. 00069 void ExpandedMacro() { DidMacroExpansion = true; } 00070 00071 /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the 00072 /// "#if !defined" equivalent) without any preceding tokens, this method is 00073 /// called. 00074 /// 00075 /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller 00076 /// ensures that this is only called if there are no tokens read before the 00077 /// #ifndef. The caller is required to do this, because reading the #if line 00078 /// obviously reads in in tokens. 00079 void EnterTopLevelIFNDEF(const IdentifierInfo *M) { 00080 // If the macro is already set, this is after the top-level #endif. 00081 if (TheMacro) 00082 return Invalidate(); 00083 00084 // If we have already expanded a macro by the end of the #ifndef line, then 00085 // there is a macro expansion *in* the #ifndef line. This means that the 00086 // condition could evaluate differently when subsequently #included. Reject 00087 // this. 00088 if (DidMacroExpansion) 00089 return Invalidate(); 00090 00091 // Remember that we're in the #if and that we have the macro. 00092 ReadAnyTokens = true; 00093 TheMacro = M; 00094 } 00095 00096 /// EnterTopLevelConditional - This is invoked when a top level conditional 00097 /// (except #ifndef) is found. 00098 void EnterTopLevelConditional() { 00099 /// If a conditional directive (except #ifndef) is found at the top level, 00100 /// there is a chunk of the file not guarded by the controlling macro. 00101 Invalidate(); 00102 } 00103 00104 /// ExitTopLevelConditional - This method is called when the lexer exits the 00105 /// top-level conditional. 00106 void ExitTopLevelConditional() { 00107 // If we have a macro, that means the top of the file was ok. Set our state 00108 // back to "not having read any tokens" so we can detect anything after the 00109 // #endif. 00110 if (!TheMacro) return Invalidate(); 00111 00112 // At this point, we haven't "read any tokens" but we do have a controlling 00113 // macro. 00114 ReadAnyTokens = false; 00115 } 00116 00117 /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if 00118 /// there is a controlling macro, return it. 00119 const IdentifierInfo *GetControllingMacroAtEndOfFile() const { 00120 // If we haven't read any tokens after the #endif, return the controlling 00121 // macro if it's valid (if it isn't, it will be null). 00122 if (!ReadAnyTokens) 00123 return TheMacro; 00124 return 0; 00125 } 00126 }; 00127 00128 } // end namespace clang 00129 00130 #endif