Revert "[Concepts] Constraint Enforcement & Diagnostics"

This reverts commit ffa214ef22892d75340dc6720271863901dc2c90, it was
causing ASAN test failures on sanitizer-x86_64-linux-bootstrap.
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index cbe2659..848ccf5 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -12,13 +12,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "clang/Sema/Template.h"
 #include "clang/AST/ExprCXX.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerUnion.h"
 using namespace clang;
 using namespace sema;
 
@@ -49,367 +46,80 @@
   return true;
 }
 
-template <typename AtomicEvaluator>
-static bool
-calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
-                                ConstraintSatisfaction &Satisfaction,
-                                AtomicEvaluator &&Evaluator) {
+bool
+Sema::CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
+                                      MultiLevelTemplateArgumentList &MLTAL,
+                                      Expr *ConstraintExpr,
+                                      bool &IsSatisfied) {
   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
 
   if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
-    if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
-      if (calculateConstraintSatisfaction(S, BO->getLHS(), Satisfaction,
-                                          Evaluator))
+    if (BO->getOpcode() == BO_LAnd) {
+      if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),
+                                          IsSatisfied))
         return true;
-
-      bool IsLHSSatisfied = Satisfaction.IsSatisfied;
-
-      if (BO->getOpcode() == BO_LOr && IsLHSSatisfied)
-        // [temp.constr.op] p3
-        //    A disjunction is a constraint taking two operands. To determine if
-        //    a disjunction is satisfied, the satisfaction of the first operand
-        //    is checked. If that is satisfied, the disjunction is satisfied.
-        //    Otherwise, the disjunction is satisfied if and only if the second
-        //    operand is satisfied.
+      if (!IsSatisfied)
         return false;
-
-      if (BO->getOpcode() == BO_LAnd && !IsLHSSatisfied)
-        // [temp.constr.op] p2
-        //    A conjunction is a constraint taking two operands. To determine if
-        //    a conjunction is satisfied, the satisfaction of the first operand
-        //    is checked. If that is not satisfied, the conjunction is not
-        //    satisfied. Otherwise, the conjunction is satisfied if and only if
-        //    the second operand is satisfied.
+      return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),
+                                             IsSatisfied);
+    } else if (BO->getOpcode() == BO_LOr) {
+      if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),
+                                          IsSatisfied))
+        return true;
+      if (IsSatisfied)
         return false;
-
-      return calculateConstraintSatisfaction(S, BO->getRHS(), Satisfaction,
-          std::forward<AtomicEvaluator>(Evaluator));
+      return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),
+                                             IsSatisfied);
     }
   }
   else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
-    return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
-        std::forward<AtomicEvaluator>(Evaluator));
-
-  // An atomic constraint expression
-  ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
-
-  if (SubstitutedAtomicExpr.isInvalid())
-    return true;
-
-  if (!SubstitutedAtomicExpr.isUsable())
-    // Evaluator has decided satisfaction without yielding an expression.
-    return false;
+    return CalculateConstraintSatisfaction(NamedConcept, MLTAL, C->getSubExpr(),
+                                           IsSatisfied);
 
   EnterExpressionEvaluationContext ConstantEvaluated(
-      S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+      *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+  // Atomic constraint - substitute arguments and check satisfaction.
+  ExprResult E;
+  {
+    TemplateDeductionInfo Info(ConstraintExpr->getBeginLoc());
+    InstantiatingTemplate Inst(*this, ConstraintExpr->getBeginLoc(),
+                               InstantiatingTemplate::ConstraintSubstitution{},
+                               NamedConcept, Info,
+                               ConstraintExpr->getSourceRange());
+    if (Inst.isInvalid())
+      return true;
+    // We do not want error diagnostics escaping here.
+    Sema::SFINAETrap Trap(*this);
+
+    E = SubstExpr(ConstraintExpr, MLTAL);
+    if (E.isInvalid() || Trap.hasErrorOccurred()) {
+      // C++2a [temp.constr.atomic]p1
+      //   ...If substitution results in an invalid type or expression, the
+      //   constraint is not satisfied.
+      IsSatisfied = false;
+      return false;
+    }
+  }
+
+  if (!CheckConstraintExpression(E.get()))
+    return true;
+
   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
   Expr::EvalResult EvalResult;
   EvalResult.Diag = &EvaluationDiags;
-  if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
-      // C++2a [temp.constr.atomic]p1
-      //   ...E shall be a constant expression of type bool.
-    S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
-           diag::err_non_constant_constraint_expression)
-        << SubstitutedAtomicExpr.get()->getSourceRange();
+  if (!E.get()->EvaluateAsRValue(EvalResult, Context)) {
+    // C++2a [temp.constr.atomic]p1
+    //   ...E shall be a constant expression of type bool.
+    Diag(E.get()->getBeginLoc(),
+         diag::err_non_constant_constraint_expression)
+        << E.get()->getSourceRange();
     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
-      S.Diag(PDiag.first, PDiag.second);
+      Diag(PDiag.first, PDiag.second);
     return true;
   }
 
