1 //===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MultipleIncludeOpt interface.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H
15 #define LLVM_CLANG_MULTIPLEINCLUDEOPT_H
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.
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;
40 /// TheMacro - The controlling macro for a file, if valid.
42 const IdentifierInfo *TheMacro;
44 MultipleIncludeOpt() {
45 ReadAnyTokens = false;
46 DidMacroExpansion = false;
50 /// Invalidate - Permanently mark this file as not being suitable for the
51 /// include-file optimization.
53 // If we have read tokens but have no controlling macro, the state-machine
54 // below can never "accept".
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; }
64 // If a token is read, remember that we have seen a side-effect in this file.
65 void ReadToken() { ReadAnyTokens = true; }
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; }
71 /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the
72 /// "#if !defined" equivalent) without any preceding tokens, this method is
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 void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
80 // If the macro is already set, this is after the top-level #endif.
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
88 if (DidMacroExpansion)
91 // Remember that we're in the #if and that we have the macro.
96 /// EnterTopLevelConditional - This is invoked when a top level conditional
97 /// (except #ifndef) is found.
98 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.
104 /// ExitTopLevelConditional - This method is called when the lexer exits the
105 /// top-level conditional.
106 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
110 if (!TheMacro) return Invalidate();
112 // At this point, we haven't "read any tokens" but we do have a controlling
114 ReadAnyTokens = false;
117 /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if
118 /// there is a controlling macro, return it.
119 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).
128 } // end namespace clang