ilya-biryukov updated this revision to Diff 240958.
ilya-biryukov marked an inline comment as done and an inline comment as not 
done.
ilya-biryukov added a comment.

- Use different types for different AST categories
- Rename to getDependence


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71920/new/

https://reviews.llvm.org/D71920

Files:
  clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
  clang/include/clang/AST/DependencyFlags.h
  clang/include/clang/AST/Expr.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/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

Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ 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::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->setDependencies(Deps);
+
   E->setValueKind(static_cast<ExprValueKind>(Record.readInt()));
   E->setObjectKind(static_cast<ExprObjectKind>(Record.readInt()));
   assert(Record.getIdx() == NumExprFields &&
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ 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"
@@ -24,6 +24,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"
@@ -12694,9 +12695,7 @@
       // base classes.
       CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy,
                                       VK_RValue, RParenLoc);
-      CE->setTypeDependent(true);
-      CE->setValueDependent(true);
-      CE->setInstantiationDependent(true);
+      CE->addDependencies(ExprDependence::TypeValueInstantiation);
       *Result = CE;
       return true;
     }
Index: clang/lib/AST/TemplateName.cpp
===================================================================
--- clang/lib/AST/TemplateName.cpp
+++ clang/lib/AST/TemplateName.cpp
@@ -13,6 +13,7 @@
 #include "clang/AST/TemplateName.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 +169,48 @@
   return TemplateName(Decl);
 }
 
-bool TemplateName::isDependent() const {
+TemplateNameDependence TemplateName::getDependence() const {
+  auto F = TemplateNameDependence::None;
+  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+    F |= toTemplateNameDependence(QTN->getQualifier()->getDependence());
+  } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
+    if (DTN->getQualifier())
+      F |= toTemplateNameDependence(DTN->getQualifier()->getDependence());
+  }
+
   if (TemplateDecl *Template = getAsTemplateDecl()) {
-    if (isa<TemplateTemplateParmDecl>(Template))
-      return true;
+    if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+      F |= TemplateNameDependence::DependentInstantiation;
+      if (TTP->isParameterPack())
+        F |= 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())
+      F |= TemplateNameDependence::DependentInstantiation;
+  } else {
+    assert(!getAsOverloadedTemplate() &&
+           "overloaded templates shouldn't survive to here");
+    F |= TemplateNameDependence::DependentInstantiation;
   }
+  if (getAsSubstTemplateTemplateParmPack() != nullptr)
+    F |= TemplateNameDependence::UnexpandedPack;
+  return F;
+}
 
-  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
Index: clang/lib/AST/TemplateBase.cpp
===================================================================
--- clang/lib/AST/TemplateBase.cpp
+++ 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 @@
   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::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, 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().isInstantiationDependent();
-    ContainsUnexpandedParameterPack =
-        ContainsUnexpandedParameterPack ||
-        Info[i].getArgument().containsUnexpandedParameterPack();
+    Deps |= Info[i].getArgument().getDependence();
 
     new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
   }
Index: clang/lib/AST/NestedNameSpecifier.cpp
===================================================================
--- clang/lib/AST/NestedNameSpecifier.cpp
+++ 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 @@
   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
Index: clang/lib/AST/ExprObjC.cpp
===================================================================
--- clang/lib/AST/ExprObjC.cpp
+++ 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 @@
       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;
-
+    addDependencies(turnTypeToValueDependence(Elements[I]->getDependence()));
     SaveElements[I] = Elements[I];
   }
 }
@@ -67,16 +62,11 @@
   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;
+    addDependencies(Deps);
 
     KeyValues[I].Key = VK[I].Key;
     KeyValues[I].Value = VK[I].Value;
@@ -183,15 +173,7 @@
   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;
-
+    addDependencies(Args[I]->getDependence());
     MyArgs[I] = Args[I];
   }
 
Index: clang/lib/AST/ExprCXX.cpp
===================================================================
--- clang/lib/AST/ExprCXX.cpp
+++ clang/lib/AST/ExprCXX.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.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"
@@ -193,36 +194,20 @@
   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)