-  Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
-  if (!Satisfaction.IsSatisfied)
-    Satisfaction.Details.emplace_back(ConstraintExpr,
-                                      SubstitutedAtomicExpr.get());
+  IsSatisfied = EvalResult.Val.getInt().getBoolValue();
 
   return false;
-}
-
-template <typename TemplateDeclT>
-static bool calculateConstraintSatisfaction(
-    Sema &S, TemplateDeclT *Template, ArrayRef<TemplateArgument> TemplateArgs,
-    SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
-    const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
-  return calculateConstraintSatisfaction(
-      S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
-        EnterExpressionEvaluationContext ConstantEvaluated(
-            S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
-
-        // Atomic constraint - substitute arguments and check satisfaction.
-        ExprResult SubstitutedExpression;
-        {
-          TemplateDeductionInfo Info(TemplateNameLoc);
-          Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
-              Sema::InstantiatingTemplate::ConstraintSubstitution{}, Template,
-              Info, AtomicExpr->getSourceRange());
-          if (Inst.isInvalid())
-            return ExprError();
-          // We do not want error diagnostics escaping here.
-          Sema::SFINAETrap Trap(S);
-          SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
-                                              MLTAL);
-          if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
-            // C++2a [temp.constr.atomic]p1
-            //   ...If substitution results in an invalid type or expression, the
-            //   constraint is not satisfied.
-            if (!Trap.hasErrorOccurred())
-              // A non-SFINAE error has occured as a result of this
-              // substitution.
-              return ExprError();
-
-            PartialDiagnosticAt SubstDiag{SourceLocation(),
-                                          PartialDiagnostic::NullDiagnostic()};
-            Info.takeSFINAEDiagnostic(SubstDiag);
-            // FIXME: Concepts: This is an unfortunate consequence of there
-            //  being no serialization code for PartialDiagnostics and the fact
-            //  that serializing them would likely take a lot more storage than
-            //  just storing them as strings. We would still like, in the
-            //  future, to serialize the proper PartialDiagnostic as serializing
-            //  it as a string defeats the purpose of the diagnostic mechanism.
-            SmallString<128> DiagString;
-            DiagString = ": ";
-            SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
-            Satisfaction.Details.emplace_back(
-                AtomicExpr,
-                new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
-                        SubstDiag.first,
-                        std::string(DiagString.begin(), DiagString.end())});
-            Satisfaction.IsSatisfied = false;
-            return ExprEmpty();
-          }
-        }
-
-        if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
-          return ExprError();
-
-        return SubstitutedExpression;
-      });
-}
-
-template<typename TemplateDeclT>
-static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
-                                        ArrayRef<const Expr *> ConstraintExprs,
-                                        ArrayRef<TemplateArgument> TemplateArgs,
-                                        SourceRange TemplateIDRange,
-                                        ConstraintSatisfaction &Satisfaction) {
-  if (ConstraintExprs.empty()) {
-    Satisfaction.IsSatisfied = true;
-    return false;
-  }
-
-  for (auto& Arg : TemplateArgs)
-    if (Arg.isInstantiationDependent()) {
-      // No need to check satisfaction for dependent constraint expressions.
-      Satisfaction.IsSatisfied = true;
-      return false;
-    }
-
-  Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
-      Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
-      TemplateIDRange);
-  if (Inst.isInvalid())
-    return true;
-
-  MultiLevelTemplateArgumentList MLTAL;
-  MLTAL.addOuterTemplateArguments(TemplateArgs);
-
-  for (const Expr *ConstraintExpr : ConstraintExprs) {
-    if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
-                                        TemplateIDRange.getBegin(), MLTAL,
-                                        ConstraintExpr, Satisfaction))
-      return true;
-    if (!Satisfaction.IsSatisfied)
-      // [temp.constr.op] p2
-      //   [...] To determine if a conjunction is satisfied, the satisfaction
-      //   of the first operand is checked. If that is not satisfied, the
-      //   conjunction is not satisfied. [...]
-      return false;
-  }
-  return false;
-}
-
-bool Sema::CheckConstraintSatisfaction(TemplateDecl *Template,
-                                       ArrayRef<const Expr *> ConstraintExprs,
-                                       ArrayRef<TemplateArgument> TemplateArgs,
-                                       SourceRange TemplateIDRange,
-                                       ConstraintSatisfaction &Satisfaction) {
-  return ::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
-                                       TemplateArgs, TemplateIDRange,
-                                       Satisfaction);
-}
-
-bool
-Sema::CheckConstraintSatisfaction(ClassTemplatePartialSpecializationDecl* Part,
-                                  ArrayRef<const Expr *> ConstraintExprs,
-                                  ArrayRef<TemplateArgument> TemplateArgs,
-                                  SourceRange TemplateIDRange,
-                                  ConstraintSatisfaction &Satisfaction) {
-  return ::CheckConstraintSatisfaction(*this, Part, ConstraintExprs,
-                                       TemplateArgs, TemplateIDRange,
-                                       Satisfaction);
-}
-
-bool
-Sema::CheckConstraintSatisfaction(VarTemplatePartialSpecializationDecl* Partial,
-                                  ArrayRef<const Expr *> ConstraintExprs,
-                                  ArrayRef<TemplateArgument> TemplateArgs,
-                                  SourceRange TemplateIDRange,
-                                  ConstraintSatisfaction &Satisfaction) {
-  return ::CheckConstraintSatisfaction(*this, Partial, ConstraintExprs,
-                                       TemplateArgs, TemplateIDRange,
-                                       Satisfaction);
-}
-
-bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
-                                       ConstraintSatisfaction &Satisfaction) {
-  return calculateConstraintSatisfaction(
-      *this, ConstraintExpr, Satisfaction,
-      [](const Expr *AtomicExpr) -> ExprResult {
-        return ExprResult(const_cast<Expr *>(AtomicExpr));
-      });
-}
-
-bool Sema::EnsureTemplateArgumentListConstraints(
-    TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
-    SourceRange TemplateIDRange) {
-  ConstraintSatisfaction Satisfaction;
-  llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
-  TD->getAssociatedConstraints(AssociatedConstraints);
-  if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
-                                  TemplateIDRange, Satisfaction))
-    return true;
-
-  if (!Satisfaction.IsSatisfied) {
-    SmallString<128> TemplateArgString;
-    TemplateArgString = " ";
-    TemplateArgString += getTemplateArgumentBindingsText(
-        TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
-
-    Diag(TemplateIDRange.getBegin(),
-         diag::err_template_arg_list_constraints_not_satisfied)
-        << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
-        << TemplateArgString << TemplateIDRange;
-    DiagnoseUnsatisfiedConstraint(Satisfaction);
-    return true;
-  }
-  return false;
-}
-
-static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
-                                                        Expr *SubstExpr,
-                                                        bool First = true) {
-  SubstExpr = SubstExpr->IgnoreParenImpCasts();
-  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
-    switch (BO->getOpcode()) {
-    // These two cases will in practice only be reached when using fold
-    // expressions with || and &&, since otherwise the || and && will have been
-    // broken down into atomic constraints during satisfaction checking.
-    case BO_LOr:
-      // Or evaluated to false - meaning both RHS and LHS evaluated to false.
-      diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
-      diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
-                                                  /*First=*/false);
-      return;
-    case BO_LAnd:
-      bool LHSSatisfied;
-      BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
-      if (LHSSatisfied) {
-        // LHS is true, so RHS must be false.
-        diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
-        return;
-      }
-      // LHS is false
-      diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
-
-      // RHS might also be false
-      bool RHSSatisfied;
-      BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
-      if (!RHSSatisfied)
-        diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
-                                                    /*First=*/false);
-      return;
-    case BO_GE:
-    case BO_LE:
-    case BO_GT:
-    case BO_LT:
-    case BO_EQ:
-    case BO_NE:
-      if (BO->getLHS()->getType()->isIntegerType() &&
-          BO->getRHS()->getType()->isIntegerType()) {
-        Expr::EvalResult SimplifiedLHS;
-        Expr::EvalResult SimplifiedRHS;
-        BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
-        BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
-        if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
-          S.Diag(SubstExpr->getBeginLoc(),
-                 diag::note_atomic_constraint_evaluated_to_false_elaborated)
-              << (int)First << SubstExpr
-              << SimplifiedLHS.Val.getInt().toString(10)
-              << BinaryOperator::getOpcodeStr(BO->getOpcode())
-              << SimplifiedRHS.Val.getInt().toString(10);
-          return;
-        }
-      }
-      break;
-
-    default:
-      break;
-    }
-  } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
-    if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
-      S.Diag(
-          CSE->getSourceRange().getBegin(),
-          diag::
-          note_single_arg_concept_specialization_constraint_evaluated_to_false)
-          << (int)First
-          << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
-          << CSE->getNamedConcept();
-    } else {
-      S.Diag(SubstExpr->getSourceRange().getBegin(),
-             diag::note_concept_specialization_constraint_evaluated_to_false)
-          << (int)First << CSE;
-    }
-    S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
-    return;
-  }
-
-  S.Diag(SubstExpr->getSourceRange().getBegin(),
-         diag::note_atomic_constraint_evaluated_to_false)
-      << (int)First << SubstExpr;
-}
-
-template<typename SubstitutionDiagnostic>
-static void diagnoseUnsatisfiedConstraintExpr(
-    Sema &S, const Expr *E,
-    const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
-    bool First = true) {
-  if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
-    S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
-        << Diag->second;
-    return;
-  }
-
-  diagnoseWellFormedUnsatisfiedConstraintExpr(S,
-      Record.template get<Expr *>(), First);
-}
-
-void Sema::DiagnoseUnsatisfiedConstraint(
-    const ConstraintSatisfaction& Satisfaction) {
-  assert(!Satisfaction.IsSatisfied &&
-         "Attempted to diagnose a satisfied constraint");
-  bool First = true;
-  for (auto &Pair : Satisfaction.Details) {
-    diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
-    First = false;
-  }
-}
-
-void Sema::DiagnoseUnsatisfiedConstraint(
-    const ASTConstraintSatisfaction &Satisfaction) {
-  assert(!Satisfaction.IsSatisfied &&
-         "Attempted to diagnose a satisfied constraint");
-  bool First = true;
-  for (auto &Pair : Satisfaction) {
-    diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
-    First = false;
-  }
 }
