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