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)
LLVM_COMMON_DEPENDENCE(TemplateNameDependence)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 // Dependence that is propagated semantically, even in cases where the
134 // type doesn't syntactically appear. This currently excludes only
135 // UnexpandedPack. Even though Instantiation dependence is also notionally
136 // syntactic, we also want to propagate it semantically because anything
137 // that semantically depends on an instantiation-dependent entity should
138 // always be instantiated when that instantiation-dependent entity is.
139 Semantic =
140 Instantiation | Type | Value | Dependent | Error | VariablyModified,
141
142 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
143 };
144
145 Dependence() : V(None) {}
146
147 Dependence(TypeDependence D)
148 : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) |
149 translate(D, TypeDependence::Instantiation, Instantiation) |
150 translate(D, TypeDependence::Dependent, Dependent) |
151 translate(D, TypeDependence::Error, Error) |
152 translate(D, TypeDependence::VariablyModified, VariablyModified)) {}
153
154 Dependence(ExprDependence D)
155 : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) |
156 translate(D, ExprDependence::Instantiation, Instantiation) |
157 translate(D, ExprDependence::Type, Type) |
158 translate(D, ExprDependence::Value, Value) |
159 translate(D, ExprDependence::Error, Error)) {}
160
161 Dependence(NestedNameSpecifierDependence D) :
162 V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) |
163 translate(D, NNSDependence::Instantiation, Instantiation) |
164 translate(D, NNSDependence::Dependent, Dependent) |
165 translate(D, NNSDependence::Error, Error)) {}
166
167 Dependence(TemplateArgumentDependence D)
168 : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) |
169 translate(D, TADependence::Instantiation, Instantiation) |
170 translate(D, TADependence::Dependent, Dependent) |
171 translate(D, TADependence::Error, Error)) {}
172
173 Dependence(TemplateNameDependence D)
174 : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) |
175 translate(D, TNDependence::Instantiation, Instantiation) |
176 translate(D, TNDependence::Dependent, Dependent) |
177 translate(D, TNDependence::Error, Error)) {}
178
179 /// Extract only the syntactic portions of this type's dependence.
180 Dependence syntactic() {
181 Dependence Result = *this;
182 Result.V &= Syntactic;
183 return Result;
184 }
185
186 /// Extract the semantic portions of this type's dependence that apply even
187 /// to uses where the type does not appear syntactically.
188 Dependence semantic() {
189 Dependence Result = *this;
190 Result.V &= Semantic;
191 return Result;
192 }
193
194 TypeDependence type() const {
195 return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
196 translate(V, Instantiation, TypeDependence::Instantiation) |
197 translate(V, Dependent, TypeDependence::Dependent) |
198 translate(V, Error, TypeDependence::Error) |
199 translate(V, VariablyModified, TypeDependence::VariablyModified);
200 }
201
202 ExprDependence expr() const {
203 return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) |
204 translate(V, Instantiation, ExprDependence::Instantiation) |
205 translate(V, Type, ExprDependence::Type) |
206 translate(V, Value, ExprDependence::Value) |
207 translate(V, Error, ExprDependence::Error);
208 }
209
210 NestedNameSpecifierDependence nestedNameSpecifier() const {
211 return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) |
212 translate(V, Instantiation, NNSDependence::Instantiation) |
213 translate(V, Dependent, NNSDependence::Dependent) |
214 translate(V, Error, NNSDependence::Error);
215 }
216
217 TemplateArgumentDependence templateArgument() const {
218 return translate(V, UnexpandedPack, TADependence::UnexpandedPack) |
219 translate(V, Instantiation, TADependence::Instantiation) |
220 translate(V, Dependent, TADependence::Dependent) |
221 translate(V, Error, TADependence::Error);
222 }
223
224 TemplateNameDependence templateName() const {
225 return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) |
226 translate(V, Instantiation, TNDependence::Instantiation) |
227 translate(V, Dependent, TNDependence::Dependent) |
228 translate(V, Error, TNDependence::Error);
229 }
230
231 private:
232 Bits V;
233
234 template <typename T, typename U>
235 static U translate(T Bits, T FromBit, U ToBit) {
236 return (Bits & FromBit) ? ToBit : static_cast<U>(0);
237 }
238
239 // Abbreviations to make conversions more readable.
240 using NNSDependence = NestedNameSpecifierDependence;
241 using TADependence = TemplateArgumentDependence;
242 using TNDependence = TemplateNameDependence;
243 };
244
245 /// Computes dependencies of a reference with the name having template arguments
246 /// with \p TA dependencies.
toExprDependence(TemplateArgumentDependence TA)247 inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
248 return Dependence(TA).expr();
249 }
toExprDependenceForImpliedType(TypeDependence D)250 inline ExprDependence toExprDependenceForImpliedType(TypeDependence D) {
251 return Dependence(D).semantic().expr();
252 }
toExprDependenceAsWritten(TypeDependence D)253 inline ExprDependence toExprDependenceAsWritten(TypeDependence D) {
254 return Dependence(D).expr();
255 }
256 // Note: it's often necessary to strip `Dependent` from qualifiers.
257 // If V<T>:: refers to the current instantiation, NNS is considered dependent
258 // but the containing V<T>::foo likely isn't.
toExprDependence(NestedNameSpecifierDependence D)259 inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
260 return Dependence(D).expr();
261 }
turnTypeToValueDependence(ExprDependence D)262 inline ExprDependence turnTypeToValueDependence(ExprDependence D) {
263 // Type-dependent expressions are always be value-dependent, so we simply drop
264 // type dependency.
265 return D & ~ExprDependence::Type;
266 }
turnValueToTypeDependence(ExprDependence D)267 inline ExprDependence turnValueToTypeDependence(ExprDependence D) {
268 // Type-dependent expressions are always be value-dependent.
269 if (D & ExprDependence::Value)
270 D |= ExprDependence::Type;
271 return D;
272 }
273
274 // Returned type-dependence will never have VariablyModified set.
toTypeDependence(ExprDependence D)275 inline TypeDependence toTypeDependence(ExprDependence D) {
276 return Dependence(D).type();
277 }
toTypeDependence(NestedNameSpecifierDependence D)278 inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
279 return Dependence(D).type();
280 }
toTypeDependence(TemplateNameDependence D)281 inline TypeDependence toTypeDependence(TemplateNameDependence D) {
282 return Dependence(D).type();
283 }
toTypeDependence(TemplateArgumentDependence D)284 inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
285 return Dependence(D).type();
286 }
287
toSyntacticDependence(TypeDependence D)288 inline TypeDependence toSyntacticDependence(TypeDependence D) {
289 return Dependence(D).syntactic().type();
290 }
toSemanticDependence(TypeDependence D)291 inline TypeDependence toSemanticDependence(TypeDependence D) {
292 return Dependence(D).semantic().type();
293 }
294
295 inline NestedNameSpecifierDependence
toNestedNameSpecifierDependendence(TypeDependence D)296 toNestedNameSpecifierDependendence(TypeDependence D) {
297 return Dependence(D).nestedNameSpecifier();
298 }
299
300 inline TemplateArgumentDependence
toTemplateArgumentDependence(TypeDependence D)301 toTemplateArgumentDependence(TypeDependence D) {
302 return Dependence(D).templateArgument();
303 }
304 inline TemplateArgumentDependence
toTemplateArgumentDependence(TemplateNameDependence D)305 toTemplateArgumentDependence(TemplateNameDependence D) {
306 return Dependence(D).templateArgument();
307 }
308 inline TemplateArgumentDependence
toTemplateArgumentDependence(ExprDependence D)309 toTemplateArgumentDependence(ExprDependence D) {
310 return Dependence(D).templateArgument();
311 }
312
313 inline TemplateNameDependence
toTemplateNameDependence(NestedNameSpecifierDependence D)314 toTemplateNameDependence(NestedNameSpecifierDependence D) {
315 return Dependence(D).templateName();
316 }
317
318 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
319
320 } // namespace clang
321 #endif
322