\ No newline at end of file
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6a718db..e3f57e3 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -14486,16 +14486,8 @@
       std::string InnerCondDescription;
       std::tie(InnerCond, InnerCondDescription) =
         findFailedBooleanCondition(Converted.get());
-      if (InnerCond && isa<ConceptSpecializationExpr>(InnerCond)) {
-        // Drill down into concept specialization expressions to see why they
-        // weren't satisfied.
-        Diag(StaticAssertLoc, diag::err_static_assert_failed)
-          << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
-        ConstraintSatisfaction Satisfaction;
-        if (!CheckConstraintSatisfaction(InnerCond, Satisfaction))
-          DiagnoseUnsatisfiedConstraint(Satisfaction);
-      } else if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
-                           && !isa<IntegerLiteral>(InnerCond)) {
+      if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
+                    && !isa<IntegerLiteral>(InnerCond)) {
         Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
           << InnerCondDescription << !AssertMessage
           << Msg.str() << InnerCond->getSourceRange();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4417d22..1547108 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -591,12 +591,6 @@
     TemplateArgumentList *TemplateArgs;
     unsigned CallArgIndex;
   };
-  // Structure used by DeductionFailureInfo to store information about
-  // unsatisfied constraints.
-  struct CNSInfo {
-    TemplateArgumentList *TemplateArgs;
-    ConstraintSatisfaction Satisfaction;
-  };
 }
 
 /// Convert from Sema's representation of template deduction information
