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