[clang] d68c09a - [AST] Add a Dependence bitmask to use for calculations with multiple node types.
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 27 16:16:22 PDT 2020
Author: Sam McCall
Date: 2020-03-28T00:15:50+01:00
New Revision: d68c09ac87959694fbb4895ff49443afc2b582f9
URL: https://github.com/llvm/llvm-project/commit/d68c09ac87959694fbb4895ff49443afc2b582f9
DIFF: https://github.com/llvm/llvm-project/commit/d68c09ac87959694fbb4895ff49443afc2b582f9.diff
LOG: [AST] Add a Dependence bitmask to use for calculations with multiple node types.
Summary:
This makes it easier/safer to add bits (error) to other node types without
worrying about bit layout all the time.
For now, just use to implement the ad-hoc conversion functions.
Next: remove these functions and use this directly.
Reviewers: hokein
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76939
Added:
Modified:
clang/include/clang/AST/DependenceFlags.h
clang/lib/AST/ComputeDependence.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h
index c92b22220c65..75c9aa1656b8 100644
--- a/clang/include/clang/AST/DependenceFlags.h
+++ b/clang/include/clang/AST/DependenceFlags.h
@@ -83,29 +83,126 @@ LLVM_COMMON_DEPENDENCE(TemplateNameDependence)
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
diff erent 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
@@ -121,57 +218,39 @@ inline ExprDependence turnValueToTypeDependence(ExprDependence D) {
// 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();
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index 2db3a6e94615..b51164e54926 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -370,7 +370,8 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
auto Deps = ExprDependence::None;
if (auto *NNS = E->getQualifier())
- Deps |= toExprDependence(NNS->getDependence());
+ Deps |= toExprDependence(NNS->getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
if (auto *FirstArg = E->getTemplateArgs()) {
unsigned NumArgs = E->getNumTemplateArgs();
@@ -590,7 +591,8 @@ ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
D |= turnTypeToValueDependence(
toExprDependence(ST->getType()->getDependence()));
if (auto *Q = E->getQualifier())
- D |= toExprDependence(Q->getDependence());
+ D |= toExprDependence(Q->getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
return D;
}
@@ -616,7 +618,8 @@ clang::computeDependence(OverloadExpr *E, bool KnownDependent,
Deps |= ExprDependence::UnexpandedPack;
Deps |= getDependenceInExpr(E->getNameInfo());
if (auto *Q = E->getQualifier())
- Deps |= toExprDependence(Q->getDependence());
+ Deps |= toExprDependence(Q->getDependence() &
+ ~NestedNameSpecifierDependence::Dependent);
for (auto *D : E->decls()) {
if (D->getDeclContext()->isDependentContext() ||
isa<UnresolvedUsingValueDecl>(D))
More information about the cfe-commits
mailing list