@@ -667,14 +661,6 @@
     }
     break;
 
-  case Sema::TDK_ConstraintsNotSatisfied: {
-    CNSInfo *Saved = new (Context) CNSInfo;
-    Saved->TemplateArgs = Info.take();
-    Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction;
-    Result.Data = Saved;
-    break;
-  }
-
   case Sema::TDK_Success:
   case Sema::TDK_NonDependentConversionFailure:
     llvm_unreachable("not a deduction failure");
@@ -715,15 +701,6 @@
     }
     break;
 
-  case Sema::TDK_ConstraintsNotSatisfied:
-    // FIXME: Destroy the template argument list?
-    Data = nullptr;
-    if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
-      Diag->~PartialDiagnosticAt();
-      HasDiagnostic = false;
-    }
-    break;
-
   // Unhandled
   case Sema::TDK_MiscellaneousDeductionFailure:
     break;
@@ -749,7 +726,6 @@
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_CUDATargetMismatch:
   case Sema::TDK_NonDependentConversionFailure:
-  case Sema::TDK_ConstraintsNotSatisfied:
     return TemplateParameter();
 
   case Sema::TDK_Incomplete:
@@ -793,9 +769,6 @@
   case Sema::TDK_SubstitutionFailure:
     return static_cast<TemplateArgumentList*>(Data);
 
