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