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
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
215private:
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.
231inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
232 return Dependence(TA).expr();
233}
234inline 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.
240inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
241 return Dependence(D).expr();
242}
243inline 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}
248inline 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.
256inline TypeDependence toTypeDependence(ExprDependence D) {
257 return Dependence(D).type();
258}
259inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
260 return Dependence(D).type();
261}
262inline TypeDependence toTypeDependence(TemplateNameDependence D) {
263 return Dependence(D).type();
264}
265inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
266 return Dependence(D).type();
267}
268
269inline TypeDependence toSyntacticDependence(TypeDependence D) {
270 return Dependence(D).syntactic().type();
271}
272
273inline NestedNameSpecifierDependence
274toNestedNameSpecifierDependendence(TypeDependence D) {
275 return Dependence(D).nestedNameSpecifier();
276}
277
278inline TemplateArgumentDependence
279toTemplateArgumentDependence(TypeDependence D) {
280 return Dependence(D).templateArgument();
281}
282inline TemplateArgumentDependence
283toTemplateArgumentDependence(TemplateNameDependence D) {
284 return Dependence(D).templateArgument();
285}
286inline TemplateArgumentDependence
287toTemplateArgumentDependence(ExprDependence D) {
288 return Dependence(D).templateArgument();
289}
290
291inline TemplateNameDependence
292toTemplateNameDependence(NestedNameSpecifierDependence D) {
293 return Dependence(D).templateName();
294}
295
296LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
297
298} // namespace clang
299#endif
300