-  case Sema::TDK_ConstraintsNotSatisfied:
-    return static_cast<CNSInfo*>(Data)->TemplateArgs;
-
   // Unhandled
   case Sema::TDK_MiscellaneousDeductionFailure:
     break;
@@ -816,7 +789,6 @@
   case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_CUDATargetMismatch:
   case Sema::TDK_NonDependentConversionFailure:
-  case Sema::TDK_ConstraintsNotSatisfied:
     return nullptr;
 
   case Sema::TDK_IncompletePack:
@@ -848,7 +820,6 @@
   case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_CUDATargetMismatch:
   case Sema::TDK_NonDependentConversionFailure:
-  case Sema::TDK_ConstraintsNotSatisfied:
     return nullptr;
 
   case Sema::TDK_Inconsistent:
@@ -1284,8 +1255,6 @@
     return NewTarget != OldTarget;
   }
 
-  // TODO: Concepts: Check function trailing requires clauses here.
-
   // The signatures match; this is not an overload.
   return false;
 }
@@ -10380,21 +10349,6 @@
     MaybeEmitInheritedConstructorNote(S, Found);
     return;
 
-  case Sema::TDK_ConstraintsNotSatisfied: {
-    // Format the template argument list into the argument string.
-    SmallString<128> TemplateArgString;
-    TemplateArgumentList *Args = DeductionFailure.getTemplateArgumentList();
-    TemplateArgString = " ";
-    TemplateArgString += S.getTemplateArgumentBindingsText(
-        getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
-    S.Diag(Templated->getLocation(),
-           diag::note_ovl_candidate_unsatisfied_constraints)
-        << TemplateArgString;
-
-    S.DiagnoseUnsatisfiedConstraint(
-        static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
-    return;
-  }
   case Sema::TDK_TooManyArguments:
   case Sema::TDK_TooFewArguments:
     DiagnoseArityMismatch(S, Found, Templated, NumArgs);
@@ -10847,7 +10801,6 @@
 
   case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_DeducedMismatch:
-  case Sema::TDK_ConstraintsNotSatisfied:
   case Sema::TDK_DeducedMismatchNested:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_MiscellaneousDeductionFailure:
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 3003a9a..3f2d386 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3210,7 +3210,8 @@
 
   TemplateDecl *Template = Name.getAsTemplateDecl();
   if (!Template || isa<FunctionTemplateDecl>(Template) ||
-      isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) {
+      isa<VarTemplateDecl>(Template) ||
+      isa<ConceptDecl>(Template)) {
     // We might have a substituted template template parameter pack. If so,
     // build a template specialization type for it.
     if (Name.getAsSubstTemplateTemplateParmPack())
@@ -3226,8 +3227,7 @@
   // template.
   SmallVector<TemplateArgument, 4> Converted;
   if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
-                                false, Converted,
-                                /*UpdateArgsWithConversion=*/true))
+                                false, Converted))
     return QualType();
 
   QualType CanonType;
