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