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 //===----------------------------------------------------------------------===//
11 /// \brief Defines the MultipleIncludeOpt interface.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H
16 #define LLVM_CLANG_MULTIPLEINCLUDEOPT_H
21 /// \brief Implements the simple state machine that the Lexer class uses to
22 /// detect files subject to the 'multiple-include' optimization.
24 /// The public methods in this class are triggered by various
25 /// events that occur when a file is lexed, and after the entire file is lexed,
26 /// information about which macro (if any) controls the header is returned.
27 class MultipleIncludeOpt {
28 /// ReadAnyTokens - This is set to false when a file is first opened and true
29 /// any time a token is returned to the client or a (non-multiple-include)
30 /// directive is parsed. When the final \#endif is parsed this is reset back
31 /// to false, that way any tokens before the first \#ifdef or after the last
32 /// \#endif can be easily detected.
35 /// ReadAnyTokens - This is set to false when a file is first opened and true
36 /// any time a token is returned to the client or a (non-multiple-include)
37 /// directive is parsed. When the final #endif is parsed this is reset back
38 /// to false, that way any tokens before the first #ifdef or after the last
39 /// #endif can be easily detected.
40 bool DidMacroExpansion;
42 /// TheMacro - The controlling macro for a file, if valid.
44 const IdentifierInfo *TheMacro;
46 MultipleIncludeOpt() {
47 ReadAnyTokens = false;
48 DidMacroExpansion = false;
52 /// Invalidate - Permanently mark this file as not being suitable for the
53 /// include-file optimization.
55 // If we have read tokens but have no controlling macro, the state-machine
56 // below can never "accept".
61 /// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the
62 /// top of the file when reading preprocessor directives. Otherwise, reading
63 /// the "ifndef x" would count as reading tokens.
64 bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
66 // If a token is read, remember that we have seen a side-effect in this file.
67 void ReadToken() { ReadAnyTokens = true; }
69 /// ExpandedMacro - When a macro is expanded with this lexer as the current
70 /// buffer, this method is called to disable the MIOpt if needed.
71 void ExpandedMacro() { DidMacroExpansion = true; }
73 /// \brief Called when entering a top-level \#ifndef directive (or the
74 /// "\#if !defined" equivalent) without any preceding tokens.
76 /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller
77 /// ensures that this is only called if there are no tokens read before the
78 /// \#ifndef. The caller is required to do this, because reading the \#if
79 /// line obviously reads in in tokens.
80 void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
81 // If the macro is already set, this is after the top-level #endif.
85 // If we have already expanded a macro by the end of the #ifndef line, then
86 // there is a macro expansion *in* the #ifndef line. This means that the
87 // condition could evaluate differently when subsequently #included. Reject
89 if (DidMacroExpansion)
92 // Remember that we're in the #if and that we have the macro.
97 /// \brief Invoked when a top level conditional (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 /// \brief Called when the lexer exits the top-level conditional.
105 void ExitTopLevelConditional() {
106 // If we have a macro, that means the top of the file was ok. Set our state
107 // back to "not having read any tokens" so we can detect anything after the
109 if (!TheMacro) return Invalidate();
111 // At this point, we haven't "read any tokens" but we do have a controlling
113 ReadAnyTokens = false;
116 /// \brief Once the entire file has been lexed, if there is a controlling
117 /// macro, return it.
118 const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
119 // If we haven't read any tokens after the #endif, return the controlling
120 // macro if it's valid (if it isn't, it will be null).
127 } // end namespace clang