@@ -3235,7 +3235,6 @@
   bool InstantiationDependent = false;
   if (TypeAliasTemplateDecl *AliasTemplate =
           dyn_cast<TypeAliasTemplateDecl>(Template)) {
-
     // Find the canonical type for this type alias template specialization.
     TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
     if (Pattern->isInvalidDecl())
@@ -3873,8 +3872,7 @@
   // template.
   SmallVector<TemplateArgument, 4> Converted;
   if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs,
-                                false, Converted,
-                                /*UpdateArgsWithConversion=*/true))
+                                false, Converted))
     return true;
 
   // Find the variable template (partial) specialization declaration that
@@ -4045,7 +4043,7 @@
   if (CheckTemplateArgumentList(
           Template, TemplateNameLoc,
           const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
-          Converted, /*UpdateArgsWithConversion=*/true))
+          Converted))
     return true;
 
   // Find the variable template specialization declaration that
@@ -4236,7 +4234,7 @@
                                 /*UpdateArgsWithConversion=*/false))
     return ExprError();
 
-  ConstraintSatisfaction Satisfaction;
+  Optional<bool> IsSatisfied;
   bool AreArgsDependent = false;
   for (TemplateArgument &Arg : Converted) {
     if (Arg.isDependent()) {
@@ -4244,21 +4242,25 @@
       break;
     }
   }
-  if (!AreArgsDependent &&
-      CheckConstraintSatisfaction(NamedConcept,
-                                  {NamedConcept->getConstraintExpr()},
-                                  Converted,
-                                  SourceRange(SS.isSet() ? SS.getBeginLoc() :
-                                                           ConceptNameLoc,
-                                              TemplateArgs->getRAngleLoc()),
-                                  Satisfaction))
+  if (!AreArgsDependent) {
+    InstantiatingTemplate Inst(*this, ConceptNameLoc,
+        InstantiatingTemplate::ConstraintsCheck{}, NamedConcept, Converted,
+        SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameLoc,
+                    TemplateArgs->getRAngleLoc()));
+    MultiLevelTemplateArgumentList MLTAL;
+    MLTAL.addOuterTemplateArguments(Converted);
+    bool Satisfied;
+    if (CalculateConstraintSatisfaction(NamedConcept, MLTAL,
+                                        NamedConcept->getConstraintExpr(),
+                                        Satisfied))
       return ExprError();
-
+    IsSatisfied = Satisfied;
+  }
   return ConceptSpecializationExpr::Create(Context,
       SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
       TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept,
       ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), Converted,
-      AreArgsDependent ? nullptr : &Satisfaction);
+      IsSatisfied);
 }
 
 ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -5204,11 +5206,7 @@
     TemplateDecl *Template, SourceLocation TemplateLoc,
     TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
     SmallVectorImpl<TemplateArgument> &Converted,
