[clang] ec3060c - [AST] Refactor propagation of dependency bits. NFC

Mikael Holmén via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 5 00:49:34 PST 2020


Hi Hokein, Ilya,

Clang warns on this code when compiled without asserts:

../../clang/lib/AST/TemplateName.cpp:189:3: error: unannotated fall-
through between switch labels [-Werror,-Wimplicit-fallthrough]
  default:
  ^
../../clang/lib/AST/TemplateName.cpp:189:3: note: insert 'break;' to
avoid fall-through
  default:
  ^
  break; 
1 error generated.


The code is

  case TemplateName::NameKind::OverloadedTemplate:
    assert(false && "overloaded templates shouldn't survive to here.");
  default:

I'm not sure if there should be a break after the assert (not sure if
someone would warn about that) or should there be a LLVM_FALLTHROUGH;
or should the assert perhaps be an llvm_unreachable?

/Mikael

On Wed, 2020-03-04 at 02:25 -0800, Haojian Wu via cfe-commits wrote:
> Author: Ilya Biryukov
> Date: 2020-03-04T11:25:17+01:00
> New Revision: ec3060c72de6ab6992269318d92764199856e5fe
> 
> URL: 
> https://github.com/llvm/llvm-project/commit/ec3060c72de6ab6992269318d92764199856e5fe
> DIFF: 
> https://github.com/llvm/llvm-project/commit/ec3060c72de6ab6992269318d92764199856e5fe.diff
> 
> LOG: [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
> 
> Added: 
>     clang/include/clang/AST/DependencyFlags.h
> 
> Modified: 
>     clang/include/clang/AST/Expr.h
>     clang/include/clang/AST/ExprConcepts.h
>     clang/include/clang/AST/NestedNameSpecifier.h
>     clang/include/clang/AST/Stmt.h
>     clang/include/clang/AST/TemplateBase.h
>     clang/include/clang/AST/TemplateName.h
>     clang/include/clang/AST/Type.h
>     clang/lib/AST/ASTImporter.cpp
>     clang/lib/AST/Expr.cpp
>     clang/lib/AST/ExprCXX.cpp
>     clang/lib/AST/ExprConcepts.cpp
>     clang/lib/AST/ExprObjC.cpp
>     clang/lib/AST/NestedNameSpecifier.cpp
>     clang/lib/AST/TemplateBase.cpp
>     clang/lib/AST/TemplateName.cpp
>     clang/lib/Sema/SemaOverload.cpp
>     clang/lib/Serialization/ASTReaderStmt.cpp
> 
> Removed: 
>     
> 
> 
> #####################################################################
> ###########
> diff  --git a/clang/include/clang/AST/DependencyFlags.h
> b/clang/include/clang/AST/DependencyFlags.h
> new file mode 100644
> index 000000000000..c27016aa9aec
> --- /dev/null
> +++ b/clang/include/clang/AST/DependencyFlags.h
> @@ -0,0 +1,138 @@
> +//===--- 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
> 
> diff  --git a/clang/include/clang/AST/Expr.h
> b/clang/include/clang/AST/Expr.h
> index 87f9b883486a..ffc1f54fe82d 100644
> --- a/clang/include/clang/AST/Expr.h
> +++ b/clang/include/clang/AST/Expr.h
> @@ -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 @@ class Expr : public ValueStmt {
>         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 @@ class Expr : public ValueStmt {
>      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 @@ class Expr : public ValueStmt {
>    /// @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 @@ class Expr : public ValueStmt {
>    ///   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 @@ class Expr : public ValueStmt {
>    /// \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 @@ class Expr : public ValueStmt {
>    /// 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 @@ class InitListExpr : public Expr {
>      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.
> 
> diff  --git a/clang/include/clang/AST/ExprConcepts.h
> b/clang/include/clang/AST/ExprConcepts.h
> index 6137e0e4082b..2a88ed5175d2 100644
> --- a/clang/include/clang/AST/ExprConcepts.h
> +++ b/clang/include/clang/AST/ExprConcepts.h
> @@ -149,6 +149,7 @@ class Requirement {
>    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;
> 
> diff  --git a/clang/include/clang/AST/NestedNameSpecifier.h
> b/clang/include/clang/AST/NestedNameSpecifier.h
> index c6fae6f465ff..e465c33e2cc5 100644
> --- a/clang/include/clang/AST/NestedNameSpecifier.h
> +++ b/clang/include/clang/AST/NestedNameSpecifier.h
> @@ -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 @@ class NestedNameSpecifier : public
> llvm::FoldingSetNode {
>      return nullptr;
>    }
>  
> +  NestedNameSpecifierDependence getDependence() const;
> +
>    /// Whether this nested name specifier refers to a dependent
>    /// type or not.
>    bool isDependent() const;
> 
> diff  --git a/clang/include/clang/AST/Stmt.h
> b/clang/include/clang/AST/Stmt.h
> index 5cc4eb8a46df..5191a8261f86 100644
> --- a/clang/include/clang/AST/Stmt.h
> +++ b/clang/include/clang/AST/Stmt.h
> @@ -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 @@ class alignas(void *) Stmt {
>  
>      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;
> 
> diff  --git a/clang/include/clang/AST/TemplateBase.h
> b/clang/include/clang/AST/TemplateBase.h
> index 93f7b62b8aea..e5fd1ca9dd46 100644
> --- a/clang/include/clang/AST/TemplateBase.h
> +++ b/clang/include/clang/AST/TemplateBase.h
> @@ -14,6 +14,7 @@
>  #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
>  #define LLVM_CLANG_AST_TEMPLATEBASE_H
>  
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/NestedNameSpecifier.h"
>  #include "clang/AST/TemplateName.h"
>  #include "clang/AST/Type.h"
> @@ -236,6 +237,8 @@ class TemplateArgument {
>    /// Determine whether this template argument has no value.
>    bool isNull() const { return getKind() == Null; }
>  
> +  TemplateArgumentDependence getDependence() const;
> +
>    /// Whether this template argument is dependent on a template
>    /// parameter such that its result can change from one
> instantiation to
>    /// another.
> @@ -668,9 +671,8 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo {
>                        TemplateArgumentLoc *OutArgArray);
>    void initializeFrom(SourceLocation TemplateKWLoc,
>                        const TemplateArgumentListInfo &List,
> -                      TemplateArgumentLoc *OutArgArray, bool
> &Dependent,
> -                      bool &InstantiationDependent,
> -                      bool &ContainsUnexpandedParameterPack);
> +                      TemplateArgumentLoc *OutArgArray,
> +                      TemplateArgumentDependence &Deps);
>    void initializeFrom(SourceLocation TemplateKWLoc);
>  
>    void copyInto(const TemplateArgumentLoc *ArgArray,
> 
> diff  --git a/clang/include/clang/AST/TemplateName.h
> b/clang/include/clang/AST/TemplateName.h
> index e1315facc966..bf917788477f 100644
> --- a/clang/include/clang/AST/TemplateName.h
> +++ b/clang/include/clang/AST/TemplateName.h
> @@ -13,6 +13,7 @@
>  #ifndef LLVM_CLANG_AST_TEMPLATENAME_H
>  #define LLVM_CLANG_AST_TEMPLATENAME_H
>  
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/NestedNameSpecifier.h"
>  #include "clang/Basic/LLVM.h"
>  #include "llvm/ADT/FoldingSet.h"
> @@ -295,6 +296,8 @@ class TemplateName {
>    /// the template, including any default template arguments.
>    TemplateName getNameToSubstitute() const;
>  
> +  TemplateNameDependence getDependence() const;
> +
>    /// Determines whether this is a dependent template name.
>    bool isDependent() const;
>  
> 
> diff  --git a/clang/include/clang/AST/Type.h
> b/clang/include/clang/AST/Type.h
> index e8248147f9ad..e589d3fa4e64 100644
> --- a/clang/include/clang/AST/Type.h
> +++ b/clang/include/clang/AST/Type.h
> @@ -17,6 +17,7 @@
>  #ifndef LLVM_CLANG_AST_TYPE_H
>  #define LLVM_CLANG_AST_TYPE_H
>  
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/NestedNameSpecifier.h"
>  #include "clang/AST/TemplateName.h"
>  #include "clang/Basic/AddressSpaces.h"
> @@ -44,8 +45,8 @@
>  #include "llvm/Support/Compiler.h"
>  #include "llvm/Support/ErrorHandling.h"
>  #include "llvm/Support/PointerLikeTypeTraits.h"
> -#include "llvm/Support/type_traits.h"
>  #include "llvm/Support/TrailingObjects.h"
> +#include "llvm/Support/type_traits.h"
>  #include <cassert>
>  #include <cstddef>
>  #include <cstdint>
> @@ -1465,19 +1466,8 @@ class alignas(8) Type : public
> ExtQualsTypeCommonBase {
>      /// TypeClass bitfield - Enum that specifies what subclass this
> belongs to.
>      unsigned TC : 8;
>  
> -    /// Whether this type is a dependent type (C++ [temp.dep.type]).
> -    unsigned Dependent : 1;
> -
> -    /// Whether this type somehow involves a template parameter,
> even
> -    /// if the resolution of the type does not depend on a template
> parameter.
> -    unsigned InstantiationDependent : 1;
> -
> -    /// Whether this type is a variably-modified type (C99 6.7.5).
> -    unsigned VariablyModified : 1;
> -
> -    /// Whether this type contains an unexpanded parameter pack
> -    /// (for C++11 variadic templates).
> -    unsigned ContainsUnexpandedParameterPack : 1;
> +    /// Store information on the type dependency.
> +    /*TypeDependence*/ unsigned Dependence : TypeDependenceBits;
>  
>      /// True if the cache (i.e. the bitfields here starting with
>      /// 'Cache') is valid.
> @@ -1833,11 +1823,18 @@ class alignas(8) Type : public
> ExtQualsTypeCommonBase {
>         bool ContainsUnexpandedParameterPack)
>        : ExtQualsTypeCommonBase(this,
>                                 canon.isNull() ? QualType(this_(), 0)
> : canon) {
> +    auto Deps = TypeDependence::None;
> +    if (Dependent)
> +      Deps |= TypeDependence::Dependent |
> TypeDependence::Instantiation;
> +    if (InstantiationDependent)
> +      Deps |= TypeDependence::Instantiation;
> +    if (ContainsUnexpandedParameterPack)
> +      Deps |= TypeDependence::UnexpandedPack;
> +    if (VariablyModified)
> +      Deps |= TypeDependence::VariablyModified;
> +
>      TypeBits.TC = tc;
> -    TypeBits.Dependent = Dependent;
> -    TypeBits.InstantiationDependent = Dependent ||
> InstantiationDependent;
> -    TypeBits.VariablyModified = VariablyModified;
> -    TypeBits.ContainsUnexpandedParameterPack =
> ContainsUnexpandedParameterPack;
> +    TypeBits.Dependence = static_cast<unsigned>(Deps);
>      TypeBits.CacheValid = false;
>      TypeBits.CachedLocalOrUnnamed = false;
>      TypeBits.CachedLinkage = NoLinkage;
> @@ -1848,18 +1845,39 @@ class alignas(8) Type : public
> ExtQualsTypeCommonBase {
>    Type *this_() { return this; }
>  
>    void setDependent(bool D = true) {
> -    TypeBits.Dependent = D;
> -    if (D)
> -      TypeBits.InstantiationDependent = true;
> +    if (!D) {
> +      TypeBits.Dependence &=
> ~static_cast<unsigned>(TypeDependence::Dependent);
> +      return;
> +    }
> +    TypeBits.Dependence |=
> static_cast<unsigned>(TypeDependence::Dependent |
> +                                                 TypeDependence::Ins
> tantiation);
>    }
>  
>    void setInstantiationDependent(bool D = true) {
> -    TypeBits.InstantiationDependent = D; }
> +    if (D)
> +      TypeBits.Dependence |=
> +          static_cast<unsigned>(TypeDependence::Instantiation);
> +    else
> +      TypeBits.Dependence &=
> +          ~static_cast<unsigned>(TypeDependence::Instantiation);
> +  }
>  
> -  void setVariablyModified(bool VM = true) {
> TypeBits.VariablyModified = VM; }
> +  void setVariablyModified(bool VM = true) {
> +    if (VM)
> +      TypeBits.Dependence |=
> +          static_cast<unsigned>(TypeDependence::VariablyModified);
> +    else
> +      TypeBits.Dependence &=
> +          ~static_cast<unsigned>(TypeDependence::VariablyModified);
> +  }
>  
>    void setContainsUnexpandedParameterPack(bool PP = true) {
> -    TypeBits.ContainsUnexpandedParameterPack = PP;
> +    if (PP)
> +      TypeBits.Dependence |=
> +          static_cast<unsigned>(TypeDependence::UnexpandedPack);
> +    else
> +      TypeBits.Dependence &=
> +          ~static_cast<unsigned>(TypeDependence::UnexpandedPack);
>    }
>  
>  public:
> @@ -1894,7 +1912,7 @@ class alignas(8) Type : public
> ExtQualsTypeCommonBase {
>    ///
>    /// Note that this routine does not specify which
>    bool containsUnexpandedParameterPack() const {
> -    return TypeBits.ContainsUnexpandedParameterPack;
> +    return getDependence() & TypeDependence::UnexpandedPack;
>    }
>  
>    /// Determines if this type would be canonical if it had no
> further
> @@ -2145,16 +2163,22 @@ class alignas(8) Type : public
> ExtQualsTypeCommonBase {
>    /// Given that this is a scalar type, classify it.
>    ScalarTypeKind getScalarTypeKind() const;
>  
> +  TypeDependence getDependence() const {
> +    return static_cast<TypeDependence>(TypeBits.Dependence);
> +  }
> +
>    /// Whether this type is a dependent type, meaning that its
> definition
>    /// somehow depends on a template parameter (C++ [temp.dep.type]).
> -  bool isDependentType() const { return TypeBits.Dependent; }
> +  bool isDependentType() const {
> +    return getDependence() & TypeDependence::Dependent;
> +  }
>  
>    /// Determine whether this type is an instantiation-dependent
> type,
>    /// meaning that the type involves a template parameter (even if
> the
>    /// definition does not actually depend on the type substituted
> for that
>    /// template parameter).
>    bool isInstantiationDependentType() const {
> -    return TypeBits.InstantiationDependent;
> +    return getDependence() & TypeDependence::Instantiation;
>    }
>  
>    /// Determine whether this type is an undeduced type, meaning that
> @@ -2163,7 +2187,9 @@ class alignas(8) Type : public
> ExtQualsTypeCommonBase {
>    bool isUndeducedType() const;
>  
>    /// Whether this type is a variably-modified type (C99 6.7.5).
> -  bool isVariablyModifiedType() const { return
> TypeBits.VariablyModified; }
> +  bool isVariablyModifiedType() const {
> +    return getDependence() & TypeDependence::VariablyModified;
> +  }
>  
>    /// Whether this type involves a variable-length array type
>    /// with a definite size.
> 
> diff  --git a/clang/lib/AST/ASTImporter.cpp
> b/clang/lib/AST/ASTImporter.cpp
> index 0cf00f6ca15b..ddbd3699bdc2 100644
> --- a/clang/lib/AST/ASTImporter.cpp
> +++ b/clang/lib/AST/ASTImporter.cpp
> @@ -8221,11 +8221,7 @@ Expected<Stmt *> ASTImporter::Import(Stmt
> *FromS) {
>      // constructors.
>      ToE->setValueKind(FromE->getValueKind());
>      ToE->setObjectKind(FromE->getObjectKind());
> -    ToE->setTypeDependent(FromE->isTypeDependent());
> -    ToE->setValueDependent(FromE->isValueDependent());
> -    ToE->setInstantiationDependent(FromE-
> >isInstantiationDependent());
> -    ToE->setContainsUnexpandedParameterPack(
> -        FromE->containsUnexpandedParameterPack());
> +    ToE->setDependence(FromE->getDependence());
>    }
>  
>    // Record the imported statement object.
> 
> diff  --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
> index 7e8808f84ead..79f9f42224d0 100644
> --- a/clang/lib/AST/Expr.cpp
> +++ b/clang/lib/AST/Expr.cpp
> @@ -17,6 +17,7 @@
>  #include "clang/AST/DeclCXX.h"
>  #include "clang/AST/DeclObjC.h"
>  #include "clang/AST/DeclTemplate.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/EvaluatedExprVisitor.h"
>  #include "clang/AST/ExprCXX.h"
>  #include "clang/AST/Mangle.h"
> @@ -371,13 +372,11 @@ APValue ConstantExpr::getAPValueResult() const
> {
>  /// Compute the type-, value-, and instantiation-dependence of a
>  /// declaration reference
>  /// based on the declaration being referenced.
> -static void computeDeclRefDependence(const ASTContext &Ctx,
> NamedDecl *D,
> -                                     QualType T, bool
> &TypeDependent,
> -                                     bool &ValueDependent,
> -                                     bool &InstantiationDependent) {
> -  TypeDependent = false;
> -  ValueDependent = false;
> -  InstantiationDependent = false;
> +static ExprDependence computeDeclRefDependence(const ASTContext
> &Ctx,
> +                                               NamedDecl *D,
> QualType T) {
> +  auto R = ExprDependence::None;
> +  if (D->isParameterPack())
> +    R |= ExprDependence::UnexpandedPack;
>  
>    // (TD) C++ [temp.dep.expr]p3:
>    //   An id-expression is type-dependent if it contains:
> @@ -389,36 +388,25 @@ static void computeDeclRefDependence(const
> ASTContext &Ctx, NamedDecl *D,
>  
>    //  (TD)  - an identifier that was declared with dependent type
>    //  (VD)  - a name declared with a dependent type,
> -  if (T->isDependentType()) {
> -    TypeDependent = true;
> -    ValueDependent = true;
> -    InstantiationDependent = true;
> -    return;
> -  } else if (T->isInstantiationDependentType()) {
> -    InstantiationDependent = true;
> -  }
> +  if (T->isDependentType())
> +    return R | ExprDependence::TypeValueInstantiation;
> +  else if (T->isInstantiationDependentType())
> +    R |= ExprDependence::Instantiation;
>  
>    //  (TD)  - a conversion-function-id that specifies a dependent
> type
>    if (D->getDeclName().getNameKind()
>                                  ==
> DeclarationName::CXXConversionFunctionName) {
>      QualType T = D->getDeclName().getCXXNameType();
> -    if (T->isDependentType()) {
> -      TypeDependent = true;
> -      ValueDependent = true;
> -      InstantiationDependent = true;
> -      return;
> -    }
> +    if (T->isDependentType())
> +      return R | ExprDependence::TypeValueInstantiation;
>  
>      if (T->isInstantiationDependentType())
> -      InstantiationDependent = true;
> +      R |= ExprDependence::Instantiation;
>    }
>  
>    //  (VD)  - the name of a non-type template parameter,
> -  if (isa<NonTypeTemplateParmDecl>(D)) {
> -    ValueDependent = true;
> -    InstantiationDependent = true;
> -    return;
> -  }
> +  if (isa<NonTypeTemplateParmDecl>(D))
> +    return R | ExprDependence::ValueInstantiation;
>  
>    //  (VD) - a constant with integral or enumeration type and is
>    //         initialized with an expression that is value-dependent.
> @@ -435,8 +423,7 @@ static void computeDeclRefDependence(const
> ASTContext &Ctx, NamedDecl *D,
>           Var->getType()->isReferenceType())) {
>        if (const Expr *Init = Var->getAnyInitializer())
>          if (Init->isValueDependent()) {
> -          ValueDependent = true;
> -          InstantiationDependent = true;
> +          R |= ExprDependence::ValueInstantiation;
>          }
>      }
>  
> @@ -445,39 +432,21 @@ static void computeDeclRefDependence(const
> ASTContext &Ctx, NamedDecl *D,
>      //         instantiation
>      if (Var->isStaticDataMember() &&
>          Var->getDeclContext()->isDependentContext()) {
> -      ValueDependent = true;
> -      InstantiationDependent = true;
> +      R |= ExprDependence::ValueInstantiation;
>        TypeSourceInfo *TInfo = Var->getFirstDecl()-
> >getTypeSourceInfo();
>        if (TInfo->getType()->isIncompleteArrayType())
> -        TypeDependent = true;
> +        R |= ExprDependence::Type;
>      }
>  
> -    return;
> +    return R;
>    }
>  
>    // (VD) - FIXME: Missing from the standard:
>    //      -  a member function or a static data member of the
> current
>    //         instantiation
> -  if (isa<CXXMethodDecl>(D) && D->getDeclContext()-
> >isDependentContext()) {
> -    ValueDependent = true;
> -    InstantiationDependent = true;
> -  }
> -}
> -
> -void DeclRefExpr::computeDependence(const ASTContext &Ctx) {
> -  bool TypeDependent = false;
> -  bool ValueDependent = false;
> -  bool InstantiationDependent = false;
> -  computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent,
> -                           ValueDependent, InstantiationDependent);
> -
> -  ExprBits.TypeDependent |= TypeDependent;
> -  ExprBits.ValueDependent |= ValueDependent;
> -  ExprBits.InstantiationDependent |= InstantiationDependent;
> -
> -  // Is the declaration a parameter pack?
> -  if (getDecl()->isParameterPack())
> -    ExprBits.ContainsUnexpandedParameterPack = true;
> +  if (isa<CXXMethodDecl>(D) && D->getDeclContext()-
> >isDependentContext())
> +    R |= ExprDependence::ValueInstantiation;
> +  return R;
>  }
>  
>  DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
> @@ -495,7 +464,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
> ValueDecl *D,
>        RefersToEnclosingVariableOrCapture;
>    DeclRefExprBits.NonOdrUseReason = NOUR;
>    DeclRefExprBits.Loc = L;
> -  computeDependence(Ctx);
> +  addDependence(computeDeclRefDependence(Ctx, getDecl(),
> getType()));
>  }
>  
>  DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
> @@ -514,9 +483,9 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
>          NestedNameSpecifierLoc(QualifierLoc);
>      auto *NNS = QualifierLoc.getNestedNameSpecifier();
>      if (NNS->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> +      addDependence(ExprDependence::Instantiation);
>      if (NNS->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +      addDependence(ExprDependence::UnexpandedPack);
>    }
>    DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
>    if (FoundD)
> @@ -527,22 +496,19 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
>        RefersToEnclosingVariableOrCapture;
>    DeclRefExprBits.NonOdrUseReason = NOUR;
>    if (TemplateArgs) {
> -    bool Dependent = false;
> -    bool InstantiationDependent = false;
> -    bool ContainsUnexpandedParameterPack = false;
> +    auto Deps = TemplateArgumentDependence::None;
>      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
>          TemplateKWLoc, *TemplateArgs,
> getTrailingObjects<TemplateArgumentLoc>(),
> -        Dependent, InstantiationDependent,
> ContainsUnexpandedParameterPack);
> -    assert(!Dependent && "built a DeclRefExpr with dependent
> template args");
> -    ExprBits.InstantiationDependent |= InstantiationDependent;
> -    ExprBits.ContainsUnexpandedParameterPack |=
> ContainsUnexpandedParameterPack;
> +        Deps);
> +    assert(!(Deps & TemplateArgumentDependence::Dependent) &&
> +           "built a DeclRefExpr with dependent template args");
> +    addDependence(toExprDependence(Deps));
>    } else if (TemplateKWLoc.isValid()) {
>      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
>          TemplateKWLoc);
>    }
>    DeclRefExprBits.HadMultipleCandidates = 0;
> -
> -  computeDependence(Ctx);
> +  addDependence(computeDeclRefDependence(Ctx, getDecl(),
> getType()));
>  }
>  
>  DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
> @@ -1360,11 +1326,11 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn,
> ArrayRef<Expr *> PreArgs,
>  
>    setCallee(Fn);
>    for (unsigned I = 0; I != NumPreArgs; ++I) {
> -    updateDependenciesFromArg(PreArgs[I]);
> +    addDependence(PreArgs[I]->getDependence());
>      setPreArg(I, PreArgs[I]);
>    }
>    for (unsigned I = 0; I != Args.size(); ++I) {
> -    updateDependenciesFromArg(Args[I]);
> +    addDependence(Args[I]->getDependence());
>      setArg(I, Args[I]);
>    }
>    for (unsigned I = Args.size(); I != NumArgs; ++I) {
> @@ -1432,17 +1398,6 @@ unsigned
> CallExpr::offsetToTrailingObjects(StmtClass SC) {
>    }
>  }
>  
> -void CallExpr::updateDependenciesFromArg(Expr *Arg) {
> -  if (Arg->isTypeDependent())
> -    ExprBits.TypeDependent = true;
> -  if (Arg->isValueDependent())
> -    ExprBits.ValueDependent = true;
> -  if (Arg->isInstantiationDependent())
> -    ExprBits.InstantiationDependent = true;
> -  if (Arg->containsUnexpandedParameterPack())
> -    ExprBits.ContainsUnexpandedParameterPack = true;
> -}
> -
>  Decl *Expr::getReferencedDeclOfCallee() {
>    Expr *CEE = IgnoreParenImpCasts();
>  
> @@ -1580,9 +1535,9 @@ OffsetOfExpr::OffsetOfExpr(const ASTContext &C,
> QualType type,
>  
>    for (unsigned i = 0; i != exprs.size(); ++i) {
>      if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> +      addDependence(ExprDependence::Value);
>      if (exprs[i]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +      addDependence(ExprDependence ::UnexpandedPack);
>  
>      setIndexExpr(i, exprs[i]);
>    }
> @@ -1624,8 +1579,7 @@
> UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
>        if (D) {
>          for (const auto *I : D->specific_attrs<AlignedAttr>()) {
>            if (I->isAlignmentDependent()) {
> -            setValueDependent(true);
> -            setInstantiationDependent(true);
> +            addDependence(ExprDependence::ValueInstantiation);
>              break;
>            }
>          }
> @@ -1678,25 +1632,23 @@ MemberExpr *MemberExpr::Create(
>      // dyn_cast_or_null is used to handle objC variables which do
> not
>      // have a declaration context.
>      CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC);
> -    if (RD && RD->isDependentContext() && RD-
> >isCurrentInstantiation(DC))
> -      E->setTypeDependent(T->isDependentType());
> -
> +    if (RD && RD->isDependentContext() && RD-
> >isCurrentInstantiation(DC)) {
> +      if (E->isTypeDependent() && !T->isDependentType())
> +        E->removeDependence(ExprDependence::Type);
> +    }
>      // Bitfield with value-dependent width is type-dependent.
>      FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl);
>      if (FD && FD->isBitField() && FD->getBitWidth()-
> >isValueDependent())
> -      E->setTypeDependent(true);
> +      E->addDependence(ExprDependence::Type);
>    }
>  
>    if (HasQualOrFound) {
>      // FIXME: Wrong. We should be looking at the member declaration
> we found.
> -    if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()-
> >isDependent()) {
> -      E->setValueDependent(true);
> -      E->setTypeDependent(true);
> -      E->setInstantiationDependent(true);
> -    }
> +    if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()-
> >isDependent())
> +      E->addDependence(ExprDependence::TypeValueInstantiation);
>      else if (QualifierLoc &&
>               QualifierLoc.getNestedNameSpecifier()-
> >isInstantiationDependent())
> -      E->setInstantiationDependent(true);
> +      E->addDependence(ExprDependence::Instantiation);
>  
>      E->MemberExprBits.HasQualifierOrFoundDecl = true;
>  
> @@ -1710,15 +1662,12 @@ MemberExpr *MemberExpr::Create(
>        TemplateArgs || TemplateKWLoc.isValid();
>  
>    if (TemplateArgs) {
> -    bool Dependent = false;
> -    bool InstantiationDependent = false;
> -    bool ContainsUnexpandedParameterPack = false;
> +    auto Deps = TemplateArgumentDependence::None;
>      E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()-
> >initializeFrom(
>          TemplateKWLoc, *TemplateArgs,
> -        E->getTrailingObjects<TemplateArgumentLoc>(), Dependent,
> -        InstantiationDependent, ContainsUnexpandedParameterPack);
> -    if (InstantiationDependent)
> -      E->setInstantiationDependent(true);
> +        E->getTrailingObjects<TemplateArgumentLoc>(), Deps);
> +    if (Deps & TemplateArgumentDependence::Instantiation)
> +      E->addDependence(ExprDependence::Instantiation);
>    } else if (TemplateKWLoc.isValid()) {
>      E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()-
> >initializeFrom(
>          TemplateKWLoc);
> @@ -2236,16 +2185,8 @@ InitListExpr::InitListExpr(const ASTContext
> &C, SourceLocation lbraceloc,
>      LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr,
> true)
>  {
>    sawArrayRangeDesignator(false);
> -  for (unsigned I = 0; I != initExprs.size(); ++I) {
> -    if (initExprs[I]->isTypeDependent())
> -      ExprBits.TypeDependent = true;
> -    if (initExprs[I]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (initExprs[I]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (initExprs[I]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> -  }
> +  for (unsigned I = 0; I != initExprs.size(); ++I)
> +    addDependence(initExprs[I]->getDependence());
>  
>    InitExprs.insert(C, InitExprs.end(), initExprs.begin(),
> initExprs.end());
>  }
> @@ -4167,15 +4108,7 @@ ShuffleVectorExpr::ShuffleVectorExpr(const
> ASTContext &C, ArrayRef<Expr*> args,
>  {
>    SubExprs = new (C) Stmt*[args.size()];
>    for (unsigned i = 0; i != args.size(); i++) {
> -    if (args[i]->isTypeDependent())
> -      ExprBits.TypeDependent = true;
> -    if (args[i]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (args[i]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (args[i]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> -
> +    addDependence(args[i]->getDependence());
>      SubExprs[i] = args[i];
>    }
>  }
> @@ -4319,13 +4252,12 @@ DesignatedInitExpr::DesignatedInitExpr(const
> ASTContext &C, QualType Ty,
>      if (this->Designators[I].isArrayDesignator()) {
>        // Compute type- and value-dependence.
>        Expr *Index = IndexExprs[IndexIdx];
> -      if (Index->isTypeDependent() || Index->isValueDependent())
> -        ExprBits.TypeDependent = ExprBits.ValueDependent = true;
> -      if (Index->isInstantiationDependent())
> -        ExprBits.InstantiationDependent = true;
> -      // Propagate unexpanded parameter packs.
> -      if (Index->containsUnexpandedParameterPack())
> -        ExprBits.ContainsUnexpandedParameterPack = true;
> +
> +      // Propagate dependence flags.
> +      auto Deps = Index->getDependence();
> +      if (Deps & (ExprDependence::Type | ExprDependence::Value))
> +        Deps |= ExprDependence::Type | ExprDependence::Value;
> +      addDependence(Deps);
>  
>        // Copy the index expressions into permanent storage.
>        *Child++ = IndexExprs[IndexIdx++];
> @@ -4333,19 +4265,11 @@ DesignatedInitExpr::DesignatedInitExpr(const
> ASTContext &C, QualType Ty,
>        // Compute type- and value-dependence.
>        Expr *Start = IndexExprs[IndexIdx];
>        Expr *End = IndexExprs[IndexIdx + 1];
> -      if (Start->isTypeDependent() || Start->isValueDependent() ||
> -          End->isTypeDependent() || End->isValueDependent()) {
> -        ExprBits.TypeDependent = ExprBits.ValueDependent = true;
> -        ExprBits.InstantiationDependent = true;
> -      } else if (Start->isInstantiationDependent() ||
> -                 End->isInstantiationDependent()) {
> -        ExprBits.InstantiationDependent = true;
> -      }
>  
> -      // Propagate unexpanded parameter packs.
> -      if (Start->containsUnexpandedParameterPack() ||
> -          End->containsUnexpandedParameterPack())
> -        ExprBits.ContainsUnexpandedParameterPack = true;
> +      auto Deps = Start->getDependence() | End->getDependence();
> +      if (Deps & (ExprDependence::Type | ExprDependence::Value))
> +        Deps |= ExprDependence::TypeValueInstantiation;
> +      addDependence(Deps);
>  
>        // Copy the start/end expressions into permanent storage.
>        *Child++ = IndexExprs[IndexIdx++];
> @@ -4483,15 +4407,7 @@ ParenListExpr::ParenListExpr(SourceLocation
> LParenLoc, ArrayRef<Expr *> Exprs,
>    ParenListExprBits.NumExprs = Exprs.size();
>  
>    for (unsigned I = 0, N = Exprs.size(); I != N; ++I) {
> -    if (Exprs[I]->isTypeDependent())
> -      ExprBits.TypeDependent = true;
> -    if (Exprs[I]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (Exprs[I]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (Exprs[I]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> -
> +    addDependence(Exprs[I]->getDependence());
>      getTrailingObjects<Stmt *>()[I] = Exprs[I];
>    }
>  }
> @@ -4578,14 +4494,7 @@ PseudoObjectExpr::PseudoObjectExpr(QualType
> type, ExprValueKind VK,
>      Expr *E = (i == 0 ? syntax : semantics[i-1]);
>      getSubExprsBuffer()[i] = E;
>  
> -    if (E->isTypeDependent())
> -      ExprBits.TypeDependent = true;
> -    if (E->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (E->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (E->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +    addDependence(E->getDependence());
>  
>      if (isa<OpaqueValueExpr>(E))
>        assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr &&
> @@ -4626,15 +4535,7 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc,
> ArrayRef<Expr*> args,
>  {
>    assert(args.size() == getNumSubExprs(op) && "wrong number of
> subexpressions");
>    for (unsigned i = 0; i != args.size(); i++) {
> -    if (args[i]->isTypeDependent())
> -      ExprBits.TypeDependent = true;
> -    if (args[i]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (args[i]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (args[i]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> -
> +    addDependence(args[i]->getDependence());
>      SubExprs[i] = args[i];
>    }
>  }
> 
> diff  --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
> index e4bd218ae2d3..38cdfcf752df 100644
> --- a/clang/lib/AST/ExprCXX.cpp
> +++ b/clang/lib/AST/ExprCXX.cpp
> @@ -19,6 +19,7 @@
>  #include "clang/AST/DeclCXX.h"
>  #include "clang/AST/DeclTemplate.h"
>  #include "clang/AST/DeclarationName.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/Expr.h"
>  #include "clang/AST/LambdaCapture.h"
>  #include "clang/AST/NestedNameSpecifier.h"
> @@ -194,36 +195,20 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew,
> FunctionDecl *OperatorNew,
>    CXXNewExprBits.NumPlacementArgs = PlacementArgs.size();
>  
>    if (ArraySize) {
> -    if (Expr *SizeExpr = *ArraySize) {
> -      if (SizeExpr->isValueDependent())
> -        ExprBits.ValueDependent = true;
> -      if (SizeExpr->isInstantiationDependent())
> -        ExprBits.InstantiationDependent = true;
> -      if (SizeExpr->containsUnexpandedParameterPack())
> -        ExprBits.ContainsUnexpandedParameterPack = true;
> -    }
> +    if (Expr *SizeExpr = *ArraySize)
> +      addDependence(SizeExpr->getDependence() &
> ~ExprDependence::Type);
>  
>      getTrailingObjects<Stmt *>()[arraySizeOffset()] = *ArraySize;
>    }
>  
>    if (Initializer) {
> -    if (Initializer->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (Initializer->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (Initializer->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +    addDependence(Initializer->getDependence() &
> ~ExprDependence::Type);
>  
>      getTrailingObjects<Stmt *>()[initExprOffset()] = Initializer;
>    }
>  
>    for (unsigned I = 0; I != PlacementArgs.size(); ++I) {
> -    if (PlacementArgs[I]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (PlacementArgs[I]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (PlacementArgs[I]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +    addDependence(PlacementArgs[I]->getDependence() &
> ~ExprDependence::Type);
>  
>      getTrailingObjects<Stmt *>()[placementNewArgsOffset() + I] =
>          PlacementArgs[I];
> @@ -474,11 +459,8 @@ OverloadExpr::OverloadExpr(StmtClass SC, const
> ASTContext &Context,
>      // Determine whether this expression is type-dependent.
>      for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I)
> {
>        if ((*I)->getDeclContext()->isDependentContext() ||
> -          isa<UnresolvedUsingValueDecl>(*I)) {
> -        ExprBits.TypeDependent = true;
> -        ExprBits.ValueDependent = true;
> -        ExprBits.InstantiationDependent = true;
> -      }
> +          isa<UnresolvedUsingValueDecl>(*I))
> +        addDependence(ExprDependence::TypeValueInstantiation);
>      }
>  
>      // Copy the results to the trailing array past
> UnresolvedLookupExpr
> @@ -491,21 +473,11 @@ OverloadExpr::OverloadExpr(StmtClass SC, const
> ASTContext &Context,
>    // template arguments and whether they contain any unexpanded pack
>    // expansions.
>    if (TemplateArgs) {
> -    bool Dependent = false;
> -    bool InstantiationDependent = false;
> -    bool ContainsUnexpandedParameterPack = false;
> +    auto Deps = TemplateArgumentDependence::None;
>      getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(
> -        TemplateKWLoc, *TemplateArgs,
> getTrailingTemplateArgumentLoc(),
> -        Dependent, InstantiationDependent,
> ContainsUnexpandedParameterPack);
> +        TemplateKWLoc, *TemplateArgs,
> getTrailingTemplateArgumentLoc(), Deps);
> +    addDependence(toExprDependence(Deps));
>  
> -    if (Dependent) {
> -      ExprBits.TypeDependent = true;
> -      ExprBits.ValueDependent = true;
> -    }
> -    if (InstantiationDependent)
> -      ExprBits.InstantiationDependent = true;
> -    if (ContainsUnexpandedParameterPack)
> -      ExprBits.ContainsUnexpandedParameterPack = true;
>    } else if (TemplateKWLoc.isValid()) {
>      getTrailingASTTemplateKWAndArgsInfo()-
> >initializeFrom(TemplateKWLoc);
>    }
> @@ -539,14 +511,11 @@
> DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(
>    DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
>        (Args != nullptr) || TemplateKWLoc.isValid();
>    if (Args) {
> -    bool Dependent = true;
> -    bool InstantiationDependent = true;
> -    bool ContainsUnexpandedParameterPack
> -      = ExprBits.ContainsUnexpandedParameterPack;
> +    auto Deps = TemplateArgumentDependence::None;
>      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
> -        TemplateKWLoc, *Args,
> getTrailingObjects<TemplateArgumentLoc>(),
> -        Dependent, InstantiationDependent,
> ContainsUnexpandedParameterPack);
> -    ExprBits.ContainsUnexpandedParameterPack =
> ContainsUnexpandedParameterPack;
> +        TemplateKWLoc, *Args,
> getTrailingObjects<TemplateArgumentLoc>(), Deps);
> +    if (Deps & TemplateArgumentDependence::UnexpandedPack)
> +      addDependence(ExprDependence::UnexpandedPack);
>    } else if (TemplateKWLoc.isValid()) {
>      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
>          TemplateKWLoc);
> @@ -1114,13 +1083,7 @@ CXXConstructExpr::CXXConstructExpr(
>    Stmt **TrailingArgs = getTrailingArgs();
>    for (unsigned I = 0, N = Args.size(); I != N; ++I) {
>      assert(Args[I] && "NULL argument in CXXConstructExpr!");
> -
> -    if (Args[I]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (Args[I]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (Args[I]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +    addDependence(Args[I]->getDependence() & ~ExprDependence::Type);
>  
>      TrailingArgs[I] = Args[I];
>    }
> @@ -1370,7 +1333,7 @@
> CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo
> *TSI,
>    auto **StoredArgs = getTrailingObjects<Expr *>();
>    for (unsigned I = 0; I != Args.size(); ++I) {
>      if (Args[I]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +      addDependence(ExprDependence::UnexpandedPack);
>  
>      StoredArgs[I] = Args[I];
>    }
> @@ -1416,14 +1379,12 @@
> CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
>    CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
>  
>    if (TemplateArgs) {
> -    bool Dependent = true;
> -    bool InstantiationDependent = true;
> -    bool ContainsUnexpandedParameterPack = false;
> +    auto Deps = TemplateArgumentDependence::None;
>      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
>          TemplateKWLoc, *TemplateArgs,
> getTrailingObjects<TemplateArgumentLoc>(),
> -        Dependent, InstantiationDependent,
> ContainsUnexpandedParameterPack);
> -    if (ContainsUnexpandedParameterPack)
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +        Deps);
> +    if (Deps & TemplateArgumentDependence::UnexpandedPack)
> +      addDependence(ExprDependence::UnexpandedPack);
>    } else if (TemplateKWLoc.isValid()) {
>      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
>          TemplateKWLoc);
> @@ -1704,13 +1665,8 @@ TypeTraitExpr::TypeTraitExpr(QualType T,
> SourceLocation Loc, TypeTrait Kind,
>    auto **ToArgs = getTrailingObjects<TypeSourceInfo *>();
>  
>    for (unsigned I = 0, N = Args.size(); I != N; ++I) {
> -    if (Args[I]->getType()->isDependentType())
> -      setValueDependent(true);
> -    if (Args[I]->getType()->isInstantiationDependentType())
> -      setInstantiationDependent(true);
> -    if (Args[I]->getType()->containsUnexpandedParameterPack())
> -      setContainsUnexpandedParameterPack(true);
> -
> +    addDependence(toExprDependence(Args[I]->getType()-
> >getDependence()) &
> +                  ~ExprDependence::Type);
>      ToArgs[I] = Args[I];
>    }
>  }
> 
> diff  --git a/clang/lib/AST/ExprConcepts.cpp
> b/clang/lib/AST/ExprConcepts.cpp
> index b5a3686dc99a..42cc4576562e 100644
> --- a/clang/lib/AST/ExprConcepts.cpp
> +++ b/clang/lib/AST/ExprConcepts.cpp
> @@ -11,11 +11,12 @@
>  //===---------------------------------------------------------------
> -------===//
>  
>  #include "clang/AST/ExprConcepts.h"
> -#include "clang/AST/ASTContext.h"
>  #include "clang/AST/ASTConcept.h"
> +#include "clang/AST/ASTContext.h"
>  #include "clang/AST/Decl.h"
> -#include "clang/AST/DeclarationName.h"
>  #include "clang/AST/DeclTemplate.h"
> +#include "clang/AST/DeclarationName.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/Expr.h"
>  #include "clang/AST/NestedNameSpecifier.h"
>  #include "clang/AST/TemplateBase.h"
> @@ -23,8 +24,8 @@
>  #include "clang/Basic/SourceLocation.h"
>  #include "llvm/Support/TrailingObjects.h"
>  #include <algorithm>
> -#include <utility>
>  #include <string>
> +#include <utility>
>  
>  using namespace clang;
>  
> @@ -46,14 +47,12 @@
> ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext
> &C,
>                     ASTConstraintSatisfaction::Create(C,
> *Satisfaction) :
>                     nullptr) {
>    setTemplateArguments(ConvertedArgs);
> -  bool IsInstantiationDependent = false;
> -  bool ContainsUnexpandedParameterPack = false;
> +  auto Deps = TemplateArgumentDependence::None;
> +  const auto InterestingDeps =
> TemplateArgumentDependence::Instantiation |
> +                               TemplateArgumentDependence::Unexpande
> dPack;
>    for (const TemplateArgumentLoc& ArgLoc : ArgsAsWritten-
> >arguments()) {
> -    if (ArgLoc.getArgument().isInstantiationDependent())
> -      IsInstantiationDependent = true;
> -    if (ArgLoc.getArgument().containsUnexpandedParameterPack())
> -      ContainsUnexpandedParameterPack = true;
> -    if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
> +    Deps |= ArgLoc.getArgument().getDependence() & InterestingDeps;
> +    if (Deps == InterestingDeps)
>        break;
>    }
>  
> @@ -62,8 +61,7 @@
> ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext
> &C,
>           (!NestedNameSpec.getNestedNameSpecifier()-
> >isInstantiationDependent() &&
>            !NestedNameSpec.getNestedNameSpecifier()
>                ->containsUnexpandedParameterPack()));
> -  setInstantiationDependent(IsInstantiationDependent);
> -  setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack
> );
> +  addDependence(toExprDependence(Deps));
>    assert((!isValueDependent() || isInstantiationDependent()) &&
>           "should not be value-dependent");
>  }
> @@ -182,9 +180,14 @@ RequiresExpr::RequiresExpr(ASTContext &C,
> SourceLocation RequiresKWLoc,
>    std::copy(Requirements.begin(), Requirements.end(),
>              getTrailingObjects<concepts::Requirement *>());
>    RequiresExprBits.IsSatisfied |= Dependent;
> -  setValueDependent(Dependent);
> -  setInstantiationDependent(Dependent);
> -  setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack
> );
> +  if (ContainsUnexpandedParameterPack)
> +    addDependence(ExprDependence::UnexpandedPack);
> +  // FIXME: this is incorrect for cases where we have a non-
> dependent
> +  // requirement, but its parameters are instantiation-dependent.
> RequiresExpr
> +  // should be instantiation-dependent if it has instantiation-
> dependent
> +  // parameters.
> +  if (Dependent)
> +    addDependence(ExprDependence::ValueInstantiation);
>  }
>  
>  RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
> 
> diff  --git a/clang/lib/AST/ExprObjC.cpp b/clang/lib/AST/ExprObjC.cpp
> index 53d0e873f8c9..6d98429bc89d 100644
> --- a/clang/lib/AST/ExprObjC.cpp
> +++ b/clang/lib/AST/ExprObjC.cpp
> @@ -12,6 +12,7 @@
>  
>  #include "clang/AST/ExprObjC.h"
>  #include "clang/AST/ASTContext.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/SelectorLocationsKind.h"
>  #include "clang/AST/Type.h"
>  #include "clang/AST/TypeLoc.h"
> @@ -30,13 +31,7 @@ ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr
> *> Elements, QualType T,
>        NumElements(Elements.size()), Range(SR),
> ArrayWithObjectsMethod(Method) {
>    Expr **SaveElements = getElements();
>    for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
> -    if (Elements[I]->isTypeDependent() || Elements[I]-
> >isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (Elements[I]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (Elements[I]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> -
> +    addDependence(turnTypeToValueDependence(Elements[I]-
> >getDependence()));
>      SaveElements[I] = Elements[I];
>    }
>  }
> @@ -67,16 +62,11 @@
> ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryE
> lement> VK,
>    ExpansionData *Expansions =
>        HasPackExpansions ? getTrailingObjects<ExpansionData>() :
> nullptr;
>    for (unsigned I = 0; I < NumElements; I++) {
> -    if (VK[I].Key->isTypeDependent() || VK[I].Key-
> >isValueDependent() ||
> -        VK[I].Value->isTypeDependent() || VK[I].Value-
> >isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (VK[I].Key->isInstantiationDependent() ||
> -        VK[I].Value->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (VK[I].EllipsisLoc.isInvalid() &&
> -        (VK[I].Key->containsUnexpandedParameterPack() ||
> -         VK[I].Value->containsUnexpandedParameterPack()))
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> +    auto Deps = turnTypeToValueDependence(VK[I].Key->getDependence() 
> |
> +                                          VK[I].Value-
> >getDependence());
> +    if (VK[I].EllipsisLoc.isValid())
> +      Deps &= ~ExprDependence::UnexpandedPack;
> +    addDependence(Deps);
>  
>      KeyValues[I].Key = VK[I].Key;
>      KeyValues[I].Value = VK[I].Value;
> @@ -183,15 +173,7 @@ void
> ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
>    setNumArgs(Args.size());
>    Expr **MyArgs = getArgs();
>    for (unsigned I = 0; I != Args.size(); ++I) {
> -    if (Args[I]->isTypeDependent())
> -      ExprBits.TypeDependent = true;
> -    if (Args[I]->isValueDependent())
> -      ExprBits.ValueDependent = true;
> -    if (Args[I]->isInstantiationDependent())
> -      ExprBits.InstantiationDependent = true;
> -    if (Args[I]->containsUnexpandedParameterPack())
> -      ExprBits.ContainsUnexpandedParameterPack = true;
> -
> +    addDependence(Args[I]->getDependence());
>      MyArgs[I] = Args[I];
>    }
>  
> 
> diff  --git a/clang/lib/AST/NestedNameSpecifier.cpp
> b/clang/lib/AST/NestedNameSpecifier.cpp
> index 06008b2f32ac..8cd65a857beb 100644
> --- a/clang/lib/AST/NestedNameSpecifier.cpp
> +++ b/clang/lib/AST/NestedNameSpecifier.cpp
> @@ -16,6 +16,7 @@
>  #include "clang/AST/Decl.h"
>  #include "clang/AST/DeclCXX.h"
>  #include "clang/AST/DeclTemplate.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/PrettyPrinter.h"
>  #include "clang/AST/TemplateName.h"
>  #include "clang/AST/Type.h"
> @@ -197,75 +198,49 @@ CXXRecordDecl
> *NestedNameSpecifier::getAsRecordDecl() const {
>    llvm_unreachable("Invalid NNS Kind!");
>  }
>  
> -/// Whether this nested name specifier refers to a dependent
> -/// type or not.
> -bool NestedNameSpecifier::isDependent() const {
> +NestedNameSpecifierDependence NestedNameSpecifier::getDependence()
> const {
>    switch (getKind()) {
> -  case Identifier:
> +  case Identifier: {
>      // Identifier specifiers always represent dependent types
> -    return true;
> +    auto F = NestedNameSpecifierDependence::Dependent |
> +             NestedNameSpecifierDependence::Instantiation;
> +    // Prefix can contain unexpanded template parameters.
> +    if (getPrefix())
> +      return F | getPrefix()->getDependence();
> +    return F;
> +  }
>  
>    case Namespace:
>    case NamespaceAlias:
>    case Global:
> -    return false;
> +    return NestedNameSpecifierDependence::None;
>  
>    case Super: {
>      CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
>      for (const auto &Base : RD->bases())
>        if (Base.getType()->isDependentType())
> -        return true;
> -
> -    return false;
> +        // FIXME: must also be instantiation-dependent.
> +        return NestedNameSpecifierDependence::Dependent;
> +    return NestedNameSpecifierDependence::None;
>    }
>  
>    case TypeSpec:
>    case TypeSpecWithTemplate:
> -    return getAsType()->isDependentType();
> +    return toNestedNameSpecifierDependendence(getAsType()-
> >getDependence());
>    }
> -
>    llvm_unreachable("Invalid NNS Kind!");
>  }
>  
> -/// Whether this nested name specifier refers to a dependent
> -/// type or not.
> -bool NestedNameSpecifier::isInstantiationDependent() const {
> -  switch (getKind()) {
> -  case Identifier:
> -    // Identifier specifiers always represent dependent types
> -    return true;
> -
> -  case Namespace:
> -  case NamespaceAlias:
> -  case Global:
> -  case Super:
> -    return false;
> -
> -  case TypeSpec:
> -  case TypeSpecWithTemplate:
> -    return getAsType()->isInstantiationDependentType();
> -  }
> +bool NestedNameSpecifier::isDependent() const {
> +  return getDependence() & NestedNameSpecifierDependence::Dependent;
> +}
>  
> -  llvm_unreachable("Invalid NNS Kind!");
> +bool NestedNameSpecifier::isInstantiationDependent() const {
> +  return getDependence() &
> NestedNameSpecifierDependence::Instantiation;
>  }
>  
>  bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
> -  switch (getKind()) {
> -  case Identifier:
> -    return getPrefix() && getPrefix()-
> >containsUnexpandedParameterPack();
> -
> -  case Namespace:
> -  case NamespaceAlias:
> -  case Global:
> -  case Super:
> -    return false;
> -
> -  case TypeSpec:
> -  case TypeSpecWithTemplate:
> -    return getAsType()->containsUnexpandedParameterPack();
> -  }
> -
> -  llvm_unreachable("Invalid NNS Kind!");
> +  return getDependence() &
> NestedNameSpecifierDependence::UnexpandedPack;
>  }
>  
>  /// Print this nested name specifier to the given output
> 
> diff  --git a/clang/lib/AST/TemplateBase.cpp
> b/clang/lib/AST/TemplateBase.cpp
> index 6f0ebf232e77..3c550bddaff8 100644
> --- a/clang/lib/AST/TemplateBase.cpp
> +++ b/clang/lib/AST/TemplateBase.cpp
> @@ -16,6 +16,7 @@
>  #include "clang/AST/Decl.h"
>  #include "clang/AST/DeclBase.h"
>  #include "clang/AST/DeclTemplate.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/Expr.h"
>  #include "clang/AST/ExprCXX.h"
>  #include "clang/AST/PrettyPrinter.h"
> @@ -111,84 +112,60 @@ TemplateArgument::CreatePackCopy(ASTContext
> &Context,
>    return TemplateArgument(Args.copy(Context));
>  }
>  
> -bool TemplateArgument::isDependent() const {
> +TemplateArgumentDependence TemplateArgument::getDependence() const {
> +  auto Deps = TemplateArgumentDependence::None;
>    switch (getKind()) {
>    case Null:
>      llvm_unreachable("Should not have a NULL template argument");
>  
>    case Type:
> -    return getAsType()->isDependentType() ||
> -           isa<PackExpansionType>(getAsType());
> +    Deps = toTemplateArgumentDependence(getAsType()-
> >getDependence());
> +    if (isa<PackExpansionType>(getAsType()))
> +      Deps |= TemplateArgumentDependence::Dependent;
> +    return Deps;
>  
>    case Template:
> -    return getAsTemplate().isDependent();
> +    return
> toTemplateArgumentDependence(getAsTemplate().getDependence());
>  
>    case TemplateExpansion:
> -    return true;
> +    return TemplateArgumentDependence::Dependent |
> +           TemplateArgumentDependence::Instantiation;
>  
> -  case Declaration:
> -    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
> -      return DC->isDependentContext();
> -    return getAsDecl()->getDeclContext()->isDependentContext();
> +  case Declaration: {
> +    auto *DC = dyn_cast<DeclContext>(getAsDecl());
> +    if (!DC)
> +      DC = getAsDecl()->getDeclContext();
> +    if (DC->isDependentContext())
> +      Deps = TemplateArgumentDependence::Dependent |
> +             TemplateArgumentDependence::Instantiation;
> +    return Deps;
> +  }
>  
>    case NullPtr:
> -    return false;
> -
>    case Integral:
> -    // Never dependent
> -    return false;
> +    return TemplateArgumentDependence::None;
>  
>    case Expression:
> -    return (getAsExpr()->isTypeDependent() || getAsExpr()-
> >isValueDependent() ||
> -            isa<PackExpansionExpr>(getAsExpr()));
> +    Deps = toTemplateArgumentDependence(getAsExpr()-
> >getDependence());
> +    if (isa<PackExpansionExpr>(getAsExpr()))
> +      Deps |= TemplateArgumentDependence::Dependent |
> +              TemplateArgumentDependence::Instantiation;
> +    return Deps;
>  
>    case Pack:
>      for (const auto &P : pack_elements())
> -      if (P.isDependent())
> -        return true;
> -    return false;
> +      Deps |= P.getDependence();
> +    return Deps;
>    }
> +  llvm_unreachable("unhandled ArgKind");
> +}
>  
> -  llvm_unreachable("Invalid TemplateArgument Kind!");
> +bool TemplateArgument::isDependent() const {
> +  return getDependence() & TemplateArgumentDependence::Dependent;
>  }
>  
>  bool TemplateArgument::isInstantiationDependent() const {
> -  switch (getKind()) {
> -  case Null:
> -    llvm_unreachable("Should not have a NULL template argument");
> -
> -  case Type:
> -    return getAsType()->isInstantiationDependentType();
> -
> -  case Template:
> -    return getAsTemplate().isInstantiationDependent();
> -
> -  case TemplateExpansion:
> -    return true;
> -
> -  case Declaration:
> -    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
> -      return DC->isDependentContext();
> -    return getAsDecl()->getDeclContext()->isDependentContext();
> -
> -  case NullPtr:
> -    return false;
> -
> -  case Integral:
> -    // Never dependent
> -    return false;
> -
> -  case Expression:
> -    return getAsExpr()->isInstantiationDependent();
> -
> -  case Pack:
> -    for (const auto &P : pack_elements())
> -      if (P.isInstantiationDependent())
> -        return true;
> -    return false;
> -  }
> -
> -  llvm_unreachable("Invalid TemplateArgument Kind!");
> +  return getDependence() &
> TemplateArgumentDependence::Instantiation;
>  }
>  
>  bool TemplateArgument::isPackExpansion() const {
> @@ -215,38 +192,7 @@ bool TemplateArgument::isPackExpansion() const {
>  }
>  
>  bool TemplateArgument::containsUnexpandedParameterPack() const {
> -  switch (getKind()) {
> -  case Null:
> -  case Declaration:
> -  case Integral:
> -  case TemplateExpansion:
> -  case NullPtr:
> -    break;
> -
> -  case Type:
> -    if (getAsType()->containsUnexpandedParameterPack())
> -      return true;
> -    break;
> -
> -  case Template:
> -    if (getAsTemplate().containsUnexpandedParameterPack())
> -      return true;
> -    break;
> -
> -  case Expression:
> -    if (getAsExpr()->containsUnexpandedParameterPack())
> -      return true;
> -    break;
> -
> -  case Pack:
> -    for (const auto &P : pack_elements())
> -      if (P.containsUnexpandedParameterPack())
> -        return true;
> -
> -    break;
> -  }
> -
> -  return false;
> +  return getDependence() &
> TemplateArgumentDependence::UnexpandedPack;
>  }
>  
>  Optional<unsigned> TemplateArgument::getNumTemplateExpansions()
> const {
> @@ -601,20 +547,14 @@ void
> ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation
> TemplateKWLoc) {
>  
>  void ASTTemplateKWAndArgsInfo::initializeFrom(
>      SourceLocation TemplateKWLoc, const TemplateArgumentListInfo
> &Info,
> -    TemplateArgumentLoc *OutArgArray, bool &Dependent,
> -    bool &InstantiationDependent, bool
> &ContainsUnexpandedParameterPack) {
> +    TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence
> &Deps) {
>    this->TemplateKWLoc = TemplateKWLoc;
>    LAngleLoc = Info.getLAngleLoc();
>    RAngleLoc = Info.getRAngleLoc();
>    NumTemplateArgs = Info.size();
>  
>    for (unsigned i = 0; i != NumTemplateArgs; ++i) {
> -    Dependent = Dependent || Info[i].getArgument().isDependent();
> -    InstantiationDependent = InstantiationDependent ||
> -                             Info[i].getArgument().isInstantiationDe
> pendent();
> -    ContainsUnexpandedParameterPack =
> -        ContainsUnexpandedParameterPack ||
> -        Info[i].getArgument().containsUnexpandedParameterPack();
> +    Deps |= Info[i].getArgument().getDependence();
>  
>      new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
>    }
> 
> diff  --git a/clang/lib/AST/TemplateName.cpp
> b/clang/lib/AST/TemplateName.cpp
> index 06e1dcec7449..afabc575b164 100644
> --- a/clang/lib/AST/TemplateName.cpp
> +++ b/clang/lib/AST/TemplateName.cpp
> @@ -11,8 +11,10 @@
>  //===---------------------------------------------------------------
> -------===//
>  
>  #include "clang/AST/TemplateName.h"
> +#include "clang/AST/Decl.h"
>  #include "clang/AST/DeclBase.h"
>  #include "clang/AST/DeclTemplate.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/NestedNameSpecifier.h"
>  #include "clang/AST/PrettyPrinter.h"
>  #include "clang/AST/TemplateBase.h"
> @@ -168,52 +170,54 @@ TemplateName
> TemplateName::getNameToSubstitute() const {
>    return TemplateName(Decl);
>  }
>  
> -bool TemplateName::isDependent() const {
> +TemplateNameDependence TemplateName::getDependence() const {
> +  auto D = TemplateNameDependence::None;
> +  switch (getKind()) {
> +  case TemplateName::NameKind::QualifiedTemplate:
> +    D |= toTemplateNameDependence(
> +        getAsQualifiedTemplateName()->getQualifier()-
> >getDependence());
> +    break;
> +  case TemplateName::NameKind::DependentTemplate:
> +    D |= toTemplateNameDependence(
> +        getAsDependentTemplateName()->getQualifier()-
> >getDependence());
> +    break;
> +  case TemplateName::NameKind::SubstTemplateTemplateParmPack:
> +    D |= TemplateNameDependence::UnexpandedPack;
> +    break;
> +  case TemplateName::NameKind::OverloadedTemplate:
> +    assert(false && "overloaded templates shouldn't survive to
> here.");
> +  default:
> +    break;
> +  }
>    if (TemplateDecl *Template = getAsTemplateDecl()) {
> -    if (isa<TemplateTemplateParmDecl>(Template))
> -      return true;
> +    if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
> +      D |= TemplateNameDependence::DependentInstantiation;
> +      if (TTP->isParameterPack())
> +        D |= TemplateNameDependence::UnexpandedPack;
> +    }
>      // FIXME: Hack, getDeclContext() can be null if Template is
> still
>      // initializing due to PCH reading, so we check it before using
> it.
>      // Should probably modify TemplateSpecializationType to allow
> constructing
>      // it without the isDependent() checking.
> -    return Template->getDeclContext() &&
> -           Template->getDeclContext()->isDependentContext();
> +    if (Template->getDeclContext() &&
> +        Template->getDeclContext()->isDependentContext())
> +      D |= TemplateNameDependence::DependentInstantiation;
> +  } else {
> +    D |= TemplateNameDependence::DependentInstantiation;
>    }
> +  return D;
> +}
>  
> -  assert(!getAsOverloadedTemplate() &&
> -         "overloaded templates shouldn't survive to here");
> -
> -  return true;
> +bool TemplateName::isDependent() const {
> +  return getDependence() & TemplateNameDependence::Dependent;
>  }
>  
>  bool TemplateName::isInstantiationDependent() const {
> -  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
> -    if (QTN->getQualifier()->isInstantiationDependent())
> -      return true;
> -  }
> -
> -  return isDependent();
> +  return getDependence() & TemplateNameDependence::Instantiation;
>  }
>  
>  bool TemplateName::containsUnexpandedParameterPack() const {
> -  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
> -    if (QTN->getQualifier()->containsUnexpandedParameterPack())
> -      return true;
> -  }
> -
> -  if (TemplateDecl *Template = getAsTemplateDecl()) {
> -    if (TemplateTemplateParmDecl *TTP
> -                                  =
> dyn_cast<TemplateTemplateParmDecl>(Template))
> -      return TTP->isParameterPack();
> -
> -    return false;
> -  }
> -
> -  if (DependentTemplateName *DTN = getAsDependentTemplateName())
> -    return DTN->getQualifier() &&
> -      DTN->getQualifier()->containsUnexpandedParameterPack();
> -
> -  return getAsSubstTemplateTemplateParmPack() != nullptr;
> +  return getDependence() & TemplateNameDependence::UnexpandedPack;
>  }
>  
>  void
> 
> diff  --git a/clang/lib/Sema/SemaOverload.cpp
> b/clang/lib/Sema/SemaOverload.cpp
> index b4be10deda32..9ecf5867e966 100644
> --- a/clang/lib/Sema/SemaOverload.cpp
> +++ b/clang/lib/Sema/SemaOverload.cpp
> @@ -10,10 +10,10 @@
>  //
>  //===---------------------------------------------------------------
> -------===//
>  
> -#include "clang/Sema/Overload.h"
>  #include "clang/AST/ASTContext.h"
>  #include "clang/AST/CXXInheritance.h"
>  #include "clang/AST/DeclObjC.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/Expr.h"
>  #include "clang/AST/ExprCXX.h"
>  #include "clang/AST/ExprObjC.h"
> @@ -25,6 +25,7 @@
>  #include "clang/Basic/TargetInfo.h"
>  #include "clang/Sema/Initialization.h"
>  #include "clang/Sema/Lookup.h"
> +#include "clang/Sema/Overload.h"
>  #include "clang/Sema/SemaInternal.h"
>  #include "clang/Sema/Template.h"
>  #include "clang/Sema/TemplateDeduction.h"
> @@ -12719,9 +12720,7 @@ bool Sema::buildOverloadedCallSet(Scope *S,
> Expr *Fn,
>        // base classes.
>        CallExpr *CE = CallExpr::Create(Context, Fn, Args,
> Context.DependentTy,
>                                        VK_RValue, RParenLoc);
> -      CE->setTypeDependent(true);
> -      CE->setValueDependent(true);
> -      CE->setInstantiationDependent(true);
> +      CE->addDependence(ExprDependence::TypeValueInstantiation);
>        *Result = CE;
>        return true;
>      }
> 
> diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp
> b/clang/lib/Serialization/ASTReaderStmt.cpp
> index fc83dc42d4d1..42803b1a3918 100644
> --- a/clang/lib/Serialization/ASTReaderStmt.cpp
> +++ b/clang/lib/Serialization/ASTReaderStmt.cpp
> @@ -11,7 +11,6 @@
>  //
>  //===---------------------------------------------------------------
> -------===//
>  
> -#include "clang/Serialization/ASTRecordReader.h"
>  #include "clang/AST/ASTConcept.h"
>  #include "clang/AST/ASTContext.h"
>  #include "clang/AST/AttrIterator.h"
> @@ -22,6 +21,7 @@
>  #include "clang/AST/DeclObjC.h"
>  #include "clang/AST/DeclTemplate.h"
>  #include "clang/AST/DeclarationName.h"
> +#include "clang/AST/DependencyFlags.h"
>  #include "clang/AST/Expr.h"
>  #include "clang/AST/ExprCXX.h"
>  #include "clang/AST/ExprObjC.h"
> @@ -49,6 +49,7 @@
>  #include "clang/Basic/TypeTraits.h"
>  #include "clang/Lex/Token.h"
>  #include "clang/Serialization/ASTBitCodes.h"
> +#include "clang/Serialization/ASTRecordReader.h"
>  #include "llvm/ADT/DenseMap.h"
>  #include "llvm/ADT/SmallString.h"
>  #include "llvm/ADT/SmallVector.h"
> @@ -511,10 +512,23 @@ void
> ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
>  void ASTStmtReader::VisitExpr(Expr *E) {
>    VisitStmt(E);
>    E->setType(Record.readType());
> -  E->setTypeDependent(Record.readInt());
> -  E->setValueDependent(Record.readInt());
> -  E->setInstantiationDependent(Record.readInt());
> -  E->ExprBits.ContainsUnexpandedParameterPack = Record.readInt();
> +
> +  // FIXME: write and read all DependentFlags with a single call.
> +  bool TypeDependent = Record.readInt();
> +  bool ValueDependent = Record.readInt();
> +  bool InstantiationDependent = Record.readInt();
> +  bool ContainsUnexpandedTemplateParameters = Record.readInt();
> +  auto Deps = ExprDependence::None;
> +  if (TypeDependent)
> +    Deps |= ExprDependence::Type;
> +  if (ValueDependent)
> +    Deps |= ExprDependence::Value;
> +  if (InstantiationDependent)
> +    Deps |= ExprDependence::Instantiation;
> +  if (ContainsUnexpandedTemplateParameters)
> +    Deps |= ExprDependence::UnexpandedPack;
> +  E->setDependence(Deps);
> +
>    E->setValueKind(static_cast<ExprValueKind>(Record.readInt()));
>    E->setObjectKind(static_cast<ExprObjectKind>(Record.readInt()));
>    assert(Record.getIdx() == NumExprFields &&
> 
> 
>         
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list