Warning: That file was not part of the compilation database. It may have many parsing errors.
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 | /// Defines the MultipleIncludeOpt interface. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H |
16 | #define LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H |
17 | |
18 | #include "clang/Basic/SourceLocation.h" |
19 | |
20 | namespace clang { |
21 | class IdentifierInfo; |
22 | |
23 | /// Implements the simple state machine that the Lexer class uses to |
24 | /// detect files subject to the 'multiple-include' optimization. |
25 | /// |
26 | /// The public methods in this class are triggered by various |
27 | /// events that occur when a file is lexed, and after the entire file is lexed, |
28 | /// information about which macro (if any) controls the header is returned. |
29 | class MultipleIncludeOpt { |
30 | /// ReadAnyTokens - This is set to false when a file is first opened and true |
31 | /// any time a token is returned to the client or a (non-multiple-include) |
32 | /// directive is parsed. When the final \#endif is parsed this is reset back |
33 | /// to false, that way any tokens before the first \#ifdef or after the last |
34 | /// \#endif can be easily detected. |
35 | bool ReadAnyTokens; |
36 | |
37 | /// ImmediatelyAfterTopLevelIfndef - This is true when the only tokens |
38 | /// processed in the file so far is an #ifndef and an identifier. Used in |
39 | /// the detection of header guards in a file. |
40 | bool ImmediatelyAfterTopLevelIfndef; |
41 | |
42 | /// ReadAnyTokens - This is set to false when a file is first opened and true |
43 | /// any time a token is returned to the client or a (non-multiple-include) |
44 | /// directive is parsed. When the final #endif is parsed this is reset back |
45 | /// to false, that way any tokens before the first #ifdef or after the last |
46 | /// #endif can be easily detected. |
47 | bool DidMacroExpansion; |
48 | |
49 | /// TheMacro - The controlling macro for a file, if valid. |
50 | /// |
51 | const IdentifierInfo *TheMacro; |
52 | |
53 | /// DefinedMacro - The macro defined right after TheMacro, if any. |
54 | const IdentifierInfo *DefinedMacro; |
55 | |
56 | SourceLocation MacroLoc; |
57 | SourceLocation DefinedLoc; |
58 | public: |
59 | MultipleIncludeOpt() { |
60 | ReadAnyTokens = false; |
61 | ImmediatelyAfterTopLevelIfndef = false; |
62 | DidMacroExpansion = false; |
63 | TheMacro = nullptr; |
64 | DefinedMacro = nullptr; |
65 | } |
66 | |
67 | SourceLocation GetMacroLocation() const { |
68 | return MacroLoc; |
69 | } |
70 | |
71 | SourceLocation GetDefinedLocation() const { |
72 | return DefinedLoc; |
73 | } |
74 | |
75 | void resetImmediatelyAfterTopLevelIfndef() { |
76 | ImmediatelyAfterTopLevelIfndef = false; |
77 | } |
78 | |
79 | void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc) { |
80 | DefinedMacro = M; |
81 | DefinedLoc = Loc; |
82 | } |
83 | |
84 | /// Invalidate - Permanently mark this file as not being suitable for the |
85 | /// include-file optimization. |
86 | void Invalidate() { |
87 | // If we have read tokens but have no controlling macro, the state-machine |
88 | // below can never "accept". |
89 | ReadAnyTokens = true; |
90 | ImmediatelyAfterTopLevelIfndef = false; |
91 | DefinedMacro = nullptr; |
92 | TheMacro = nullptr; |
93 | } |
94 | |
95 | /// getHasReadAnyTokensVal - This is used for the \#ifndef handshake at the |
96 | /// top of the file when reading preprocessor directives. Otherwise, reading |
97 | /// the "ifndef x" would count as reading tokens. |
98 | bool getHasReadAnyTokensVal() const { return ReadAnyTokens; } |
99 | |
100 | /// getImmediatelyAfterTopLevelIfndef - returns true if the last directive |
101 | /// was an #ifndef at the beginning of the file. |
102 | bool getImmediatelyAfterTopLevelIfndef() const { |
103 | return ImmediatelyAfterTopLevelIfndef; |
104 | } |
105 | |
106 | // If a token is read, remember that we have seen a side-effect in this file. |
107 | void ReadToken() { |
108 | ReadAnyTokens = true; |
109 | ImmediatelyAfterTopLevelIfndef = false; |
110 | } |
111 | |
112 | /// ExpandedMacro - When a macro is expanded with this lexer as the current |
113 | /// buffer, this method is called to disable the MIOpt if needed. |
114 | void ExpandedMacro() { DidMacroExpansion = true; } |
115 | |
116 | /// Called when entering a top-level \#ifndef directive (or the |
117 | /// "\#if !defined" equivalent) without any preceding tokens. |
118 | /// |
119 | /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller |
120 | /// ensures that this is only called if there are no tokens read before the |
121 | /// \#ifndef. The caller is required to do this, because reading the \#if |
122 | /// line obviously reads in tokens. |
123 | void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc) { |
124 | // If the macro is already set, this is after the top-level #endif. |
125 | if (TheMacro) |
126 | return Invalidate(); |
127 | |
128 | // If we have already expanded a macro by the end of the #ifndef line, then |
129 | // there is a macro expansion *in* the #ifndef line. This means that the |
130 | // condition could evaluate differently when subsequently #included. Reject |
131 | // this. |
132 | if (DidMacroExpansion) |
133 | return Invalidate(); |
134 | |
135 | // Remember that we're in the #if and that we have the macro. |
136 | ReadAnyTokens = true; |
137 | ImmediatelyAfterTopLevelIfndef = true; |
138 | TheMacro = M; |
139 | MacroLoc = Loc; |
140 | } |
141 | |
142 | /// Invoked when a top level conditional (except \#ifndef) is found. |
143 | void EnterTopLevelConditional() { |
144 | // If a conditional directive (except #ifndef) is found at the top level, |
145 | // there is a chunk of the file not guarded by the controlling macro. |
146 | Invalidate(); |
147 | } |
148 | |
149 | /// Called when the lexer exits the top-level conditional. |
150 | void ExitTopLevelConditional() { |
151 | // If we have a macro, that means the top of the file was ok. Set our state |
152 | // back to "not having read any tokens" so we can detect anything after the |
153 | // #endif. |
154 | if (!TheMacro) return Invalidate(); |
155 | |
156 | // At this point, we haven't "read any tokens" but we do have a controlling |
157 | // macro. |
158 | ReadAnyTokens = false; |
159 | ImmediatelyAfterTopLevelIfndef = false; |
160 | } |
161 | |
162 | /// Once the entire file has been lexed, if there is a controlling |
163 | /// macro, return it. |
164 | const IdentifierInfo *GetControllingMacroAtEndOfFile() const { |
165 | // If we haven't read any tokens after the #endif, return the controlling |
166 | // macro if it's valid (if it isn't, it will be null). |
167 | if (!ReadAnyTokens) |
168 | return TheMacro; |
169 | return nullptr; |
170 | } |
171 | |
172 | /// If the ControllingMacro is followed by a macro definition, return |
173 | /// the macro that was defined. |
174 | const IdentifierInfo *GetDefinedMacro() const { |
175 | return DefinedMacro; |
176 | } |
177 | }; |
178 | |
179 | } // end namespace clang |
180 | |
181 | #endif |
182 |
Warning: That file was not part of the compilation database. It may have many parsing errors.