-    bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {
-
-  if (ConstraintsNotSatisfied)
-    *ConstraintsNotSatisfied = false;
-
+    bool UpdateArgsWithConversions) {
   // Make a copy of the template arguments for processing.  Only make the
   // changes at the end when successful in matching the arguments to the
   // template.
@@ -5323,6 +5321,7 @@
       if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
         Converted.push_back(
             TemplateArgument::CreatePackCopy(Context, ArgumentPack));
+
       return false;
     }
 
@@ -5461,15 +5460,6 @@
   if (UpdateArgsWithConversions)
     TemplateArgs = std::move(NewArgs);
 
-  if (!PartialTemplateArgs &&
-      EnsureTemplateArgumentListConstraints(
-        Template, Converted, SourceRange(TemplateLoc,
-                                         TemplateArgs.getRAngleLoc()))) {
-    if (ConstraintsNotSatisfied)
-      *ConstraintsNotSatisfied = true;
-    return true;
-  }
-
   return false;
 }
 
@@ -7804,8 +7794,7 @@
   // template.
   SmallVector<TemplateArgument, 4> Converted;
   if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
-                                TemplateArgs, false, Converted,
-                                /*UpdateArgsWithConversion=*/true))
+                                TemplateArgs, false, Converted))
     return true;
 
   // Find the class template (partial) specialization declaration that
@@ -9051,8 +9040,7 @@
   // template.
   SmallVector<TemplateArgument, 4> Converted;
   if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
-                                TemplateArgs, false, Converted,
-                                /*UpdateArgsWithConversion=*/true))
+                                TemplateArgs, false, Converted))
     return true;
 
   // Find the class template specialization declaration that
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 3274477..64ef819 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2591,23 +2591,6 @@
   return ConvertArg(Arg, 0);
 }
 
-template<typename TemplateDeclT>
-static Sema::TemplateDeductionResult
-CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
-                                ArrayRef<TemplateArgument> DeducedArgs,
-                                TemplateDeductionInfo &Info) {
-  llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
-  Template->getAssociatedConstraints(AssociatedConstraints);
-  if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints,
-                                    DeducedArgs, Info.getLocation(),
-                                    Info.AssociatedConstraintsSatisfaction) ||
-      !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
-    Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs));
-    return Sema::TDK_ConstraintsNotSatisfied;
-  }
-  return Sema::TDK_Success;
-}
-
 // FIXME: This should not be a template, but
 // ClassTemplatePartialSpecializationDecl sadly does not derive from
 // TemplateDecl.
@@ -2705,10 +2688,6 @@
     // If we get here, we successfully used the default template argument.
   }
 
-  if (Sema::TemplateDeductionResult Result
-        = CheckDeducedArgumentConstraints(S, Template, Builder, Info))
-    return Result;
-
   return Sema::TDK_Success;
 }
 
@@ -2788,14 +2767,10 @@
     return Sema::TDK_SubstitutionFailure;
   }
 
-  bool ConstraintsNotSatisfied;
   SmallVector<TemplateArgument, 4> ConvertedInstArgs;
   if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs,
-                                  false, ConvertedInstArgs,
-                                  /*UpdateArgsWithConversions=*/true,
-                                  &ConstraintsNotSatisfied))
-    return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied :
-                                     Sema::TDK_SubstitutionFailure;
+                                  false, ConvertedInstArgs))
+    return Sema::TDK_SubstitutionFailure;
 
   TemplateParameterList *TemplateParams = Template->getTemplateParameters();
   for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
@@ -2856,6 +2831,7 @@
   return Sema::TDK_Success;
 }
 
+
 /// Perform template argument deduction to determine whether
 /// the given template arguments match the given class template
 /// partial specialization per C++ [temp.class.spec.match].