+      addDependencies(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;
+    addDependencies(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;
+    addDependencies(PlacementArgs[I]->getDependence() & ~ExprDependence::Type);
 
     getTrailingObjects<Stmt *>()[placementNewArgsOffset() + I] =
         PlacementArgs[I];
@@ -473,11 +458,8 @@
     // 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))
+        addDependencies(ExprDependence::TypeValueInstantiation);
     }
 
     // Copy the results to the trailing array past UnresolvedLookupExpr
@@ -490,21 +472,11 @@
   // 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);
+    addDependencies(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);
   }
@@ -538,14 +510,11 @@
   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)
+      addDependencies(ExprDependence::UnexpandedPack);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -1113,13 +1082,7 @@
   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;
+    addDependencies(Args[I]->getDependence() & ~ExprDependence::Type);
 
     TrailingArgs[I] = Args[I];
   }
@@ -1369,7 +1332,7 @@
   auto **StoredArgs = getTrailingObjects<Expr *>();
   for (unsigned I = 0; I != Args.size(); ++I) {
     if (Args[I]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      addDependencies(ExprDependence::UnexpandedPack);
 
     StoredArgs[I] = Args[I];
   }
@@ -1415,14 +1378,12 @@
   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)
+      addDependencies(ExprDependence::UnexpandedPack);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -1703,13 +1664,8 @@
   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);
-
+    addDependencies(toExprDependence(Args[I]->getType()->getDependence()) &
+                    ~ExprDependence::Type);
     ToArgs[I] = Args[I];
   }
 }
@@ -1798,24 +1754,22 @@
   this->ArgsAsWritten = ArgsAsWritten;
   std::uninitialized_copy(Converted.begin(), Converted.end(),
                           getTrailingObjects<TemplateArgument>());
-  bool IsInstantiationDependent = false;
-  bool ContainsUnexpandedParameterPack = false;
-  for (const TemplateArgumentLoc& LocInfo : ArgsAsWritten->arguments()) {
-    if (LocInfo.getArgument().isInstantiationDependent())
-      IsInstantiationDependent = true;
-    if (LocInfo.getArgument().containsUnexpandedParameterPack())
-      ContainsUnexpandedParameterPack = true;
-    if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
+  auto Deps = TemplateArgumentDependence::None;
+  const auto InterestingDeps = TemplateArgumentDependence::Instantiation |
+                               TemplateArgumentDependence::UnexpandedPack;
+  for (const TemplateArgumentLoc &LocInfo : ArgsAsWritten->arguments()) {
+    Deps |= LocInfo.getArgument().getDependence() & InterestingDeps;
+    if (Deps == InterestingDeps)
       break;
   }
 
   // Currently guaranteed by the fact concepts can only be at namespace-scope.
-  assert(!NestedNameSpec ||
-         (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
-          !NestedNameSpec.getNestedNameSpecifier()
-              ->containsUnexpandedParameterPack()));
-  setInstantiationDependent(IsInstantiationDependent);
-  setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
+  assert(
+      !NestedNameSpec ||
+      (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
+       !NestedNameSpec.getNestedNameSpecifier()
+            ->containsUnexpandedParameterPack()));
+  addDependencies(toExprDependence(Deps & InterestingDeps));
   assert((!isValueDependent() || isInstantiationDependent()) &&
          "should not be value-dependent");
 }
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ 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"
@@ -368,13 +369,11 @@
 /// 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:
@@ -386,36 +385,25 @@
 
   //  (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.
@@ -432,8 +420,7 @@
          Var->getType()->isReferenceType())) {
       if (const Expr *Init = Var->getAnyInitializer())
         if (Init->isValueDependent()) {
-          ValueDependent = true;
-          InstantiationDependent = true;
+          R |= ExprDependence::ValueInstantiation;
         }
     }
 
@@ -442,39 +429,21 @@
     //         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,
@@ -492,7 +461,7 @@
       RefersToEnclosingVariableOrCapture;
   DeclRefExprBits.NonOdrUseReason = NOUR;
   DeclRefExprBits.Loc = L;
-  computeDependence(Ctx);
+  addDependencies(computeDeclRefDependence(Ctx, getDecl(), getType()));
 }
 
 DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
