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
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.
toExprDependence(TemplateArgumentDependence TA)231 inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
232 return Dependence(TA).expr();
233 }
toExprDependence(TypeDependence D)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.
toExprDependence(NestedNameSpecifierDependence D)240 inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
241 return Dependence(D).expr();
242 }
turnTypeToValueDependence(ExprDependence D)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 }
turnValueToTypeDependence(ExprDependence D)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.
toTypeDependence(ExprDependence D)256 inline TypeDependence toTypeDependence(ExprDependence D) {
257 return Dependence(D).type();
258 }
toTypeDependence(NestedNameSpecifierDependence D)259 inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
260 return Dependence(D).type();
261 }
toTypeDependence(TemplateNameDependence D)262 inline TypeDependence toTypeDependence(TemplateNameDependence D) {
263 return Dependence(D).type();
264 }
toTypeDependence(TemplateArgumentDependence D)265 inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
266 return Dependence(D).type();
267 }
268
toSyntacticDependence(TypeDependence D)269 inline TypeDependence toSyntacticDependence(TypeDependence D) {
270 return Dependence(D).syntactic().type();
271 }
272
273 inline NestedNameSpecifierDependence
toNestedNameSpecifierDependendence(TypeDependence D)274 toNestedNameSpecifierDependendence(TypeDependence D) {
275 return Dependence(D).nestedNameSpecifier();
276 }
277
278 inline TemplateArgumentDependence
toTemplateArgumentDependence(TypeDependence D)279 toTemplateArgumentDependence(TypeDependence D) {
280 return Dependence(D).templateArgument();
281 }
282 inline TemplateArgumentDependence
toTemplateArgumentDependence(TemplateNameDependence D)283 toTemplateArgumentDependence(TemplateNameDependence D) {
284 return Dependence(D).templateArgument();
285 }
286 inline TemplateArgumentDependence
toTemplateArgumentDependence(ExprDependence D)287 toTemplateArgumentDependence(ExprDependence D) {
288 return Dependence(D).templateArgument();
289 }
290
291 inline TemplateNameDependence
toTemplateNameDependence(NestedNameSpecifierDependence D)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