@@ -5073,7 +5049,6 @@
 static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
                                      TemplateLikeDecl *P2,
                                      TemplateDeductionInfo &Info) {
-  // TODO: Concepts: Regard constraints
   // C++ [temp.class.order]p1:
   //   For two class template partial specializations, the first is at least as
   //   specialized as the second if, given the following rewrite to two
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e6c3ab4..0daa33c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -363,7 +363,7 @@
 
 Sema::InstantiatingTemplate::InstantiatingTemplate(
     Sema &SemaRef, SourceLocation PointOfInstantiation,
-    ConstraintsCheck, NamedDecl *Template,
+    ConstraintsCheck, TemplateDecl *Template,
     ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
     : InstantiatingTemplate(
           SemaRef, CodeSynthesisContext::ConstraintsCheck,
@@ -372,7 +372,7 @@
 
 Sema::InstantiatingTemplate::InstantiatingTemplate(
     Sema &SemaRef, SourceLocation PointOfInstantiation,
-    ConstraintSubstitution, NamedDecl *Template,
+    ConstraintSubstitution, TemplateDecl *Template,
     sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
     : InstantiatingTemplate(
           SemaRef, CodeSynthesisContext::ConstraintSubstitution,
@@ -691,27 +691,24 @@
     case CodeSynthesisContext::Memoization:
       break;
     
-    case CodeSynthesisContext::ConstraintsCheck: {
-      unsigned DiagID = 0;
-      if (isa<ConceptDecl>(Active->Entity))
-        DiagID = diag::note_concept_specialization_here;
-      else if (isa<TemplateDecl>(Active->Entity))
-        DiagID = diag::note_checking_constraints_for_template_id_here;
-      else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
-        DiagID = diag::note_checking_constraints_for_var_spec_id_here;
-      else {
-        assert(isa<ClassTemplatePartialSpecializationDecl>(Active->Entity));
-        DiagID = diag::note_checking_constraints_for_class_spec_id_here;
+    case CodeSynthesisContext::ConstraintsCheck:
+      if (auto *CD = dyn_cast<ConceptDecl>(Active->Entity)) {
+        SmallVector<char, 128> TemplateArgsStr;
+        llvm::raw_svector_ostream OS(TemplateArgsStr);
+        CD->printName(OS);
+        printTemplateArgumentList(OS, Active->template_arguments(),
+                                  getPrintingPolicy());
+        Diags.Report(Active->PointOfInstantiation,
+                     diag::note_concept_specialization_here)
+          << OS.str()
+          << Active->InstantiationRange;
+        break;
       }
-      SmallVector<char, 128> TemplateArgsStr;
-      llvm::raw_svector_ostream OS(TemplateArgsStr);
-      cast<NamedDecl>(Active->Entity)->printName(OS);
-      printTemplateArgumentList(OS, Active->template_arguments(),
-                                getPrintingPolicy());
-      Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
-        << Active->InstantiationRange;
+      // TODO: Concepts - implement this for constrained templates and partial
+      // specializations.
+      llvm_unreachable("only concept constraints are supported right now");
       break;
-    }
+      
     case CodeSynthesisContext::ConstraintSubstitution:
       Diags.Report(Active->PointOfInstantiation,
                    diag::note_constraint_substitution_here)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c1d7b7f..31a4302 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3279,8 +3279,7 @@
                                         D->getLocation(),
                                         InstTemplateArgs,
                                         false,
-                                        Converted,
-                                        /*UpdateArgsWithConversion=*/true))
+                                        Converted))
     return nullptr;
 
   // Figure out where to insert this class template explicit specialization
@@ -3401,8 +3400,7 @@
   // Check that the template argument list is well-formed for this template.
   SmallVector<TemplateArgument, 4> Converted;
   if (SemaRef.CheckTemplateArgumentList(InstVarTemplate, D->getLocation(),
-                                        VarTemplateArgsInfo, false, Converted,
-                                        /*UpdateArgsWithConversion=*/true))
+                                        VarTemplateArgsInfo, false, Converted))
     return nullptr;
 
   // Check whether we've already seen a declaration of this specialization.