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 Instantiation = 2,
20 Type = 4,
21 Value = 8,
22
23 // clang extension: this expr contains or references an error, and is
24 // considered dependent on how that error is resolved.
25 Error = 16,
26
27 None = 0,
28 All = 31,
29
30 TypeValue = Type | Value,
31 TypeInstantiation = Type | Instantiation,
32 ValueInstantiation = Value | Instantiation,
33 TypeValueInstantiation = Type | Value | Instantiation,
34
35 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
36 };
37};
38using ExprDependence = ExprDependenceScope::ExprDependence;
39
40struct TypeDependenceScope {
41 enum TypeDependence : uint8_t {
42 /// Whether this type contains an unexpanded parameter pack
43 /// (for C++11 variadic templates)
44 UnexpandedPack = 1,
45 /// Whether this type somehow involves a template parameter, even
46 /// if the resolution of the type does not depend on a template parameter.
47 Instantiation = 2,
48 /// Whether this type is a dependent type (C++ [temp.dep.type]).
49 Dependent = 4,
50 /// Whether this type is a variably-modified type (C99 6.7.5).
51 VariablyModified = 8,
52
53 /// Whether this type references an error, e.g. decltype(err-expression)
54 /// yields an error type.
55 Error = 16,
56
57 None = 0,
58 All = 31,
59
60 DependentInstantiation = Dependent | Instantiation,
61
62 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
63 };
64};
65using TypeDependence = TypeDependenceScope::TypeDependence;
66
67#define LLVM_COMMON_DEPENDENCE(NAME) \
68 struct NAME##Scope { \
69 enum NAME : uint8_t { \
70 UnexpandedPack = 1, \
71 Instantiation = 2, \
72 Dependent = 4, \
73 \
74 None = 0, \
75 DependentInstantiation = Dependent | Instantiation, \
76 All = 7, \
77 \
78 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Dependent) \
79 }; \
80 }; \
81 using NAME = NAME##Scope::NAME;
82
83LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence)
84LLVM_COMMON_DEPENDENCE(TemplateNameDependence)
85LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
86#undef LLVM_COMMON_DEPENDENCE
87
88// A combined space of all dependence concepts for all node types.
89// Used when aggregating dependence of nodes of different types.
90class Dependence {
91public:
92 enum Bits : uint8_t {
93 None = 0,
94
95 // Contains a template parameter pack that wasn't expanded.
96 UnexpandedPack = 1,
97 // Uses a template parameter, even if it doesn't affect the result.
98 // Validity depends on the template parameter.
99 Instantiation = 2,
100 // Expression type depends on template context.
101 // Value and Instantiation should also be set.
102 Type = 4,
103 // Expression value depends on template context.
104 // Instantiation should also be set.
105 Value = 8,
106 // Depends on template context.
107 // The type/value distinction is only meaningful for expressions.
108 Dependent = Type | Value,
109 // Includes an error, and depends on how it is resolved.
110 Error = 16,
111 // Type depends on a runtime value (variable-length array).
112 VariablyModified = 32,
113
114 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
115 };
116
117 Dependence() : V(None) {}
118
119 Dependence(TypeDependence D)
120 : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) |
121 translate(D, TypeDependence::Instantiation, Instantiation) |
122 translate(D, TypeDependence::Dependent, Dependent) |
123 translate(D, TypeDependence::VariablyModified, VariablyModified)) {
124 }
125
126 Dependence(ExprDependence D)
127 : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) |
128 translate(D, ExprDependence::Instantiation, Instantiation) |
129 translate(D, ExprDependence::Type, Type) |
130 translate(D, ExprDependence::Value, Value) |
131 translate(D, ExprDependence::Error, Error)) {}
132
133 Dependence(NestedNameSpecifierDependence D) :
134 V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) |
135 translate(D, NNSDependence::Instantiation, Instantiation) |
136 translate(D, NNSDependence::Dependent, Dependent)){}
137
138 Dependence(TemplateArgumentDependence D)
139 : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) |
140 translate(D, TADependence::Instantiation, Instantiation) |
141 translate(D, TADependence::Dependent, Dependent)) {}
142
143 Dependence(TemplateNameDependence D)
144 : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) |
145 translate(D, TNDependence::Instantiation, Instantiation) |
146 translate(D, TNDependence::Dependent, Dependent)) {}
147
148 TypeDependence type() const {
149 return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
150 translate(V, Instantiation, TypeDependence::Instantiation) |
151 translate(V, Dependent, TypeDependence::Dependent) |
152 translate(V, Error, TypeDependence::Error) |
153 translate(V, VariablyModified, TypeDependence::VariablyModified);
154 }
155
156 ExprDependence expr() const {
157 return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) |
158 translate(V, Instantiation, ExprDependence::Instantiation) |
159 translate(V, Type, ExprDependence::Type) |
160 translate(V, Value, ExprDependence::Value) |
161 translate(V, Error, ExprDependence::Error);
162 }
163
164 NestedNameSpecifierDependence nestedNameSpecifier() const {
165 return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) |
166 translate(V, Instantiation, NNSDependence::Instantiation) |
167 translate(V, Dependent, NNSDependence::Dependent);
168 }
169
170 TemplateArgumentDependence templateArgument() const {
171 return translate(V, UnexpandedPack, TADependence::UnexpandedPack) |
172 translate(V, Instantiation, TADependence::Instantiation) |
173 translate(V, Dependent, TADependence::Dependent);
174 }
175
176 TemplateNameDependence templateName() const {
177 return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) |
178 translate(V, Instantiation, TNDependence::Instantiation) |
179 translate(V, Dependent, TNDependence::Dependent);
180 }
181
182private:
183 Bits V;
184
185 template <typename T, typename U>
186 static U translate(T Bits, T FromBit, U ToBit) {
187 return (Bits & FromBit) ? ToBit : static_cast<U>(0);
188 }
189
190 // Abbreviations to make conversions more readable.
191 using NNSDependence = NestedNameSpecifierDependence;
192 using TADependence = TemplateArgumentDependence;
193 using TNDependence = TemplateNameDependence;
194};
195
196/// Computes dependencies of a reference with the name having template arguments
197/// with \p TA dependencies.
198inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
199 return Dependence(TA).expr();
200}
201inline ExprDependence toExprDependence(TypeDependence D) {
202 return Dependence(D).expr();
203}
204// Note: it's often necessary to strip `Dependent` from qualifiers.
205// If V<T>:: refers to the current instantiation, NNS is considered dependent
206// but the containing V<T>::foo likely isn't.
207inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
208 return Dependence(D).expr();
209}
210inline ExprDependence turnTypeToValueDependence(ExprDependence D) {
211 // Type-dependent expressions are always be value-dependent, so we simply drop
212 // type dependency.
213 return D & ~ExprDependence::Type;
214}
215inline ExprDependence turnValueToTypeDependence(ExprDependence D) {
216 // Type-dependent expressions are always be value-dependent.
217 if (D & ExprDependence::Value)
218 D |= ExprDependence::Type;
219 return D;
220}
221
222// Returned type-dependence will never have VariablyModified set.
223inline TypeDependence toTypeDependence(ExprDependence D) {
224 return Dependence(D).type();
225}
226inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
227 return Dependence(D).type();
228}
229inline TypeDependence toTypeDependence(TemplateNameDependence D) {
230 return Dependence(D).type();
231}
232inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
233 return Dependence(D).type();
234}
235
236inline NestedNameSpecifierDependence
237toNestedNameSpecifierDependendence(TypeDependence D) {
238 return Dependence(D).nestedNameSpecifier();
239}
240
241inline TemplateArgumentDependence
242toTemplateArgumentDependence(TypeDependence D) {
243 return Dependence(D).templateArgument();
244}
245inline TemplateArgumentDependence
246toTemplateArgumentDependence(TemplateNameDependence D) {
247 return Dependence(D).templateArgument();
248}
249inline TemplateArgumentDependence
250toTemplateArgumentDependence(ExprDependence D) {
251 return Dependence(D).templateArgument();
252}
253
254inline TemplateNameDependence
255toTemplateNameDependence(NestedNameSpecifierDependence D) {
256 return Dependence(D).templateName();
257}
258
259LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
260
261} // namespace clang
262#endif
263