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 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
132 };
133
134 Dependence() : V(None) {}
135
136 Dependence(TypeDependence D)
137 : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) |
138 translate(D, TypeDependence::Instantiation, Instantiation) |
139 translate(D, TypeDependence::Dependent, Dependent) |
140 translate(D, TypeDependence::Error, Error) |
141 translate(D, TypeDependence::VariablyModified, VariablyModified)) {}
142
143 Dependence(ExprDependence D)
144 : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) |
145 translate(D, ExprDependence::Instantiation, Instantiation) |
146 translate(D, ExprDependence::Type, Type) |
147 translate(D, ExprDependence::Value, Value) |
148 translate(D, ExprDependence::Error, Error)) {}
149
150 Dependence(NestedNameSpecifierDependence D) :
151 V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) |
152 translate(D, NNSDependence::Instantiation, Instantiation) |
153 translate(D, NNSDependence::Dependent, Dependent) |
154 translate(D, NNSDependence::Error, Error)) {}
155
156 Dependence(TemplateArgumentDependence D)
157 : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) |
158 translate(D, TADependence::Instantiation, Instantiation) |
159 translate(D, TADependence::Dependent, Dependent) |
160 translate(D, TADependence::Error, Error)) {}
161
162 Dependence(TemplateNameDependence D)
163 : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) |
164 translate(D, TNDependence::Instantiation, Instantiation) |
165 translate(D, TNDependence::Dependent, Dependent) |
166 translate(D, TNDependence::Error, Error)) {}
167
168 TypeDependence type() const {
169 return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
170 translate(V, Instantiation, TypeDependence::Instantiation) |
171 translate(V, Dependent, TypeDependence::Dependent) |
172 translate(V, Error, TypeDependence::Error) |
173 translate(V, VariablyModified, TypeDependence::VariablyModified);
174 }
175
176 ExprDependence expr() const {
177 return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) |
178 translate(V, Instantiation, ExprDependence::Instantiation) |
179 translate(V, Type, ExprDependence::Type) |
180 translate(V, Value, ExprDependence::Value) |
181 translate(V, Error, ExprDependence::Error);
182 }
183
184 NestedNameSpecifierDependence nestedNameSpecifier() const {
185 return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) |
186 translate(V, Instantiation, NNSDependence::Instantiation) |
187 translate(V, Dependent, NNSDependence::Dependent) |
188 translate(V, Error, NNSDependence::Error);
189 }
190
191 TemplateArgumentDependence templateArgument() const {
192 return translate(V, UnexpandedPack, TADependence::UnexpandedPack) |
193 translate(V, Instantiation, TADependence::Instantiation) |
194 translate(V, Dependent, TADependence::Dependent) |
195 translate(V, Error, TADependence::Error);
196 }
197
198 TemplateNameDependence templateName() const {
199 return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) |
200 translate(V, Instantiation, TNDependence::Instantiation) |
201 translate(V, Dependent, TNDependence::Dependent) |
202 translate(V, Error, TNDependence::Error);
203 }
204
205 private:
206 Bits V;
207
208 template <typename T, typename U>
209 static U translate(T Bits, T FromBit, U ToBit) {
210 return (Bits & FromBit) ? ToBit : static_cast<U>(0);
211 }
212
213 // Abbreviations to make conversions more readable.
214 using NNSDependence = NestedNameSpecifierDependence;
215 using TADependence = TemplateArgumentDependence;
216 using TNDependence = TemplateNameDependence;
217 };
218
219 /// Computes dependencies of a reference with the name having template arguments
220 /// with \p TA dependencies.
toExprDependence(TemplateArgumentDependence TA)221 inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
222 return Dependence(TA).expr();
223 }
toExprDependence(TypeDependence D)224 inline ExprDependence toExprDependence(TypeDependence D) {
225 return Dependence(D).expr();
226 }
227 // Note: it's often necessary to strip `Dependent` from qualifiers.
228 // If V<T>:: refers to the current instantiation, NNS is considered dependent
229 // but the containing V<T>::foo likely isn't.
toExprDependence(NestedNameSpecifierDependence D)230 inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
231 return Dependence(D).expr();
232 }
turnTypeToValueDependence(ExprDependence D)233 inline ExprDependence turnTypeToValueDependence(ExprDependence D) {
234 // Type-dependent expressions are always be value-dependent, so we simply drop
235 // type dependency.
236 return D & ~ExprDependence::Type;
237 }
turnValueToTypeDependence(ExprDependence D)238 inline ExprDependence turnValueToTypeDependence(ExprDependence D) {
239 // Type-dependent expressions are always be value-dependent.
240 if (D & ExprDependence::Value)
241 D |= ExprDependence::Type;
242 return D;
243 }
244
245 // Returned type-dependence will never have VariablyModified set.
toTypeDependence(ExprDependence D)246 inline TypeDependence toTypeDependence(ExprDependence D) {
247 return Dependence(D).type();
248 }
toTypeDependence(NestedNameSpecifierDependence D)249 inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
250 return Dependence(D).type();
251 }
toTypeDependence(TemplateNameDependence D)252 inline TypeDependence toTypeDependence(TemplateNameDependence D) {
253 return Dependence(D).type();
254 }
toTypeDependence(TemplateArgumentDependence D)255 inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
256 return Dependence(D).type();
257 }
258
259 inline NestedNameSpecifierDependence
toNestedNameSpecifierDependendence(TypeDependence D)260 toNestedNameSpecifierDependendence(TypeDependence D) {
261 return Dependence(D).nestedNameSpecifier();
262 }
263
264 inline TemplateArgumentDependence
toTemplateArgumentDependence(TypeDependence D)265 toTemplateArgumentDependence(TypeDependence D) {
266 return Dependence(D).templateArgument();
267 }
268 inline TemplateArgumentDependence
toTemplateArgumentDependence(TemplateNameDependence D)269 toTemplateArgumentDependence(TemplateNameDependence D) {
270 return Dependence(D).templateArgument();
271 }
272 inline TemplateArgumentDependence
toTemplateArgumentDependence(ExprDependence D)273 toTemplateArgumentDependence(ExprDependence D) {
274 return Dependence(D).templateArgument();
275 }
276
277 inline TemplateNameDependence
toTemplateNameDependence(NestedNameSpecifierDependence D)278 toTemplateNameDependence(NestedNameSpecifierDependence D) {
279 return Dependence(D).templateName();
280 }
281
282 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
283
284 } // namespace clang
285 #endif
286