Commit ec3060c7 authored by Ilya Biryukov's avatar Ilya Biryukov Committed by Haojian Wu
Browse files

[AST] Refactor propagation of dependency bits. NFC

Summary:
This changes introduces an enum to represent dependencies as a bitmask
and extract common patterns from code that computes dependency bits into
helper functions.

Reviewers: rsmith, martong, shafik, ilya-biryukov, hokein

Subscribers: hokein, sammccall, Mordante, riccibruno, merge_guards_bot, rnkovacs, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D71920
parent 670a4036
Loading
Loading
Loading
Loading
+138 −0
Original line number Diff line number Diff line
//===--- DependencyFlags.h ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DEPENDENCYFLAGS_H
#define LLVM_CLANG_AST_DEPENDENCYFLAGS_H

#include "clang/Basic/BitmaskEnum.h"
#include "llvm/ADT/BitmaskEnum.h"
#include <cstdint>

namespace clang {
struct ExprDependenceScope {
  enum ExprDependence : uint8_t {
    UnexpandedPack = 1,
    Instantiation = 2,
    Type = 4,
    Value = 8,

    None = 0,
    All = 15,

    TypeInstantiation = Type | Instantiation,
    ValueInstantiation = Value | Instantiation,
    TypeValueInstantiation = Type | Value | Instantiation,

    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Value)
  };
};
using ExprDependence = ExprDependenceScope::ExprDependence;
static constexpr unsigned ExprDependenceBits = 4;

struct TypeDependenceScope {
  enum TypeDependence : uint8_t {
    /// Whether this type contains an unexpanded parameter pack
    /// (for C++11 variadic templates)
    UnexpandedPack = 1,
    /// Whether this type somehow involves a template parameter, even
    /// if the resolution of the type does not depend on a template parameter.
    Instantiation = 2,
    /// Whether this type is a dependent type (C++ [temp.dep.type]).
    Dependent = 4,
    /// Whether this type is a variably-modified type (C99 6.7.5).
    VariablyModified = 8,

    None = 0,
    All = 15,

    DependentInstantiation = Dependent | Instantiation,

    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
  };
};
using TypeDependence = TypeDependenceScope::TypeDependence;
static constexpr unsigned TypeDependenceBits = 4;

#define LLVM_COMMON_DEPENDENCE(NAME)                                           \
  struct NAME##Scope {                                                         \
    enum NAME : uint8_t {                                                      \
      UnexpandedPack = 1,                                                      \
      Instantiation = 2,                                                       \
      Dependent = 4,                                                           \
                                                                               \
      None = 0,                                                                \
      DependentInstantiation = Dependent | Instantiation,                      \
      All = 7,                                                                 \
                                                                               \
      LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Dependent)                    \
    };                                                                         \
  };                                                                           \
  using NAME = NAME##Scope::NAME;                                              \
  static constexpr unsigned NAME##Bits = 3;

LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence)
LLVM_COMMON_DEPENDENCE(TemplateNameDependence)
LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
#undef LLVM_COMMON_DEPENDENCE

/// Computes dependencies of a reference with the name having template arguments
/// with \p TA dependencies.
inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
  auto E =
      static_cast<ExprDependence>(TA & ~TemplateArgumentDependence::Dependent);
  if (TA & TemplateArgumentDependence::Dependent)
    return E | ExprDependence::Type | ExprDependence::Value;
  return E;
}
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 turnTypeToValueDependence(ExprDependence D) {
  // Type-dependent expressions are always be value-dependent, so we simply drop
  // type dependency.
  return D & ~ExprDependence::Type;
}

inline NestedNameSpecifierDependence
toNestedNameSpecifierDependendence(TypeDependence D) {
  // This works because both classes share the same bit representation.
  return static_cast<NestedNameSpecifierDependence>(
      D & ~TypeDependence::VariablyModified);
}

