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
15namespace clang {
16struct 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};
49using ExprDependence = ExprDependenceScope::ExprDependence;
50
51struct 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};
80using 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
99LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence)
100LLVM_COMMON_DEPENDENCE(TemplateNameDependence)
101LLVM_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.
106class Dependence {
107public:
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(Bits: D, FromBit: TypeDependence::UnexpandedPack, ToBit: UnexpandedPack) |
149 translate(Bits: D, FromBit: TypeDependence::Instantiation, ToBit: Instantiation) |
150 translate(Bits: D, FromBit: TypeDependence::Dependent, ToBit: Dependent) |
151 translate(Bits: D, FromBit: TypeDependence::Error, ToBit: Error) |
152 translate(Bits: D, FromBit: TypeDependence::VariablyModified, ToBit: VariablyModified)) {}
153
154 Dependence(ExprDependence D)
155 : V(translate(Bits: D, FromBit: ExprDependence::UnexpandedPack, ToBit: UnexpandedPack) |
156 translate(Bits: D, FromBit: ExprDependence::Instantiation, ToBit: Instantiation) |
157 translate(Bits: D, FromBit: ExprDependence::Type, ToBit: Type) |
158 translate(Bits: D, FromBit: ExprDependence::Value, ToBit: Value) |
159 translate(Bits: D, FromBit: ExprDependence::Error, ToBit: Error)) {}
160
161 Dependence(NestedNameSpecifierDependence D) :
162 V ( translate(Bits: D, FromBit: NNSDependence::UnexpandedPack, ToBit: UnexpandedPack) |
163 translate(Bits: D, FromBit: NNSDependence::Instantiation, ToBit: Instantiation) |
164 translate(Bits: D, FromBit: NNSDependence::Dependent, ToBit: Dependent) |
165 translate(Bits: D, FromBit: NNSDependence::Error, ToBit: Error)) {}
166
167 Dependence(TemplateArgumentDependence D)
168 : V(translate(Bits: D, FromBit: TADependence::UnexpandedPack, ToBit: UnexpandedPack) |
169 translate(Bits: D, FromBit: TADependence::Instantiation, ToBit: Instantiation) |
170 translate(Bits: D, FromBit: TADependence::Dependent, ToBit: Dependent) |
171 translate(Bits: D, FromBit: TADependence::Error, ToBit: Error)) {}
172
173 Dependence(TemplateNameDependence D)
174 : V(translate(Bits: D, FromBit: TNDependence::UnexpandedPack, ToBit: UnexpandedPack) |
175 translate(Bits: D, FromBit: TNDependence::Instantiation, ToBit: Instantiation) |
176 translate(Bits: D, FromBit: TNDependence::Dependent, ToBit: Dependent) |
177 translate(Bits: D, FromBit: TNDependence::Error, ToBit: 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(Bits: V, FromBit: UnexpandedPack, ToBit: TypeDependence::UnexpandedPack) |
196 translate(Bits: V, FromBit: Instantiation, ToBit: TypeDependence::Instantiation) |
197 translate(Bits: V, FromBit: Dependent, ToBit: TypeDependence::Dependent) |
198 translate(Bits: V, FromBit: Error, ToBit: TypeDependence::Error) |
199 translate(Bits: V, FromBit: VariablyModified, ToBit: TypeDependence::VariablyModified);
200 }
201
202 ExprDependence expr() const {
203 return translate(Bits: V, FromBit: UnexpandedPack, ToBit: ExprDependence::UnexpandedPack) |
204 translate(Bits: V, FromBit: Instantiation, ToBit: ExprDependence::Instantiation) |
205 translate(Bits: V, FromBit: Type, ToBit: ExprDependence::Type) |
206 translate(Bits: V, FromBit: Value, ToBit: ExprDependence::Value) |
207 translate(Bits: V, FromBit: Error, ToBit: ExprDependence::Error);
208 }
209
210 NestedNameSpecifierDependence nestedNameSpecifier() const {
211 return translate(Bits: V, FromBit: UnexpandedPack, ToBit: NNSDependence::UnexpandedPack) |
212 translate(Bits: V, FromBit: Instantiation, ToBit: NNSDependence::Instantiation) |
213 translate(Bits: V, FromBit: Dependent, ToBit: NNSDependence::Dependent) |
214 translate(Bits: V, FromBit: Error, ToBit: NNSDependence::Error);
215 }
216
217 TemplateArgumentDependence templateArgument() const {
218 return translate(Bits: V, FromBit: UnexpandedPack, ToBit: TADependence::UnexpandedPack) |
219 translate(Bits: V, FromBit: Instantiation, ToBit: TADependence::Instantiation) |
220 translate(Bits: V, FromBit: Dependent, ToBit: TADependence::Dependent) |
221 translate(Bits: V, FromBit: Error, ToBit: TADependence::Error);
222 }
223
224 TemplateNameDependence templateName() const {
225 return translate(Bits: V, FromBit: UnexpandedPack, ToBit: TNDependence::UnexpandedPack) |
226 translate(Bits: V, FromBit: Instantiation, ToBit: TNDependence::Instantiation) |
227 translate(Bits: V, FromBit: Dependent, ToBit: TNDependence::Dependent) |
228 translate(Bits: V, FromBit: Error, ToBit: TNDependence::Error);
229 }
230
231private:
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.
247inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
248 return Dependence(TA).expr();
249}
250inline ExprDependence toExprDependenceForImpliedType(TypeDependence D) {
251 return Dependence(D).semantic().expr();
252}
253inline 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.
259inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
260 return Dependence(D).expr();
261}
262inline 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}
267inline 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.
275inline TypeDependence toTypeDependence(ExprDependence D) {
276 return Dependence(D).type();
277}
278inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
279 return Dependence(D).type();
280}
281inline TypeDependence toTypeDependence(TemplateNameDependence D) {
282 return Dependence(D).type();
283}
284inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
285 return Dependence(D).type();
286}
287
288inline TypeDependence toSyntacticDependence(TypeDependence D) {
289 return Dependence(D).syntactic().type();
290}
291inline TypeDependence toSemanticDependence(TypeDependence D) {
292 return Dependence(D).semantic().type();
293}
294
295inline NestedNameSpecifierDependence
296toNestedNameSpecifierDependendence(TypeDependence D) {
297 return Dependence(D).nestedNameSpecifier();
298}
299
300inline TemplateArgumentDependence
301toTemplateArgumentDependence(TypeDependence D) {
302 return Dependence(D).templateArgument();
303}
304inline TemplateArgumentDependence
305toTemplateArgumentDependence(TemplateNameDependence D) {
306 return Dependence(D).templateArgument();
307}
308inline TemplateArgumentDependence
309toTemplateArgumentDependence(ExprDependence D) {
310 return Dependence(D).templateArgument();
311}
312
313inline TemplateNameDependence
314toTemplateNameDependence(NestedNameSpecifierDependence D) {
315 return Dependence(D).templateName();
316}
317
318LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
319
320} // namespace clang
321#endif
322

source code of clang/include/clang/AST/DependenceFlags.h