[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