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
20namespace clang {
21class 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.
29class 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;
58public:
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.