1 | //===--- DependenceFlags.h ------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | #ifndef LLVM_CLANG_AST_DEPENDENCEFLAGS_H |
9 | #define LLVM_CLANG_AST_DEPENDENCEFLAGS_H |
10 | |
11 | #include "clang/Basic/BitmaskEnum.h" |
12 | #include "llvm/ADT/BitmaskEnum.h" |
13 | #include <cstdint> |
14 | |
15 | namespace clang { |
16 | struct ExprDependenceScope { |
17 | enum ExprDependence : uint8_t { |
18 | UnexpandedPack = 1, |
19 | // This expr depends in any way on |
20 | // - a template parameter, it implies that the resolution of this expr may |
21 | // cause instantiation to fail |
22 | // - or an error (often in a non-template context) |
23 | // |
24 | // Note that C++ standard doesn't define the instantiation-dependent term, |
25 | // we follow the formal definition coming from the Itanium C++ ABI, and |
26 | // extend it to errors. |
27 | Instantiation = 2, |
28 | // The type of this expr depends on a template parameter, or an error. |
29 | Type = 4, |
30 | // The value of this expr depends on a template parameter, or an error. |
31 | Value = 8, |
32 | |
33 | // clang extension: this expr contains or references an error, and is |
34 | // considered dependent on how that error is resolved. |
35 | Error = 16, |
36 | |
37 | None = 0, |
38 | All = 31, |
39 | |
40 | TypeValue = Type | Value, |
41 | TypeInstantiation = Type | Instantiation, |
42 | ValueInstantiation = Value | Instantiation, |
43 | TypeValueInstantiation = Type | Value | Instantiation, |
44 | ErrorDependent = Error | ValueInstantiation, |
45 | |
46 | LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) |
47 | }; |
48 | }; |
49 | using ExprDependence = ExprDependenceScope::ExprDependence; |
50 | |
51 | struct TypeDependenceScope { |
52 | enum TypeDependence : uint8_t { |
53 | /// Whether this type contains an unexpanded parameter pack |
54 | /// (for C++11 variadic templates) |
55 | UnexpandedPack = 1, |
56 | /// Whether this type somehow involves |
57 | /// - a template parameter, even if the resolution of the type does not |
58 | /// depend on a template parameter. |
59 | /// - or an error. |
60 | Instantiation = 2, |
61 | /// Whether this type |
62 | /// - is a dependent type (C++ [temp.dep.type]) |
63 | /// - or it somehow involves an error, e.g. decltype(recovery-expr) |
64 | Dependent = 4, |
65 | /// Whether this type is a variably-modified type (C99 6.7.5). |
66 | VariablyModified = 8, |
67 | |
68 | /// Whether this type references an error, e.g. decltype(err-expression) |
69 | /// yields an error type. |
70 | Error = 16, |
71 | |
72 | None = 0, |
73 | All = 31, |
74 | |
75 | DependentInstantiation = Dependent | Instantiation, |
76 | |
77 | LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) |
78 | }; |
79 | }; |
80 | using TypeDependence = TypeDependenceScope::TypeDependence; |
81 | |
82 | #define LLVM_COMMON_DEPENDENCE(NAME) \ |
83 | struct NAME##Scope { \ |
84 | enum NAME : uint8_t { \ |
85 | UnexpandedPack = 1, \ |
86 | Instantiation = 2, \ |
87 | Dependent = 4, \ |
88 | Error = 8, \ |
89 | \ |
90 | None = 0, \ |
91 | DependentInstantiation = Dependent | Instantiation, \ |
92 | All = 15, \ |
93 | \ |
94 | LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) \ |
95 | }; \ |
96 | }; \ |
97 | using NAME = NAME##Scope::NAME; |
98 | |
99 | LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence) |
100 | LLVM_COMMON_DEPENDENCE(TemplateNameDependence) |
101 | LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence) |
102 | #undef LLVM_COMMON_DEPENDENCE |
103 | |
104 | // A combined space of all dependence concepts for all node types. |
105 | // Used when aggregating dependence of nodes of different types. |
106 | class Dependence { |
107 | public: |
108 | enum Bits : uint8_t { |
109 | None = 0, |
110 | |
111 | // Contains a template parameter pack that wasn't expanded. |
112 | UnexpandedPack = 1, |
113 | // Depends on a template parameter or an error in some way. |
114 | // Validity depends on how the template is instantiated or the error is |
115 | // resolved. |
116 | Instantiation = 2, |
117 | // Expression type depends on template context, or an error. |
118 | // Value and Instantiation should also be set. |
119 | Type = 4, |
120 | // Expression value depends on template context, or an error. |
121 | // Instantiation should also be set. |
122 | Value = 8, |
123 | // Depends on template context, or an error. |
124 | // The type/value distinction is only meaningful for expressions. |
125 | Dependent = Type | Value, |
126 | // Includes an error, and depends on how it is resolved. |
127 | Error = 16, |
128 | // Type depends on a runtime value (variable-length array). |
129 | VariablyModified = 32, |
130 | |
131 | // Dependence that is propagated syntactically, regardless of semantics. |
132 | Syntactic = UnexpandedPack | Instantiation | Error, |
133 | |
134 | LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified) |
135 | }; |
136 | |
137 | Dependence() : V(None) {} |
138 | |
139 | Dependence(TypeDependence D) |
140 | : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) | |
141 | translate(D, TypeDependence::Instantiation, Instantiation) | |
142 | translate(D, TypeDependence::Dependent, Dependent) | |
143 | translate(D, TypeDependence::Error, Error) | |
144 | translate(D, TypeDependence::VariablyModified, VariablyModified)) {} |
145 | |
146 | Dependence(ExprDependence D) |
147 | : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) | |
148 | translate(D, ExprDependence::Instantiation, Instantiation) | |
149 | translate(D, ExprDependence::Type, Type) | |
150 | translate(D, ExprDependence::Value, Value) | |
151 | translate(D, ExprDependence::Error, Error)) {} |
152 | |
153 | Dependence(NestedNameSpecifierDependence D) : |
154 | V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) | |
155 | translate(D, NNSDependence::Instantiation, Instantiation) | |
156 | translate(D, NNSDependence::Dependent, Dependent) | |
157 | translate(D, NNSDependence::Error, Error)) {} |
158 | |
159 | Dependence(TemplateArgumentDependence D) |
160 | : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) | |
161 | translate(D, TADependence::Instantiation, Instantiation) | |
162 | translate(D, TADependence::Dependent, Dependent) | |
163 | translate(D, TADependence::Error, Error)) {} |
164 | |
165 | Dependence(TemplateNameDependence D) |
166 | : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) | |
167 | translate(D, TNDependence::Instantiation, Instantiation) | |
168 | translate(D, TNDependence::Dependent, Dependent) | |
169 | translate(D, TNDependence::Error, Error)) {} |
170 | |
171 | /// Extract only the syntactic portions of this type's dependence. |
172 | Dependence syntactic() { |
173 | Dependence Result = *this; |
174 | Result.V &= Syntactic; |
175 | return Result; |
176 | } |
177 | |
178 | TypeDependence type() const { |
179 | return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) | |
180 | translate(V, Instantiation, TypeDependence::Instantiation) | |
181 | translate(V, Dependent, TypeDependence::Dependent) | |
182 | translate(V, Error, TypeDependence::Error) | |
183 | translate(V, VariablyModified, TypeDependence::VariablyModified); |
184 | } |
185 | |
186 | ExprDependence expr() const { |
187 | return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) | |
188 | translate(V, Instantiation, ExprDependence::Instantiation) | |
189 | translate(V, Type, ExprDependence::Type) | |
190 | translate(V, Value, ExprDependence::Value) | |
191 | translate(V, Error, ExprDependence::Error); |
192 | } |
193 | |
194 | NestedNameSpecifierDependence nestedNameSpecifier() const { |
195 | return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) | |
196 | translate(V, Instantiation, NNSDependence::Instantiation) | |
197 | translate(V, Dependent, NNSDependence::Dependent) | |
198 | translate(V, Error, NNSDependence::Error); |
199 | } |
200 | |
201 | TemplateArgumentDependence templateArgument() const { |
202 | return translate(V, UnexpandedPack, TADependence::UnexpandedPack) | |
203 | translate(V, Instantiation, TADependence::Instantiation) | |
204 | translate(V, Dependent, TADependence::Dependent) | |
205 | translate(V, Error, TADependence::Error); |
206 | } |
207 | |
208 | TemplateNameDependence templateName() const { |
209 | return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) | |
210 | translate(V, Instantiation, TNDependence::Instantiation) | |
211 | translate(V, Dependent, TNDependence::Dependent) | |
212 | translate(V, Error, TNDependence::Error); |
213 | } |
214 | |
215 | private: |
216 | Bits V; |
217 | |
218 | template <typename T, typename U> |
219 | static U translate(T Bits, T FromBit, U ToBit) { |
220 | return (Bits & FromBit) ? ToBit : static_cast<U>(0); |
221 | } |
222 | |
223 | // Abbreviations to make conversions more readable. |
224 | using NNSDependence = NestedNameSpecifierDependence; |
225 | using TADependence = TemplateArgumentDependence; |
226 | using TNDependence = TemplateNameDependence; |
227 | }; |
228 | |
229 | /// Computes dependencies of a reference with the name having template arguments |
230 | /// with \p TA dependencies. |
231 | inline ExprDependence toExprDependence(TemplateArgumentDependence TA) { |
232 | return Dependence(TA).expr(); |
233 | } |
234 | inline ExprDependence toExprDependence(TypeDependence D) { |
235 | return Dependence(D).expr(); |
236 | } |
237 | // Note: it's often necessary to strip `Dependent` from qualifiers. |
238 | // If V<T>:: refers to the current instantiation, NNS is considered dependent |
239 | // but the containing V<T>::foo likely isn't. |
240 | inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) { |
241 | return Dependence(D).expr(); |
242 | } |
243 | inline ExprDependence turnTypeToValueDependence(ExprDependence D) { |
244 | // Type-dependent expressions are always be value-dependent, so we simply drop |
245 | // type dependency. |
246 | return D & ~ExprDependence::Type; |
247 | } |
248 | inline ExprDependence turnValueToTypeDependence(ExprDependence D) { |
249 | // Type-dependent expressions are always be value-dependent. |
250 | if (D & ExprDependence::Value) |
251 | D |= ExprDependence::Type; |
252 | return D; |
253 | } |
254 | |
255 | // Returned type-dependence will never have VariablyModified set. |
256 | inline TypeDependence toTypeDependence(ExprDependence D) { |
257 | return Dependence(D).type(); |
258 | } |
259 | inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) { |
260 | return Dependence(D).type(); |
261 | } |
262 | inline TypeDependence toTypeDependence(TemplateNameDependence D) { |
263 | return Dependence(D).type(); |
264 | } |
265 | inline TypeDependence toTypeDependence(TemplateArgumentDependence D) { |
266 | return Dependence(D).type(); |
267 | } |
268 | |
269 | inline TypeDependence toSyntacticDependence(TypeDependence D) { |
270 | return Dependence(D).syntactic().type(); |
271 | } |
272 | |
273 | inline NestedNameSpecifierDependence |
274 | toNestedNameSpecifierDependendence(TypeDependence D) { |
275 | return Dependence(D).nestedNameSpecifier(); |
276 | } |
277 | |
278 | inline TemplateArgumentDependence |
279 | toTemplateArgumentDependence(TypeDependence D) { |
280 | return Dependence(D).templateArgument(); |
281 | } |
282 | inline TemplateArgumentDependence |
283 | toTemplateArgumentDependence(TemplateNameDependence D) { |
284 | return Dependence(D).templateArgument(); |
285 | } |
286 | inline TemplateArgumentDependence |
287 | toTemplateArgumentDependence(ExprDependence D) { |
288 | return Dependence(D).templateArgument(); |
289 | } |
290 | |
291 | inline TemplateNameDependence |
292 | toTemplateNameDependence(NestedNameSpecifierDependence D) { |
293 | return Dependence(D).templateName(); |
294 | } |
295 | |
296 | LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); |
297 | |
298 | } // namespace clang |
299 | #endif |
300 | |