@@ -511,9 +480,9 @@
         NestedNameSpecifierLoc(QualifierLoc);
     auto *NNS = QualifierLoc.getNestedNameSpecifier();
     if (NNS->isInstantiationDependent())
-      ExprBits.InstantiationDependent = true;
+      addDependencies(ExprDependence::Instantiation);
     if (NNS->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      addDependencies(ExprDependence::UnexpandedPack);
   }
   DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
   if (FoundD)
@@ -524,22 +493,19 @@
       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");
+    addDependencies(toExprDependence(Deps));
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
   }
   DeclRefExprBits.HadMultipleCandidates = 0;
-
-  computeDependence(Ctx);
+  addDependencies(computeDeclRefDependence(Ctx, getDecl(), getType()));
 }
 
 DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
@@ -1357,11 +1323,11 @@
 
   setCallee(Fn);
   for (unsigned I = 0; I != NumPreArgs; ++I) {
-    updateDependenciesFromArg(PreArgs[I]);
+    addDependencies(PreArgs[I]->getDependence());
     setPreArg(I, PreArgs[I]);
   }
   for (unsigned I = 0; I != Args.size(); ++I) {
-    updateDependenciesFromArg(Args[I]);
+    addDependencies(Args[I]->getDependence());
     setArg(I, Args[I]);
   }
   for (unsigned I = Args.size(); I != NumArgs; ++I) {
@@ -1429,17 +1395,6 @@
   }
 }
 
-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();
 
@@ -1585,9 +1540,9 @@
 
   for (unsigned i = 0; i != exprs.size(); ++i) {
     if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent())
-      ExprBits.ValueDependent = true;
+      addDependencies(ExprDependence::Value);
     if (exprs[i]->containsUnexpandedParameterPack())
-      ExprBits.ContainsUnexpandedParameterPack = true;
+      addDependencies(ExprDependence ::UnexpandedPack);
 
     setIndexExpr(i, exprs[i]);
   }
@@ -1629,8 +1584,7 @@
       if (D) {
         for (const auto *I : D->specific_attrs<AlignedAttr>()) {
           if (I->isAlignmentDependent()) {
-            setValueDependent(true);
-            setInstantiationDependent(true);
+            addDependencies(ExprDependence::ValueInstantiation);
             break;
           }
         }
@@ -1683,20 +1637,19 @@
     // 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->removeDependencies(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->addDependencies(ExprDependence::TypeValueInstantiation);
     else if (QualifierLoc &&
              QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
-      E->setInstantiationDependent(true);
+      E->addDependencies(ExprDependence::Instantiation);
 
     E->MemberExprBits.HasQualifierOrFoundDecl = true;
 
@@ -1710,15 +1663,12 @@
       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->addDependencies(ExprDependence::Instantiation);
   } else if (TemplateKWLoc.isValid()) {
     E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -2236,16 +2186,8 @@
     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)
+    addDependencies(initExprs[I]->getDependence());
 
   InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end());
 }
@@ -4159,15 +4101,7 @@
 {
   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;
-
+    addDependencies(args[i]->getDependence());
     SubExprs[i] = args[i];
   }
 }
@@ -4311,13 +4245,12 @@
     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;
+      addDependencies(Deps);
 
       // Copy the index expressions into permanent storage.
       *Child++ = IndexExprs[IndexIdx++];
@@ -4325,19 +4258,11 @@
       // 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;
+      addDependencies(Deps);
 
       // Copy the start/end expressions into permanent storage.
       *Child++ = IndexExprs[IndexIdx++];
@@ -4475,15 +4400,7 @@
   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;
-
+    addDependencies(Exprs[I]->getDependence());
     getTrailingObjects<Stmt *>()[I] = Exprs[I];
   }
 }
@@ -4570,14 +4487,7 @@
     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;
+    addDependencies(E->getDependence());
 
     if (isa<OpaqueValueExpr>(E))
       assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr &&