inline TemplateArgumentDependence
toTemplateArgumentDependence(TypeDependence D) {
  // This works because both classes share the same bit representation.
  return static_cast<TemplateArgumentDependence>(
      D & ~TypeDependence::VariablyModified);
}
inline TemplateArgumentDependence
toTemplateArgumentDependence(TemplateNameDependence D) {
  // This works because both classes share the same bit representation.
  return static_cast<TemplateArgumentDependence>(D);
}
inline TemplateArgumentDependence
toTemplateArgumentDependence(ExprDependence ED) {
  TemplateArgumentDependence TAD = static_cast<TemplateArgumentDependence>(
      ED & ~(ExprDependence::Type | ExprDependence::Value));
  if (ED & (ExprDependence::Type | ExprDependence::Value))
    TAD |= TemplateArgumentDependence::Dependent;
  return TAD;
}

inline TemplateNameDependence
toTemplateNameDependence(NestedNameSpecifierDependence D) {
  return static_cast<TemplateNameDependence>(D);
}

LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();

} // namespace clang
#endif
+36 −42
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "clang/AST/ASTVector.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DependencyFlags.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
@@ -28,10 +29,10 @@
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
@@ -120,13 +121,20 @@ protected:
       bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
    : ValueStmt(SC)
  {
    ExprBits.TypeDependent = TD;
    ExprBits.ValueDependent = VD;
    ExprBits.InstantiationDependent = ID;
    auto D = ExprDependence::None;
    if (TD)
      D |= ExprDependence::Type;
    if (VD)
      D |= ExprDependence::Value;
    if (ID)
      D |= ExprDependence::Instantiation;
    if (ContainsUnexpandedParameterPack)
      D |= ExprDependence::UnexpandedPack;

    ExprBits.Dependent = static_cast<unsigned>(D);
    ExprBits.ValueKind = VK;
    ExprBits.ObjectKind = OK;
    assert(ExprBits.ObjectKind == OK && "truncated kind");
    ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
    setType(T);
  }

@@ -148,6 +156,20 @@ public:
    TR = t;
  }

  ExprDependence getDependence() const {
    return static_cast<ExprDependence>(ExprBits.Dependent);
  }

  void setDependence(ExprDependence Deps) {
    ExprBits.Dependent = static_cast<unsigned>(Deps);
  }
  void addDependence(ExprDependence Deps) {
    ExprBits.Dependent |= static_cast<unsigned>(Deps);
  }
  void removeDependence(ExprDependence Deps) {
    ExprBits.Dependent &= ~static_cast<unsigned>(Deps);
  }

  /// isValueDependent - Determines whether this expression is
  /// value-dependent (C++ [temp.dep.constexpr]). For example, the
  /// array bound of "Chars" in the following example is
