LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
#undef LLVM_COMMON_DEPENDENCE
+// A combined space of all dependence concepts for all node types.
+// Used when aggregating dependence of nodes of different types.
+class Dependence {
+public:
+ enum Bits : uint8_t {
+ None = 0,
+
+ // Contains a template parameter pack that wasn't expanded.
+ UnexpandedPack = 1,
+ // Uses a template parameter, even if it doesn't affect the result.
+ // Validity depends on the template parameter.
+ Instantiation = 2,
+ // Expression type depends on template context.
+ // Value and Instantiation should also be set.
+ Type = 4,
+ // Expression value depends on template context.
+ // Instantiation should also be set.
+ Value = 8,
+ // Depends on template context.
+ // The type/value distinction is only meaningful for expressions.
+ Dependent = Type | Value,
+ // Includes an error, and depends on how it is resolved.
+ Error = 16,
+ // Type depends on a runtime value (variable-length array).
+ VariablyModified = 32,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
+ };
+
+ Dependence() : V(None) {}
+
+ Dependence(TypeDependence D)
+ : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, TypeDependence::Instantiation, Instantiation) |
+ translate(D, TypeDependence::Dependent, Dependent) |
+ translate(D, TypeDependence::VariablyModified, VariablyModified)) {
+ }
+
+ Dependence(ExprDependence D)
+ : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, ExprDependence::Instantiation, Instantiation) |
+ translate(D, ExprDependence::Type, Type) |
+ translate(D, ExprDependence::Value, Value) |
+ translate(D, ExprDependence::Error, Error)) {}
+
+ Dependence(NestedNameSpecifierDependence D) :
+ V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, NNSDependence::Instantiation, Instantiation) |
+ translate(D, NNSDependence::Dependent, Dependent)){}
+
+ Dependence(TemplateArgumentDependence D)
+ : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, TADependence::Instantiation, Instantiation) |
+ translate(D, TADependence::Dependent, Dependent)) {}
+
+ Dependence(TemplateNameDependence D)
+ : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, TNDependence::Instantiation, Instantiation) |
+ translate(D, TNDependence::Dependent, Dependent)) {}
+
+ TypeDependence type() const {
+ return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
+ translate(V, Instantiation, TypeDependence::Instantiation) |
+ translate(V, Dependent, TypeDependence::Dependent) |
+ translate(V, VariablyModified, TypeDependence::VariablyModified);
+ }
+
+ ExprDependence expr() const {
+ return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) |
+ translate(V, Instantiation, ExprDependence::Instantiation) |
+ translate(V, Type, ExprDependence::Type) |
+ translate(V, Value, ExprDependence::Value) |
+ translate(V, Error, ExprDependence::Error);
+ }
+
+ NestedNameSpecifierDependence nestedNameSpecifier() const {
+ return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) |
+ translate(V, Instantiation, NNSDependence::Instantiation) |
+ translate(V, Dependent, NNSDependence::Dependent);
+ }
+
+ TemplateArgumentDependence templateArgument() const {
+ return translate(V, UnexpandedPack, TADependence::UnexpandedPack) |
+ translate(V, Instantiation, TADependence::Instantiation) |
+ translate(V, Dependent, TADependence::Dependent);
+ }
+
+ TemplateNameDependence templateName() const {
+ return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) |
+ translate(V, Instantiation, TNDependence::Instantiation) |
+ translate(V, Dependent, TNDependence::Dependent);
+ }
+
+private:
+ Bits V;
+
+ template <typename T, typename U>
+ static U translate(T Bits, T FromBit, U ToBit) {
+ return (Bits & FromBit) ? ToBit : static_cast<U>(0);
+ }
+
+ // Abbreviations to make conversions more readable.
+ using NNSDependence = NestedNameSpecifierDependence;
+ using TADependence = TemplateArgumentDependence;
+ using TNDependence = TemplateNameDependence;
+};
+
/// Computes dependencies of a reference with the name having template arguments
/// with \p TA dependencies.
inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
- auto D = ExprDependence::None;
- if (TA & TemplateArgumentDependence::UnexpandedPack)
- D |= ExprDependence::UnexpandedPack;
- if (TA & TemplateArgumentDependence::Instantiation)
- D |= ExprDependence::Instantiation;
- if (TA & TemplateArgumentDependence::Dependent)
- D |= ExprDependence::Type | ExprDependence::Value;
- return D;
+ return Dependence(TA).expr();
}
-inline ExprDependence toExprDependence(TypeDependence TD) {
- // This hack works because TypeDependence and TemplateArgumentDependence
- // share the same bit representation, apart from variably-modified.
- return toExprDependence(static_cast<TemplateArgumentDependence>(
- TD & ~TypeDependence::VariablyModified));
+inline ExprDependence toExprDependence(TypeDependence D) {
+ return Dependence(D).expr();
}
-inline ExprDependence toExprDependence(NestedNameSpecifierDependence NSD) {
- // This hack works because TypeDependence and TemplateArgumentDependence
- // share the same bit representation.
- return toExprDependence(static_cast<TemplateArgumentDependence>(NSD)) &
- ~ExprDependence::TypeValue;
+// Note: it's often necessary to strip `Dependent` from qualifiers.
+// If V<T>:: refers to the current instantiation, NNS is considered dependent
+// but the containing V<T>::foo likely isn't.
+inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
+ return Dependence(D).expr();
}
inline ExprDependence turnTypeToValueDependence(ExprDependence D) {
// Type-dependent expressions are always be value-dependent, so we simply drop
// Returned type-dependence will never have VariablyModified set.
inline TypeDependence toTypeDependence(ExprDependence D) {
- // Supported bits all have the same representation.
- return static_cast<TypeDependence>(D & (ExprDependence::UnexpandedPack |
- ExprDependence::Instantiation |
- ExprDependence::Type));
+ return Dependence(D).type();
}
inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
- // Supported bits all have the same representation.
- return static_cast<TypeDependence>(D);
+ return Dependence(D).type();
}
inline TypeDependence toTypeDependence(TemplateNameDependence D) {
- // Supported bits all have the same representation.
- return static_cast<TypeDependence>(D);
+ return Dependence(D).type();
}
inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
- // Supported bits all have the same representation.
- return static_cast<TypeDependence>(D);
+ return Dependence(D).type();
}
inline NestedNameSpecifierDependence
toNestedNameSpecifierDependendence(TypeDependence D) {
- // This works because both classes share the same bit representation.
- return static_cast<NestedNameSpecifierDependence>(
- D & ~TypeDependence::VariablyModified);
+ return Dependence(D).nestedNameSpecifier();
}
inline TemplateArgumentDependence
toTemplateArgumentDependence(TypeDependence D) {
- // This works because both classes share the same bit representation.
- return static_cast<TemplateArgumentDependence>(
- D & ~TypeDependence::VariablyModified);
+ return Dependence(D).templateArgument();
}
inline TemplateArgumentDependence
toTemplateArgumentDependence(TemplateNameDependence D) {
- // This works because both classes share the same bit representation.
- return static_cast<TemplateArgumentDependence>(D);
+ return Dependence(D).templateArgument();
}
inline TemplateArgumentDependence
-toTemplateArgumentDependence(ExprDependence ED) {
- TemplateArgumentDependence TAD = TemplateArgumentDependence::None;
- if (ED & (ExprDependence::Type | ExprDependence::Value))
- TAD |= TemplateArgumentDependence::Dependent;
- if (ED & ExprDependence::Instantiation)
- TAD |= TemplateArgumentDependence::Instantiation;
- if (ED & ExprDependence::UnexpandedPack)
- TAD |= TemplateArgumentDependence::UnexpandedPack;
- return TAD;
+toTemplateArgumentDependence(ExprDependence D) {
+ return Dependence(D).templateArgument();
}
inline TemplateNameDependence
toTemplateNameDependence(NestedNameSpecifierDependence D) {
- return static_cast<TemplateNameDependence>(D);
+ return Dependence(D).templateName();
}
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();