@@ -4618,15 +4528,7 @@
 {
   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;
-
+    addDependencies(args[i]->getDependence());
     SubExprs[i] = args[i];
   }
 }
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -8331,11 +8331,7 @@
     // 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->setDependencies(FromE->getDependence());
   }
 
   // Record the imported statement object.
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ 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>
@@ -1464,20 +1465,12 @@
     /// 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;
+    /// Store information on the type dependency.
+    /*TypeDependence*/ unsigned Dependence : TypeDependenceBits;
 
     /// 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;
-
     /// True if the cache (i.e. the bitfields here starting with
     /// 'Cache') is valid.
     mutable unsigned CacheValid : 1;
@@ -1823,11 +1816,17 @@
        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;
+
     TypeBits.TC = tc;
-    TypeBits.Dependent = Dependent;
-    TypeBits.InstantiationDependent = Dependent || InstantiationDependent;
+    TypeBits.Dependence = static_cast<unsigned>(Deps);
     TypeBits.VariablyModified = VariablyModified;
-    TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
     TypeBits.CacheValid = false;
     TypeBits.CachedLocalOrUnnamed = false;
     TypeBits.CachedLinkage = NoLinkage;
@@ -1838,18 +1837,32 @@
   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::Instantiation);
   }
 
   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 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:
@@ -1884,7 +1897,7 @@
   ///
   /// 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
@@ -2135,16 +2148,22 @@
   /// 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
Index: clang/include/clang/AST/TemplateName.h
===================================================================
--- clang/include/clang/AST/TemplateName.h
+++ 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 @@
   /// the template, including any default template arguments.
   TemplateName getNameToSubstitute() const;
 
+  TemplateNameDependence getDependence() const;
+
   /// Determines whether this is a dependent template name.
   bool isDependent() const;
 
Index: clang/include/clang/AST/TemplateBase.h
===================================================================
--- clang/include/clang/AST/TemplateBase.h
+++ 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 @@
   /// 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 @@
                       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,
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ 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 @@
 
     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;
Index: clang/include/clang/AST/NestedNameSpecifier.h
===================================================================
--- clang/include/clang/AST/NestedNameSpecifier.h
+++ 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 @@
     return nullptr;
   }
 
+  NestedNameSpecifierDependence getDependence() const;
+
   /// Whether this nested name specifier refers to a dependent
   /// type or not.
   bool isDependent() const;
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ 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 @@
        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 @@
     TR = t;
   }
 
+  ExprDependence getDependence() const {
+    return static_cast<ExprDependence>(ExprBits.Dependent);
+  }
+
+  void setDependencies(ExprDependence Deps) {
+    ExprBits.Dependent = static_cast<unsigned>(Deps);
+  }
+  void addDependencies(ExprDependence Deps) {
+    ExprBits.Dependent |= static_cast<unsigned>(Deps);
+  }
+  void removeDependencies(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 @@
   /// @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 @@
   ///   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 @@
   /// \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 @@
   /// 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
@@ -1210,10 +1215,6 @@
   /// 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,
@@ -2553,8 +2554,6 @@
   /// 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
@@ -4462,13 +4461,8 @@
     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)
+      addDependencies(expr->getDependence());
   }
 
   /// Reserve space for some number of initializers.
Index: clang/include/clang/AST/DependencyFlags.h
===================================================================
--- /dev/null
+++ clang/include/clang/AST/DependencyFlags.h
@@ -0,0 +1,112 @@
+//===--- 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;
+
+#define LLVM_COMMON_DEPENDENCE(NAME)                                           \
+  struct NAME##Scope {                                                         \
+    enum NAME {                                                                \
+      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(TypeDependence)
+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.
+  return toExprDependence(static_cast<TemplateArgumentDependence>(TD));
+}
+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);
+}
+
+inline TemplateArgumentDependence
+toTemplateArgumentDependence(TypeDependence D) {
+  // This works because both classes share the same bit representation.
+  return static_cast<TemplateArgumentDependence>(D);
+}
+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
Index: clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
+++ clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
@@ -10,12 +10,12 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 
-using namespace clang::ast_matchers;
-
 namespace clang {
 namespace tidy {
 namespace hicpp {
 
+using namespace clang::ast_matchers;
+
 void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus)
     return;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to