@@ -155,11 +177,8 @@ public:
  /// @code
  /// template<int Size, char (&Chars)[Size]> struct meta_string;
  /// @endcode
  bool isValueDependent() const { return ExprBits.ValueDependent; }

  /// Set whether this expression is value-dependent or not.
  void setValueDependent(bool VD) {
    ExprBits.ValueDependent = VD;
  bool isValueDependent() const {
    return static_cast<bool>(getDependence() & ExprDependence::Value);
  }

  /// isTypeDependent - Determines whether this expression is
@@ -173,11 +192,8 @@ public:
  ///   x + y;
  /// }
  /// @endcode
  bool isTypeDependent() const { return ExprBits.TypeDependent; }

  /// Set whether this expression is type-dependent or not.
  void setTypeDependent(bool TD) {
    ExprBits.TypeDependent = TD;
  bool isTypeDependent() const {
    return static_cast<bool>(getDependence() & ExprDependence::Type);
  }

  /// Whether this expression is instantiation-dependent, meaning that
@@ -198,12 +214,7 @@ public:
  /// \endcode
  ///
  bool isInstantiationDependent() const {
    return ExprBits.InstantiationDependent;
  }

  /// Set whether this expression is instantiation-dependent or not.
  void setInstantiationDependent(bool ID) {
    ExprBits.InstantiationDependent = ID;
    return static_cast<bool>(getDependence() & ExprDependence::Instantiation);
  }

  /// Whether this expression contains an unexpanded parameter
@@ -221,13 +232,7 @@ public:
  /// The expressions \c args and \c static_cast<Types&&>(args) both
  /// contain parameter packs.
  bool containsUnexpandedParameterPack() const {
    return ExprBits.ContainsUnexpandedParameterPack;
  }

  /// Set the bit that describes whether this expression
  /// contains an unexpanded parameter pack.
  void setContainsUnexpandedParameterPack(bool PP = true) {
    ExprBits.ContainsUnexpandedParameterPack = PP;
    return static_cast<bool>(getDependence() & ExprDependence::UnexpandedPack);
  }

  /// getExprLoc - Return the preferred location for the arrow when diagnosing
@@ -1215,10 +1220,6 @@ class DeclRefExpr final
  /// Construct an empty declaration reference expression.
  explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {}

  /// Computes the type- and value-dependence flags for this
  /// declaration reference expression.
  void computeDependence(const ASTContext &Ctx);

public:
  DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
              bool RefersToEnclosingVariableOrCapture, QualType T,
@@ -2558,8 +2559,6 @@ class CallExpr : public Expr {
  /// the derived classes of CallExpr.
  SourceLocation RParenLoc;

  void updateDependenciesFromArg(Expr *Arg);

  // CallExpr store some data in trailing objects. However since CallExpr
  // is used a base of other expression classes we cannot use
  // llvm::TrailingObjects. Instead we manually perform the pointer arithmetic
@@ -4467,13 +4466,8 @@ public:
    assert(Init < getNumInits() && "Initializer access out of range!");
    InitExprs[Init] = expr;

    if (expr) {
      ExprBits.TypeDependent |= expr->isTypeDependent();
      ExprBits.ValueDependent |= expr->isValueDependent();
      ExprBits.InstantiationDependent |= expr->isInstantiationDependent();
      ExprBits.ContainsUnexpandedParameterPack |=
          expr->containsUnexpandedParameterPack();
    }
    if (expr)
      addDependence(expr->getDependence());
  }

  /// Reserve space for some number of initializers.
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ public:
  enum RequirementKind { RK_Type, RK_Simple, RK_Compound, RK_Nested };
private:
  const RequirementKind Kind;
  // FIXME: use RequirementDependence to model dependence?
  bool Dependent : 1;
  bool ContainsUnexpandedParameterPack : 1;
  bool Satisfied : 1;
+3 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H

#include "clang/AST/DependencyFlags.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/FoldingSet.h"
@@ -199,6 +200,8 @@ public:
    return nullptr;
  }

  NestedNameSpecifierDependence getDependence() const;

  /// Whether this nested name specifier refers to a dependent
  /// type or not.
  bool isDependent() const;
+3 −5
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#define LLVM_CLANG_AST_STMT_H

#include "clang/AST/DeclGroup.h"
#include "clang/AST/DependencyFlags.h"
#include "clang/AST/StmtIterator.h"
#include "clang/Basic/CapturedStmt.h"
#include "clang/Basic/IdentifierTable.h"
@@ -315,12 +316,9 @@ protected:

    unsigned ValueKind : 2;
    unsigned ObjectKind : 3;
    unsigned TypeDependent : 1;
    unsigned ValueDependent : 1;
    unsigned InstantiationDependent : 1;
    unsigned ContainsUnexpandedParameterPack : 1;
    unsigned /*ExprDependence*/ Dependent : ExprDependenceBits;
  };
  enum { NumExprBits = NumStmtBits + 9 };
  enum { NumExprBits = NumStmtBits + 5 + ExprDependenceBits };

  class ConstantExprBitfields {
    friend class ASTStmtReader;
Loading