[clang] [clang] Introduce `SemaConcept` (PR #92672)

Vlad Serebrennikov via cfe-commits cfe-commits at lists.llvm.org
Sun May 19 03:14:51 PDT 2024


https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/92672

>From 716135aa2b0e87172890b545ee20107ceba624e0 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 21:41:19 +0300
Subject: [PATCH 1/4] [clang] Introduce `SemaConcept`

---
 clang/include/clang/Sema/Sema.h            | 319 ++-------------------
 clang/include/clang/Sema/SemaConcept.h     | 271 ++++++++++++++++-
 clang/lib/Parse/ParseExpr.cpp              |   5 +-
 clang/lib/Sema/Sema.cpp                    |  12 +-
 clang/lib/Sema/SemaConcept.cpp             | 219 +++++++-------
 clang/lib/Sema/SemaDecl.cpp                |   7 +-
 clang/lib/Sema/SemaDeclCXX.cpp             |   7 +-
 clang/lib/Sema/SemaExpr.cpp                |   5 +-
 clang/lib/Sema/SemaExprCXX.cpp             |   3 +-
 clang/lib/Sema/SemaOverload.cpp            |  29 +-
 clang/lib/Sema/SemaTemplate.cpp            |  19 +-
 clang/lib/Sema/SemaTemplateDeduction.cpp   |  21 +-
 clang/lib/Sema/SemaTemplateInstantiate.cpp |  41 ++-
 13 files changed, 490 insertions(+), 468 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d4d4a82525a02..1e92eb929e62e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -168,6 +168,7 @@ class PseudoDestructorTypeStorage;
 class PseudoObjectExpr;
 class QualType;
 class SemaCodeCompletion;
+class SemaConcept;
 class SemaCUDA;
 class SemaHLSL;
 class SemaObjC;
@@ -181,6 +182,7 @@ class SwitchStmt;
 class TemplateArgument;
 class TemplateArgumentList;
 class TemplateArgumentLoc;
+class TemplateCompareNewDeclInfo;
 class TemplateDecl;
 class TemplateInstantiationCallback;
 class TemplateParameterList;
@@ -989,6 +991,11 @@ class Sema final : public SemaBase {
     return *CodeCompletionPtr;
   }
 
+  SemaConcept &Concept() {
+    assert(ConceptPtr);
+    return *ConceptPtr;
+  }
+
   SemaCUDA &CUDA() {
     assert(CUDAPtr);
     return *CUDAPtr;
@@ -1050,6 +1057,7 @@ class Sema final : public SemaBase {
   mutable IdentifierInfo *Ident_super;
 
   std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
+  std::unique_ptr<SemaConcept> ConceptPtr;
   std::unique_ptr<SemaCUDA> CUDAPtr;
   std::unique_ptr<SemaHLSL> HLSLPtr;
   std::unique_ptr<SemaObjC> ObjCPtr;
@@ -9198,46 +9206,6 @@ class Sema final : public SemaBase {
     TPL_TemplateParamsEquivalent,
   };
 
-  // A struct to represent the 'new' declaration, which is either itself just
-  // the named decl, or the important information we need about it in order to
-  // do constraint comparisons.
-  class TemplateCompareNewDeclInfo {
-    const NamedDecl *ND = nullptr;
-    const DeclContext *DC = nullptr;
-    const DeclContext *LexicalDC = nullptr;
-    SourceLocation Loc;
-
-  public:
-    TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
-    TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
-                               const DeclContext *LexicalDeclCtx,
-                               SourceLocation Loc)
-
-        : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
-      assert(DC && LexicalDC &&
-             "Constructor only for cases where we have the information to put "
-             "in here");
-    }
-
-    // If this was constructed with no information, we cannot do substitution
-    // for constraint comparison, so make sure we can check that.
-    bool isInvalid() const { return !ND && !DC; }
-
-    const NamedDecl *getDecl() const { return ND; }
-
-    bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
-
-    const DeclContext *getLexicalDeclContext() const {
-      return ND ? ND->getLexicalDeclContext() : LexicalDC;
-    }
-
-    const DeclContext *getDeclContext() const {
-      return ND ? ND->getDeclContext() : DC;
-    }
-
-    SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
-  };
-
   bool TemplateParameterListsAreEqual(
       const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
       const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
@@ -10402,6 +10370,15 @@ class Sema final : public SemaBase {
     return CodeSynthesisContexts.size() > NonInstantiationEntries;
   }
 
+  private:
+
+  /// Introduce the instantiated captures of the lambda into the local
+  /// instantiation scope.
+  bool addInstantiatedCapturesToScope(
+      FunctionDecl *Function, const FunctionDecl *PatternDecl,
+      LocalInstantiationScope &Scope,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+
   ///@}
 
   //
@@ -10638,12 +10615,6 @@ class Sema final : public SemaBase {
       const DeclContext *Pattern,
       const MultiLevelTemplateArgumentList &TemplateArgs);
 
-private:
-  /// Introduce the instantiated local variables into the local
-  /// instantiation scope.
-  void addInstantiatedLocalVarsToScope(FunctionDecl *Function,
-                                       const FunctionDecl *PatternDecl,
-                                       LocalInstantiationScope &Scope);
   /// Introduce the instantiated function parameters into the local
   /// instantiation scope, and set the parameter names to those used
   /// in the template.
@@ -10652,6 +10623,13 @@ class Sema final : public SemaBase {
       LocalInstantiationScope &Scope,
       const MultiLevelTemplateArgumentList &TemplateArgs);
 
+private:
+  /// Introduce the instantiated local variables into the local
+  /// instantiation scope.
+  void addInstantiatedLocalVarsToScope(FunctionDecl *Function,
+                                       const FunctionDecl *PatternDecl,
+                                       LocalInstantiationScope &Scope);
+
   int ParsingClassDepth = 0;
 
   class SavePendingParsedClassStateRAII {
@@ -11092,255 +11070,6 @@ class Sema final : public SemaBase {
   //
   //
 
-  /// \name Constraints and Concepts
-  /// Implementations are in SemaConcept.cpp
-  ///@{
-
-public:
-  void PushSatisfactionStackEntry(const NamedDecl *D,
-                                  const llvm::FoldingSetNodeID &ID) {
-    const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
-    SatisfactionStack.emplace_back(Can, ID);
-  }
-
-  void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
-
-  bool SatisfactionStackContains(const NamedDecl *D,
-                                 const llvm::FoldingSetNodeID &ID) const {
-    const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
-    return llvm::find(SatisfactionStack, SatisfactionStackEntryTy{Can, ID}) !=
-           SatisfactionStack.end();
-  }
-
-  using SatisfactionStackEntryTy =
-      std::pair<const NamedDecl *, llvm::FoldingSetNodeID>;
-
-  // Resets the current SatisfactionStack for cases where we are instantiating
-  // constraints as a 'side effect' of normal instantiation in a way that is not
-  // indicative of recursive definition.
-  class SatisfactionStackResetRAII {
-    llvm::SmallVector<SatisfactionStackEntryTy, 10> BackupSatisfactionStack;
-    Sema &SemaRef;
-
-  public:
-    SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
-      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
-    }
-
-    ~SatisfactionStackResetRAII() {
-      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
-    }
-  };
-
-  void SwapSatisfactionStack(
-      llvm::SmallVectorImpl<SatisfactionStackEntryTy> &NewSS) {
-    SatisfactionStack.swap(NewSS);
-  }
-
-  /// Check whether the given expression is a valid constraint expression.
-  /// A diagnostic is emitted if it is not, false is returned, and
-  /// PossibleNonPrimary will be set to true if the failure might be due to a
-  /// non-primary expression being used as an atomic constraint.
-  bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(),
-                                 bool *PossibleNonPrimary = nullptr,
-                                 bool IsTrailingRequiresClause = false);
-
-  /// \brief Check whether the given list of constraint expressions are
-  /// satisfied (as if in a 'conjunction') given template arguments.
-  /// \param Template the template-like entity that triggered the constraints
-  /// check (either a concept or a constrained entity).
-  /// \param ConstraintExprs a list of constraint expressions, treated as if
-  /// they were 'AND'ed together.
-  /// \param TemplateArgLists the list of template arguments to substitute into
-  /// the constraint expression.
-  /// \param TemplateIDRange The source range of the template id that
-  /// caused the constraints check.
-  /// \param Satisfaction if true is returned, will contain details of the
-  /// satisfaction, with enough information to diagnose an unsatisfied
-  /// expression.
-  /// \returns true if an error occurred and satisfaction could not be checked,
-  /// false otherwise.
-  bool CheckConstraintSatisfaction(
-      const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
-      const MultiLevelTemplateArgumentList &TemplateArgLists,
-      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
-    llvm::SmallVector<Expr *, 4> Converted;
-    return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
-                                       TemplateArgLists, TemplateIDRange,
-                                       Satisfaction);
-  }
-
-  /// \brief Check whether the given list of constraint expressions are
-  /// satisfied (as if in a 'conjunction') given template arguments.
-  /// Additionally, takes an empty list of Expressions which is populated with
-  /// the instantiated versions of the ConstraintExprs.
-  /// \param Template the template-like entity that triggered the constraints
-  /// check (either a concept or a constrained entity).
-  /// \param ConstraintExprs a list of constraint expressions, treated as if
-  /// they were 'AND'ed together.
-  /// \param ConvertedConstraints a out parameter that will get populated with
-  /// the instantiated version of the ConstraintExprs if we successfully checked
-  /// satisfaction.
-  /// \param TemplateArgList the multi-level list of template arguments to
-  /// substitute into the constraint expression. This should be relative to the
-  /// top-level (hence multi-level), since we need to instantiate fully at the
-  /// time of checking.
-  /// \param TemplateIDRange The source range of the template id that
-  /// caused the constraints check.
-  /// \param Satisfaction if true is returned, will contain details of the
-  /// satisfaction, with enough information to diagnose an unsatisfied
-  /// expression.
-  /// \returns true if an error occurred and satisfaction could not be checked,
-  /// false otherwise.
-  bool CheckConstraintSatisfaction(
-      const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
-      llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
-      const MultiLevelTemplateArgumentList &TemplateArgList,
-      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
-
-  /// \brief Check whether the given non-dependent constraint expression is
-  /// satisfied. Returns false and updates Satisfaction with the satisfaction
-  /// verdict if successful, emits a diagnostic and returns true if an error
-  /// occurred and satisfaction could not be determined.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
-                                   ConstraintSatisfaction &Satisfaction);
-
-  /// Check whether the given function decl's trailing requires clause is
-  /// satisfied, if any. Returns false and updates Satisfaction with the
-  /// satisfaction verdict if successful, emits a diagnostic and returns true if
-  /// an error occurred and satisfaction could not be determined.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool CheckFunctionConstraints(const FunctionDecl *FD,
-                                ConstraintSatisfaction &Satisfaction,
-                                SourceLocation UsageLoc = SourceLocation(),
-                                bool ForOverloadResolution = false);
-
-  // Calculates whether two constraint expressions are equal irrespective of a
-  // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and
-  // 'New', which are the "source" of the constraint, since this is necessary
-  // for figuring out the relative 'depth' of the constraint. The depth of the
-  // 'primary template' and the 'instantiated from' templates aren't necessarily
-  // the same, such as a case when one is a 'friend' defined in a class.
-  bool AreConstraintExpressionsEqual(const NamedDecl *Old,
-                                     const Expr *OldConstr,
-                                     const TemplateCompareNewDeclInfo &New,
-                                     const Expr *NewConstr);
-
-  // Calculates whether the friend function depends on an enclosing template for
-  // the purposes of [temp.friend] p9.
-  bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
-
-  /// \brief Ensure that the given template arguments satisfy the constraints
-  /// associated with the given template, emitting a diagnostic if they do not.
-  ///
-  /// \param Template The template to which the template arguments are being
-  /// provided.
-  ///
-  /// \param TemplateArgs The converted, canonicalized template arguments.
-  ///
-  /// \param TemplateIDRange The source range of the template id that
-  /// caused the constraints check.
-  ///
-  /// \returns true if the constrains are not satisfied or could not be checked
-  /// for satisfaction, false if the constraints are satisfied.
-  bool EnsureTemplateArgumentListConstraints(
-      TemplateDecl *Template,
-      const MultiLevelTemplateArgumentList &TemplateArgs,
-      SourceRange TemplateIDRange);
-
-  bool CheckInstantiatedFunctionTemplateConstraints(
-      SourceLocation PointOfInstantiation, FunctionDecl *Decl,
-      ArrayRef<TemplateArgument> TemplateArgs,
-      ConstraintSatisfaction &Satisfaction);
-
-  /// \brief Emit diagnostics explaining why a constraint expression was deemed
-  /// unsatisfied.
-  /// \param First whether this is the first time an unsatisfied constraint is
-  /// diagnosed for this error.
-  void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
-                                     bool First = true);
-
-  /// \brief Emit diagnostics explaining why a constraint expression was deemed
-  /// unsatisfied.
-  void
-  DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
-                                bool First = true);
-
-  const NormalizedConstraint *getNormalizedAssociatedConstraints(
-      NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints);
-
-  /// \brief Check whether the given declaration's associated constraints are
-  /// at least as constrained than another declaration's according to the
-  /// partial ordering of constraints.
-  ///
-  /// \param Result If no error occurred, receives the result of true if D1 is
-  /// at least constrained than D2, and false otherwise.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef<const Expr *> AC1,
-                              NamedDecl *D2, MutableArrayRef<const Expr *> AC2,
-                              bool &Result);
-
-  /// If D1 was not at least as constrained as D2, but would've been if a pair
-  /// of atomic constraints involved had been declared in a concept and not
-  /// repeated in two separate places in code.
-  /// \returns true if such a diagnostic was emitted, false otherwise.
-  bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
-      NamedDecl *D1, ArrayRef<const Expr *> AC1, NamedDecl *D2,
-      ArrayRef<const Expr *> AC2);
-
-private:
-  /// Caches pairs of template-like decls whose associated constraints were
-  /// checked for subsumption and whether or not the first's constraints did in
-  /// fact subsume the second's.
-  llvm::DenseMap<std::pair<NamedDecl *, NamedDecl *>, bool> SubsumptionCache;
-  /// Caches the normalized associated constraints of declarations (concepts or
-  /// constrained declarations). If an error occurred while normalizing the
-  /// associated constraints of the template or concept, nullptr will be cached
-  /// here.
-  llvm::DenseMap<NamedDecl *, NormalizedConstraint *> NormalizationCache;
-
-  llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
-      SatisfactionCache;
-
-  // The current stack of constraint satisfactions, so we can exit-early.
-  llvm::SmallVector<SatisfactionStackEntryTy, 10> SatisfactionStack;
-
-  /// Introduce the instantiated captures of the lambda into the local
-  /// instantiation scope.
-  bool addInstantiatedCapturesToScope(
-      FunctionDecl *Function, const FunctionDecl *PatternDecl,
-      LocalInstantiationScope &Scope,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
-
-  /// Used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
-  /// the case of lambdas) set up the LocalInstantiationScope of the current
-  /// function.
-  bool
-  SetupConstraintScope(FunctionDecl *FD,
-                       std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
-                       const MultiLevelTemplateArgumentList &MLTAL,
-                       LocalInstantiationScope &Scope);
-
-  /// Used during constraint checking, sets up the constraint template argument
-  /// lists, and calls SetupConstraintScope to set up the
-  /// LocalInstantiationScope to have the proper set of ParVarDecls configured.
-  std::optional<MultiLevelTemplateArgumentList>
-  SetupConstraintCheckingTemplateArgumentsAndScope(
-      FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
-      LocalInstantiationScope &Scope);
-
-  ///@}
-
-  //
-  //
-  // -------------------------------------------------------------------------
-  //
-  //
-
   /// \name Types
   /// Implementations are in SemaType.cpp
   ///@{
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 711443505174f..7104e91f24b61 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -17,6 +17,8 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Token.h"
+#include "clang/Sema/SemaBase.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
 #include <optional>
@@ -24,7 +26,6 @@
 #include <utility>
 
 namespace clang {
-class Sema;
 
 struct AtomicConstraint {
   const Expr *ConstraintExpr;
@@ -80,6 +81,7 @@ struct AtomicConstraint {
 /// disjunction of normalized constraints.
 struct NormalizedConstraint {
   friend class Sema;
+  friend class SemaConcept;
 
   enum CompoundConstraintKind { CCK_Conjunction, CCK_Disjunction };
 
@@ -150,6 +152,271 @@ struct NormalizedConstraint {
   fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E);
 };
 
-} // clang
+class LocalInstantiationScope;
+class MultiLevelTemplateArgumentList;
+
+// A struct to represent the 'new' declaration, which is either itself just
+// the named decl, or the important information we need about it in order to
+// do constraint comparisons.
+class TemplateCompareNewDeclInfo {
+  const NamedDecl *ND = nullptr;
+  const DeclContext *DC = nullptr;
+  const DeclContext *LexicalDC = nullptr;
+  SourceLocation Loc;
+
+public:
+  TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
+  TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
+                              const DeclContext *LexicalDeclCtx,
+                              SourceLocation Loc)
+
+      : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
+    assert(DC && LexicalDC &&
+            "Constructor only for cases where we have the information to put "
+            "in here");
+  }
+
+  // If this was constructed with no information, we cannot do substitution
+  // for constraint comparison, so make sure we can check that.
+  bool isInvalid() const { return !ND && !DC; }
+
+  const NamedDecl *getDecl() const { return ND; }
+
+  bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
+
+  const DeclContext *getLexicalDeclContext() const {
+    return ND ? ND->getLexicalDeclContext() : LexicalDC;
+  }
+
+  const DeclContext *getDeclContext() const {
+    return ND ? ND->getDeclContext() : DC;
+  }
+
+  SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
+};
+
+class SemaConcept : public SemaBase {
+public:
+  SemaConcept(Sema &S);
+  ~SemaConcept();
+
+  void PushSatisfactionStackEntry(const NamedDecl *D,
+                                  const llvm::FoldingSetNodeID &ID) {
+    const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
+    SatisfactionStack.emplace_back(Can, ID);
+  }
+
+  void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
+
+  bool SatisfactionStackContains(const NamedDecl *D,
+                                 const llvm::FoldingSetNodeID &ID) const {
+    const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
+    return llvm::find(SatisfactionStack, SatisfactionStackEntryTy{Can, ID}) !=
+           SatisfactionStack.end();
+  }
+
+  using SatisfactionStackEntryTy =
+      std::pair<const NamedDecl *, llvm::FoldingSetNodeID>;
+
+  // Resets the current SatisfactionStack for cases where we are instantiating
+  // constraints as a 'side effect' of normal instantiation in a way that is not
+  // indicative of recursive definition.
+  class SatisfactionStackResetRAII {
+    llvm::SmallVector<SatisfactionStackEntryTy, 10> BackupSatisfactionStack;
+    Sema &SemaRef;
+
+  public:
+    SatisfactionStackResetRAII(Sema &S);
+    ~SatisfactionStackResetRAII();
+  };
+
+  void SwapSatisfactionStack(
+      llvm::SmallVectorImpl<SatisfactionStackEntryTy> &NewSS) {
+    SatisfactionStack.swap(NewSS);
+  }
+
+  /// Check whether the given expression is a valid constraint expression.
+  /// A diagnostic is emitted if it is not, false is returned, and
+  /// PossibleNonPrimary will be set to true if the failure might be due to a
+  /// non-primary expression being used as an atomic constraint.
+  bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(),
+                                 bool *PossibleNonPrimary = nullptr,
+                                 bool IsTrailingRequiresClause = false);
+
+  /// \brief Check whether the given list of constraint expressions are
+  /// satisfied (as if in a 'conjunction') given template arguments.
+  /// \param Template the template-like entity that triggered the constraints
+  /// check (either a concept or a constrained entity).
+  /// \param ConstraintExprs a list of constraint expressions, treated as if
+  /// they were 'AND'ed together.
+  /// \param TemplateArgLists the list of template arguments to substitute into
+  /// the constraint expression.
+  /// \param TemplateIDRange The source range of the template id that
+  /// caused the constraints check.
+  /// \param Satisfaction if true is returned, will contain details of the
+  /// satisfaction, with enough information to diagnose an unsatisfied
+  /// expression.
+  /// \returns true if an error occurred and satisfaction could not be checked,
+  /// false otherwise.
+  bool CheckConstraintSatisfaction(
+      const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
+      const MultiLevelTemplateArgumentList &TemplateArgLists,
+      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
+    llvm::SmallVector<Expr *, 4> Converted;
+    return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
+                                       TemplateArgLists, TemplateIDRange,
+                                       Satisfaction);
+  }
+
+  /// \brief Check whether the given list of constraint expressions are
+  /// satisfied (as if in a 'conjunction') given template arguments.
+  /// Additionally, takes an empty list of Expressions which is populated with
+  /// the instantiated versions of the ConstraintExprs.
+  /// \param Template the template-like entity that triggered the constraints
+  /// check (either a concept or a constrained entity).
+  /// \param ConstraintExprs a list of constraint expressions, treated as if
+  /// they were 'AND'ed together.
+  /// \param ConvertedConstraints a out parameter that will get populated with
+  /// the instantiated version of the ConstraintExprs if we successfully checked
+  /// satisfaction.
+  /// \param TemplateArgList the multi-level list of template arguments to
+  /// substitute into the constraint expression. This should be relative to the
+  /// top-level (hence multi-level), since we need to instantiate fully at the
+  /// time of checking.
+  /// \param TemplateIDRange The source range of the template id that
+  /// caused the constraints check.
+  /// \param Satisfaction if true is returned, will contain details of the
+  /// satisfaction, with enough information to diagnose an unsatisfied
+  /// expression.
+  /// \returns true if an error occurred and satisfaction could not be checked,
+  /// false otherwise.
+  bool CheckConstraintSatisfaction(
+      const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
+      llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
+      const MultiLevelTemplateArgumentList &TemplateArgList,
+      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
+
+  /// \brief Check whether the given non-dependent constraint expression is
+  /// satisfied. Returns false and updates Satisfaction with the satisfaction
+  /// verdict if successful, emits a diagnostic and returns true if an error
+  /// occurred and satisfaction could not be determined.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
+                                   ConstraintSatisfaction &Satisfaction);
+
+  /// Check whether the given function decl's trailing requires clause is
+  /// satisfied, if any. Returns false and updates Satisfaction with the
+  /// satisfaction verdict if successful, emits a diagnostic and returns true if
+  /// an error occurred and satisfaction could not be determined.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool CheckFunctionConstraints(const FunctionDecl *FD,
+                                ConstraintSatisfaction &Satisfaction,
+                                SourceLocation UsageLoc = SourceLocation(),
+                                bool ForOverloadResolution = false);
+
+  // Calculates whether two constraint expressions are equal irrespective of a
+  // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and
+  // 'New', which are the "source" of the constraint, since this is necessary
+  // for figuring out the relative 'depth' of the constraint. The depth of the
+  // 'primary template' and the 'instantiated from' templates aren't necessarily
+  // the same, such as a case when one is a 'friend' defined in a class.
+  bool AreConstraintExpressionsEqual(const NamedDecl *Old,
+                                     const Expr *OldConstr,
+                                     const TemplateCompareNewDeclInfo &New,
+                                     const Expr *NewConstr);
+
+  // Calculates whether the friend function depends on an enclosing template for
+  // the purposes of [temp.friend] p9.
+  bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
+
+  /// \brief Ensure that the given template arguments satisfy the constraints
+  /// associated with the given template, emitting a diagnostic if they do not.
+  ///
+  /// \param Template The template to which the template arguments are being
+  /// provided.
+  ///
+  /// \param TemplateArgs The converted, canonicalized template arguments.
+  ///
+  /// \param TemplateIDRange The source range of the template id that
+  /// caused the constraints check.
+  ///
+  /// \returns true if the constrains are not satisfied or could not be checked
+  /// for satisfaction, false if the constraints are satisfied.
+  bool EnsureTemplateArgumentListConstraints(
+      TemplateDecl *Template,
+      const MultiLevelTemplateArgumentList &TemplateArgs,
+      SourceRange TemplateIDRange);
+
+  bool CheckInstantiatedFunctionTemplateConstraints(
+      SourceLocation PointOfInstantiation, FunctionDecl *Decl,
+      ArrayRef<TemplateArgument> TemplateArgs,
+      ConstraintSatisfaction &Satisfaction);
+
+  /// \brief Emit diagnostics explaining why a constraint expression was deemed
+  /// unsatisfied.
+  /// \param First whether this is the first time an unsatisfied constraint is
+  /// diagnosed for this error.
+  void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
+                                     bool First = true);
+
+  /// \brief Emit diagnostics explaining why a constraint expression was deemed
+  /// unsatisfied.
+  void
+  DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
+                                bool First = true);
+
+  const NormalizedConstraint *getNormalizedAssociatedConstraints(
+      NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints);
+
+  /// \brief Check whether the given declaration's associated constraints are
+  /// at least as constrained than another declaration's according to the
+  /// partial ordering of constraints.
+  ///
+  /// \param Result If no error occurred, receives the result of true if D1 is
+  /// at least constrained than D2, and false otherwise.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef<const Expr *> AC1,
+                              NamedDecl *D2, MutableArrayRef<const Expr *> AC2,
+                              bool &Result);
+
+  /// If D1 was not at least as constrained as D2, but would've been if a pair
+  /// of atomic constraints involved had been declared in a concept and not
+  /// repeated in two separate places in code.
+  /// \returns true if such a diagnostic was emitted, false otherwise.
+  bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+      NamedDecl *D1, ArrayRef<const Expr *> AC1, NamedDecl *D2,
+      ArrayRef<const Expr *> AC2);
+
+  /// Used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
+  /// the case of lambdas) set up the LocalInstantiationScope of the current
+  /// function.
+  bool
+  SetupConstraintScope(FunctionDecl *FD,
+                       std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
+                       const MultiLevelTemplateArgumentList &MLTAL,
+                       LocalInstantiationScope &Scope);
+
+private:
+  /// Caches pairs of template-like decls whose associated constraints were
+  /// checked for subsumption and whether or not the first's constraints did in
+  /// fact subsume the second's.
+  llvm::DenseMap<std::pair<NamedDecl *, NamedDecl *>, bool> SubsumptionCache;
+  /// Caches the normalized associated constraints of declarations (concepts or
+  /// constrained declarations). If an error occurred while normalizing the
+  /// associated constraints of the template or concept, nullptr will be cached
+  /// here.
+  llvm::DenseMap<NamedDecl *, NormalizedConstraint *> NormalizationCache;
+
+  llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
+      SatisfactionCache;
+
+  // The current stack of constraint satisfactions, so we can exit-early.
+  llvm::SmallVector<SatisfactionStackEntryTy, 10> SatisfactionStack;
+};
+
+} // namespace clang
 
 #endif // LLVM_CLANG_SEMA_SEMACONCEPT_H
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index eb7447fa038e4..175e0bce683f7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -31,6 +31,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaCodeCompletion.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenACC.h"
@@ -268,7 +269,7 @@ ExprResult Parser::ParseConstraintExpression() {
       Actions, Sema::ExpressionEvaluationContext::Unevaluated);
   ExprResult LHS(ParseCastExpression(AnyCastExpr));
   ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
-  if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {
+  if (Res.isUsable() && !Actions.Concept().CheckConstraintExpression(Res.get())) {
     Actions.CorrectDelayedTyposInExpr(Res);
     return ExprError();
   }
@@ -330,7 +331,7 @@ Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
     }
     bool PossibleNonPrimary;
     bool IsConstraintExpr =
-        Actions.CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,
+        Actions.Concept().CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,
                                           IsTrailingRequiresClause);
     if (!IsConstraintExpr || PossibleNonPrimary) {
       // Atomic constraint might be an unparenthesized non-primary expression
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index f847c49920cf3..e3f9648db1793 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -43,6 +43,7 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaConsumer.h"
 #include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaInternal.h"
@@ -205,6 +206,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
       CurScope(nullptr), Ident_super(nullptr),
       CodeCompletionPtr(
           std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
+      ConceptPtr(std::make_unique<SemaConcept>(*this)),
       CUDAPtr(std::make_unique<SemaCUDA>(*this)),
       HLSLPtr(std::make_unique<SemaHLSL>(*this)),
       ObjCPtr(std::make_unique<SemaObjC>(*this)),
@@ -228,7 +230,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
       TyposCorrected(0), IsBuildingRecoveryCallExpr(false), NumSFINAEErrors(0),
       AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr),
       InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
-      ArgumentPackSubstitutionIndex(-1), SatisfactionCache(Context) {
+      ArgumentPackSubstitutionIndex(-1) {
   assert(pp.TUKind == TUKind);
   TUScope = nullptr;
 
@@ -491,14 +493,6 @@ Sema::~Sema() {
         = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
     ExternalSema->ForgetSema();
 
-  // Delete cached satisfactions.
-  std::vector<ConstraintSatisfaction *> Satisfactions;
-  Satisfactions.reserve(SatisfactionCache.size());
-  for (auto &Node : SatisfactionCache)
-    Satisfactions.push_back(&Node);
-  for (auto *Node : Satisfactions)
-    delete Node;
-
   threadSafety::threadSafetyCleanup(ThreadSafetyDeclCache);
 
   // Destroys data sharing attributes stack for OpenMP
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 202dd86c67f62..3f92eac2e5769 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -88,9 +88,10 @@ class LogicalBinOp {
 };
 }
 
-bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
+bool SemaConcept::CheckConstraintExpression(const Expr *ConstraintExpression,
                                      Token NextToken, bool *PossibleNonPrimary,
                                      bool IsTrailingRequiresClause) {
+  ASTContext &Context = getASTContext();
   // C++2a [temp.constr.atomic]p1
   // ..E shall be a constant expression of type bool.
 
@@ -126,7 +127,7 @@ bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
          (IsTrailingRequiresClause ||
           (Type->isDependentType() &&
            isa<UnresolvedLookupExpr>(ConstraintExpression) &&
-           !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
+           !dyn_cast_if_present<LambdaScopeInfo>(SemaRef.getCurFunction())) ||
           Type->isFunctionType() ||
           Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
         // We have the following case:
@@ -166,13 +167,13 @@ struct SatisfactionStackRAII {
                         const llvm::FoldingSetNodeID &FSNID)
       : SemaRef(SemaRef) {
       if (ND) {
-      SemaRef.PushSatisfactionStackEntry(ND, FSNID);
+      SemaRef.Concept().PushSatisfactionStackEntry(ND, FSNID);
       Inserted = true;
       }
   }
   ~SatisfactionStackRAII() {
         if (Inserted)
-          SemaRef.PopSatisfactionStackEntry();
+          SemaRef.Concept().PopSatisfactionStackEntry();
   }
 };
 } // namespace
@@ -323,7 +324,7 @@ DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
   // expression, or when trying to determine the constexpr-ness of special
   // members. Otherwise we could just use the
   // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
-  if (S.SatisfactionStackContains(Templ, ID)) {
+  if (S.Concept().SatisfactionStackContains(Templ, ID)) {
     S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
         << const_cast<Expr *>(E) << E->getSourceRange();
     return true;
@@ -401,7 +402,7 @@ static ExprResult calculateConstraintSatisfaction(
           }
         }
 
-        if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
+        if (!S.Concept().CheckConstraintExpression(SubstitutedExpression.get()))
           return ExprError();
 
         // [temp.constr.atomic]p3: To determine if an atomic constraint is
@@ -472,7 +473,7 @@ static bool CheckConstraintSatisfaction(
   return false;
 }
 
-bool Sema::CheckConstraintSatisfaction(
+bool SemaConcept::CheckConstraintSatisfaction(
     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
     llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
     const MultiLevelTemplateArgumentList &TemplateArgsLists,
@@ -483,7 +484,7 @@ bool Sema::CheckConstraintSatisfaction(
   }
   if (!Template) {
     return ::CheckConstraintSatisfaction(
-        *this, nullptr, ConstraintExprs, ConvertedConstraints,
+        SemaRef, nullptr, ConstraintExprs, ConvertedConstraints,
         TemplateArgsLists, TemplateIDRange, OutSatisfaction);
   }
 
@@ -497,7 +498,7 @@ bool Sema::CheckConstraintSatisfaction(
                          List.Args.end());
 
   llvm::FoldingSetNodeID ID;
-  ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
+  ConstraintSatisfaction::Profile(ID, SemaRef.Context, Template, FlattenedArgs);
   void *InsertPos;
   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
     OutSatisfaction = *Cached;
@@ -506,7 +507,7 @@ bool Sema::CheckConstraintSatisfaction(
 
   auto Satisfaction =
       std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
-  if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
+  if (::CheckConstraintSatisfaction(SemaRef, Template, ConstraintExprs,
                                     ConvertedConstraints, TemplateArgsLists,
                                     TemplateIDRange, *Satisfaction)) {
     OutSatisfaction = *Satisfaction;
@@ -535,63 +536,26 @@ bool Sema::CheckConstraintSatisfaction(
   return false;
 }
 
-bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
+bool SemaConcept::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
                                        ConstraintSatisfaction &Satisfaction) {
   return calculateConstraintSatisfaction(
-             *this, ConstraintExpr, Satisfaction,
+             SemaRef, ConstraintExpr, Satisfaction,
              [this](const Expr *AtomicExpr) -> ExprResult {
                // We only do this to immitate lvalue-to-rvalue conversion.
-               return PerformContextuallyConvertToBool(
+               return SemaRef.PerformContextuallyConvertToBool(
                    const_cast<Expr *>(AtomicExpr));
              })
       .isInvalid();
 }
 
-bool Sema::addInstantiatedCapturesToScope(
-    FunctionDecl *Function, const FunctionDecl *PatternDecl,
-    LocalInstantiationScope &Scope,
-    const MultiLevelTemplateArgumentList &TemplateArgs) {
-  const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
-  const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
-
-  unsigned Instantiated = 0;
-
-  auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
-                              unsigned Index) {
-    ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
-    if (CapturedVar->isInitCapture())
-      Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
-  };
-
-  for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
-    if (!CapturePattern.capturesVariable()) {
-      Instantiated++;
-      continue;
-    }
-    const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
-    if (!CapturedPattern->isParameterPack()) {
-      AddSingleCapture(CapturedPattern, Instantiated++);
-    } else {
-      Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
-      std::optional<unsigned> NumArgumentsInExpansion =
-          getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
-      if (!NumArgumentsInExpansion)
-        continue;
-      for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
-        AddSingleCapture(CapturedPattern, Instantiated++);
-    }
-  }
-  return false;
-}
-
-bool Sema::SetupConstraintScope(
+bool SemaConcept::SetupConstraintScope(
     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
     const MultiLevelTemplateArgumentList &MLTAL,
     LocalInstantiationScope &Scope) {
   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
-    InstantiatingTemplate Inst(
-        *this, FD->getPointOfInstantiation(),
+    Sema::InstantiatingTemplate Inst(
+        SemaRef, FD->getPointOfInstantiation(),
         Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
         SourceRange());
@@ -606,7 +570,7 @@ bool Sema::SetupConstraintScope(
     if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
       MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
                                                    /*Final=*/false);
-      if (addInstantiatedParametersToScope(
+      if (SemaRef.addInstantiatedParametersToScope(
               FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
         return true;
     }
@@ -621,7 +585,7 @@ bool Sema::SetupConstraintScope(
             PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
       while (FromMemTempl->getInstantiatedFromMemberTemplate())
         FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
-      if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
+      if (SemaRef.addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
                                            Scope, MLTAL))
         return true;
     }
@@ -636,8 +600,8 @@ bool Sema::SetupConstraintScope(
             ? FD->getInstantiatedFromMemberFunction()
             : FD->getInstantiatedFromDecl();
 
-    InstantiatingTemplate Inst(
-        *this, FD->getPointOfInstantiation(),
+    Sema::InstantiatingTemplate Inst(
+        SemaRef, FD->getPointOfInstantiation(),
         Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
         SourceRange());
@@ -646,17 +610,20 @@ bool Sema::SetupConstraintScope(
 
     // Case where this was not a template, but instantiated as a
     // child-function.
-    if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
+    if (SemaRef.addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
       return true;
   }
 
   return false;
 }
 
-// This function collects all of the template arguments for the purposes of
-// constraint-instantiation and checking.
-std::optional<MultiLevelTemplateArgumentList>
-Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
+/// This function collects all of the template arguments for the purposes of
+/// constraint-instantiation and checking.
+/// Used during constraint checking, sets up the constraint template argument
+/// lists, and calls SetupConstraintScope to set up the
+/// LocalInstantiationScope to have the proper set of ParVarDecls configured.
+static std::optional<MultiLevelTemplateArgumentList>
+SetupConstraintCheckingTemplateArgumentsAndScope(Sema &SemaRef,
     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
     LocalInstantiationScope &Scope) {
   MultiLevelTemplateArgumentList MLTAL;
@@ -665,18 +632,18 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
   // We need the entire list, since the constraint is completely uninstantiated
   // at this point.
   MLTAL =
-      getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
+      SemaRef.getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
                                    /*Final=*/false, /*Innermost=*/std::nullopt,
                                    /*RelativeToPrimary=*/true,
                                    /*Pattern=*/nullptr,
                                    /*ForConstraintInstantiation=*/true);
-  if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
+  if (SemaRef.Concept().SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
     return std::nullopt;
 
   return MLTAL;
 }
 
-bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
+bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
                                     ConstraintSatisfaction &Satisfaction,
                                     SourceLocation UsageLoc,
                                     bool ForOverloadResolution) {
@@ -713,10 +680,10 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
       CtxToSave = CtxToSave->getNonTransparentContext();
   }
 
-  ContextRAII SavedContext{*this, CtxToSave};
-  LocalInstantiationScope Scope(*this, !ForOverloadResolution);
+  Sema::ContextRAII SavedContext{SemaRef, CtxToSave};
+  LocalInstantiationScope Scope(SemaRef, !ForOverloadResolution);
   std::optional<MultiLevelTemplateArgumentList> MLTAL =
-      SetupConstraintCheckingTemplateArgumentsAndScope(
+      SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef,
           const_cast<FunctionDecl *>(FD), {}, Scope);
 
   if (!MLTAL)
@@ -728,10 +695,10 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
     ThisQuals = Method->getMethodQualifiers();
     Record = const_cast<CXXRecordDecl *>(Method->getParent());
   }
-  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
+  Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
 
-  LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
-      *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
+  Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
+      SemaRef, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
       ForOverloadResolution);
 
   return CheckConstraintSatisfaction(
@@ -785,7 +752,7 @@ namespace {
 } // namespace
 
 static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
-    Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
+    Sema &S, const TemplateCompareNewDeclInfo &DeclInfo,
     const Expr *ConstrExpr) {
   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
       DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
@@ -837,7 +804,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
   return SubstConstr.get();
 }
 
-bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
+bool SemaConcept::AreConstraintExpressionsEqual(const NamedDecl *Old,
                                          const Expr *OldConstr,
                                          const TemplateCompareNewDeclInfo &New,
                                          const Expr *NewConstr) {
@@ -847,13 +814,13 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
   if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
       Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
     if (const Expr *SubstConstr =
-            SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
+            SubstituteConstraintExpressionWithoutSatisfaction(SemaRef, Old,
                                                               OldConstr))
       OldConstr = SubstConstr;
     else
       return false;
     if (const Expr *SubstConstr =
-            SubstituteConstraintExpressionWithoutSatisfaction(*this, New,
+            SubstituteConstraintExpressionWithoutSatisfaction(SemaRef, New,
                                                               NewConstr))
       NewConstr = SubstConstr;
     else
@@ -861,12 +828,12 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
   }
 
   llvm::FoldingSetNodeID ID1, ID2;
-  OldConstr->Profile(ID1, Context, /*Canonical=*/true);
-  NewConstr->Profile(ID2, Context, /*Canonical=*/true);
+  OldConstr->Profile(ID1, SemaRef.Context, /*Canonical=*/true);
+  NewConstr->Profile(ID2, SemaRef.Context, /*Canonical=*/true);
   return ID1 == ID2;
 }
 
-bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
+bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
   assert(FD->getFriendObjectKind() && "Must be a friend!");
 
   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
@@ -878,16 +845,16 @@ bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
   SmallVector<const Expr *, 3> ACs;
   FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
 
-  unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
+  unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(SemaRef, FD);
   for (const Expr *Constraint : ACs)
-    if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
+    if (SemaRef.ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
                                                        Constraint))
       return true;
 
   return false;
 }
 
-bool Sema::EnsureTemplateArgumentListConstraints(
+bool SemaConcept::EnsureTemplateArgumentListConstraints(
     TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
     SourceRange TemplateIDRange) {
   ConstraintSatisfaction Satisfaction;
@@ -900,13 +867,13 @@ bool Sema::EnsureTemplateArgumentListConstraints(
   if (!Satisfaction.IsSatisfied) {
     SmallString<128> TemplateArgString;
     TemplateArgString = " ";
-    TemplateArgString += getTemplateArgumentBindingsText(
+    TemplateArgString += SemaRef.getTemplateArgumentBindingsText(
         TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
         TemplateArgsLists.getInnermost().size());
 
     Diag(TemplateIDRange.getBegin(),
          diag::err_template_arg_list_constraints_not_satisfied)
-        << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
+        << (int)SemaRef.getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
         << TemplateArgString << TemplateIDRange;
     DiagnoseUnsatisfiedConstraint(Satisfaction);
     return true;
@@ -914,7 +881,7 @@ bool Sema::EnsureTemplateArgumentListConstraints(
   return false;
 }
 
-bool Sema::CheckInstantiatedFunctionTemplateConstraints(
+bool SemaConcept::CheckInstantiatedFunctionTemplateConstraints(
     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
     ArrayRef<TemplateArgument> TemplateArgs,
     ConstraintSatisfaction &Satisfaction) {
@@ -931,11 +898,11 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
 
   // Enter the scope of this instantiation. We don't use
   // PushDeclContext because we don't have a scope.
-  Sema::ContextRAII savedContext(*this, Decl);
-  LocalInstantiationScope Scope(*this);
+  Sema::ContextRAII savedContext(SemaRef, Decl);
+  LocalInstantiationScope Scope(SemaRef);
 
   std::optional<MultiLevelTemplateArgumentList> MLTAL =
-      SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
+      SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef, Decl, TemplateArgs,
                                                        Scope);
 
   if (!MLTAL)
@@ -948,9 +915,9 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
     Record = Method->getParent();
   }
 
-  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
-  LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
-      *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
+  Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
+  Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
+      SemaRef, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
 
   llvm::SmallVector<Expr *, 1> Converted;
   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
@@ -1014,7 +981,7 @@ static void diagnoseUnsatisfiedRequirement(Sema &S,
                diag::note_expr_requirement_constraints_not_satisfied)
             << (int)First << ConstraintExpr;
       }
-      S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
+      S.Concept().DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
       break;
     }
     case concepts::ExprRequirement::SS_Satisfied:
@@ -1146,7 +1113,7 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
              diag::note_concept_specialization_constraint_evaluated_to_false)
           << (int)First << CSE;
     }
-    S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
+    S.Concept().DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
     return;
   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
     // FIXME: RequiresExpr should store dependent diagnostics.
@@ -1192,29 +1159,29 @@ static void diagnoseUnsatisfiedConstraintExpr(
 }
 
 void
-Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
+SemaConcept::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
                                     bool First) {
   assert(!Satisfaction.IsSatisfied &&
          "Attempted to diagnose a satisfied constraint");
   for (auto &Pair : Satisfaction.Details) {
-    diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
+    diagnoseUnsatisfiedConstraintExpr(SemaRef, Pair.first, Pair.second, First);
     First = false;
   }
 }
 
-void Sema::DiagnoseUnsatisfiedConstraint(
+void SemaConcept::DiagnoseUnsatisfiedConstraint(
     const ASTConstraintSatisfaction &Satisfaction,
     bool First) {
   assert(!Satisfaction.IsSatisfied &&
          "Attempted to diagnose a satisfied constraint");
   for (auto &Pair : Satisfaction) {
-    diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
+    diagnoseUnsatisfiedConstraintExpr(SemaRef, Pair.first, Pair.second, First);
     First = false;
   }
 }
 
 const NormalizedConstraint *
-Sema::getNormalizedAssociatedConstraints(
+SemaConcept::getNormalizedAssociatedConstraints(
     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
   // In case the ConstrainedDecl comes from modules, it is necessary to use
   // the canonical decl to avoid different atomic constraints with the 'same'
@@ -1224,13 +1191,13 @@ Sema::getNormalizedAssociatedConstraints(
   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
   if (CacheEntry == NormalizationCache.end()) {
     auto Normalized =
-        NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
+        NormalizedConstraint::fromConstraintExprs(SemaRef, ConstrainedDecl,
                                                   AssociatedConstraints);
     CacheEntry =
         NormalizationCache
             .try_emplace(ConstrainedDecl,
                          Normalized
-                             ? new (Context) NormalizedConstraint(
+                             ? new (SemaRef.Context) NormalizedConstraint(
                                  std::move(*Normalized))
                              : nullptr)
             .first;
@@ -1377,7 +1344,7 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
       // expression, the program is ill-formed; no diagnostic is required.
       // [...]
       ConceptDecl *CD = CSE->getNamedConcept();
-      SubNF = S.getNormalizedAssociatedConstraints(CD,
+      SubNF = S.Concept().getNormalizedAssociatedConstraints(CD,
                                                    {CD->getConstraintExpr()});
       if (!SubNF)
         return std::nullopt;
@@ -1496,12 +1463,12 @@ static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
   //   In order to determine if a constraint P subsumes a constraint Q, P is
   //   transformed into disjunctive normal form, and Q is transformed into
   //   conjunctive normal form. [...]
-  auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
+  auto *PNormalized = S.Concept().getNormalizedAssociatedConstraints(DP, P);
   if (!PNormalized)
     return true;
   const NormalForm PDNF = makeDNF(*PNormalized);
 
-  auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
+  auto *QNormalized = S.Concept().getNormalizedAssociatedConstraints(DQ, Q);
   if (!QNormalized)
     return true;
   const NormalForm QCNF = makeCNF(*QNormalized);
@@ -1510,7 +1477,7 @@ static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
   return false;
 }
 
-bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
+bool SemaConcept::IsAtLeastAsConstrained(NamedDecl *D1,
                                   MutableArrayRef<const Expr *> AC1,
                                   NamedDecl *D2,
                                   MutableArrayRef<const Expr *> AC2,
@@ -1547,33 +1514,33 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
     return false;
   }
 
-  unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
-  unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
+  unsigned Depth1 = CalculateTemplateDepthForConstraints(SemaRef, D1, true);
+  unsigned Depth2 = CalculateTemplateDepthForConstraints(SemaRef, D2, true);
 
   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
     if (Depth2 > Depth1) {
-      AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
+      AC1[I] = AdjustConstraintDepth(SemaRef, Depth2 - Depth1)
                    .TransformExpr(const_cast<Expr *>(AC1[I]))
                    .get();
     } else if (Depth1 > Depth2) {
-      AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
+      AC2[I] = AdjustConstraintDepth(SemaRef, Depth1 - Depth2)
                    .TransformExpr(const_cast<Expr *>(AC2[I]))
                    .get();
     }
   }
 
-  if (subsumes(*this, D1, AC1, D2, AC2, Result,
+  if (subsumes(SemaRef, D1, AC1, D2, AC2, Result,
         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
-          return A.subsumes(Context, B);
+          return A.subsumes(SemaRef.Context, B);
         }))
     return true;
   SubsumptionCache.try_emplace(Key, Result);
   return false;
 }
 
-bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
+bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
-  if (isSFINAEContext())
+  if (SemaRef.isSFINAEContext())
     // No need to work here because our notes would be discarded.
     return false;
 
@@ -1582,13 +1549,13 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
 
   auto NormalExprEvaluator =
       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
-        return A.subsumes(Context, B);
+        return A.subsumes(SemaRef.Context, B);
       };
 
   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
   auto IdenticalExprEvaluator =
       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
-        if (!A.hasMatchingParameterMapping(Context, B))
+        if (!A.hasMatchingParameterMapping(SemaRef.Context, B))
           return false;
         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
         if (EA == EB)
@@ -1597,8 +1564,8 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
         // Not the same source level expression - are the expressions
         // identical?
         llvm::FoldingSetNodeID IDA, IDB;
-        EA->Profile(IDA, Context, /*Canonical=*/true);
-        EB->Profile(IDB, Context, /*Canonical=*/true);
+        EA->Profile(IDA, SemaRef.Context, /*Canonical=*/true);
+        EB->Profile(IDB, SemaRef.Context, /*Canonical=*/true);
         if (IDA != IDB)
           return false;
 
@@ -1609,7 +1576,7 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
 
   {
     // The subsumption checks might cause diagnostics
-    SFINAETrap Trap(*this);
+    Sema::SFINAETrap Trap(SemaRef);
     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
     if (!Normalized1)
       return false;
@@ -1700,3 +1667,23 @@ concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
     Value(T),
     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
                                                         : SS_Satisfied) {}
+
+clang::SemaConcept::SemaConcept(Sema &S) : SemaBase(S), SatisfactionCache(S.Context) {}
+
+clang::SemaConcept::~SemaConcept() {
+  // Delete cached satisfactions.
+  std::vector<ConstraintSatisfaction *> Satisfactions;
+  Satisfactions.reserve(SatisfactionCache.size());
+  for (auto &Node : SatisfactionCache)
+    Satisfactions.push_back(&Node);
+  for (auto *Node : Satisfactions)
+    delete Node;
+}
+
+clang::SemaConcept::SatisfactionStackResetRAII::SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
+  SemaRef.Concept().SwapSatisfactionStack(BackupSatisfactionStack);
+}
+
+clang::SemaConcept::SatisfactionStackResetRAII::~SatisfactionStackResetRAII() {
+  SemaRef.Concept().SwapSatisfactionStack(BackupSatisfactionStack);
+}
\ No newline at end of file
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f2b9202255cd4..50715866b357d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -46,6 +46,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
@@ -10901,7 +10902,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
     // Precalculate whether this is a friend function template with a constraint
     // that depends on an enclosing template, per [temp.friend]p9.
     if (isFriend && FunctionTemplate &&
-        FriendConstraintsDependOnEnclosingTemplate(NewFD)) {
+        Concept().FriendConstraintsDependOnEnclosingTemplate(NewFD)) {
       NewFD->setFriendConstraintRefersToEnclosingTemplate(true);
 
       // C++ [temp.friend]p9:
@@ -18977,7 +18978,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
       SatisfactionStatus.push_back(true);
     else {
       ConstraintSatisfaction Satisfaction;
-      if (S.CheckFunctionConstraints(Method, Satisfaction))
+      if (S.Concept().CheckFunctionConstraints(Method, Satisfaction))
         SatisfactionStatus.push_back(false);
       else
         SatisfactionStatus.push_back(Satisfaction.IsSatisfied);
@@ -19012,7 +19013,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
         AnotherMethodIsMoreConstrained = true;
         break;
       }
-      if (S.IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, OrigMethod,
+      if (S.Concept().IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, OrigMethod,
                                    {Constraints},
                                    AnotherMethodIsMoreConstrained)) {
         // There was an error with the constraints comparison. Exit the loop
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8225381985052..a087b8592bdb0 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -43,6 +43,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -7466,7 +7467,7 @@ static bool specialMemberIsConstexpr(
   // Suppress duplicate constraint checking here, in case a constraint check
   // caused us to decide to do this.  Any truely recursive checks will get
   // caught during these checks anyway.
-  Sema::SatisfactionStackResetRAII SSRAII{S};
+  SemaConcept::SatisfactionStackResetRAII SSRAII{S};
 
   // If we're inheriting a constructor, see if we need to call it for this base
   // class.
@@ -17585,8 +17586,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
         Diag(AssertExpr->getBeginLoc(), diag::err_static_assert_failed)
             << !HasMessage << Msg.str() << AssertExpr->getSourceRange();
         ConstraintSatisfaction Satisfaction;
-        if (!CheckConstraintSatisfaction(InnerCond, Satisfaction))
-          DiagnoseUnsatisfiedConstraint(Satisfaction);
+        if (!Concept().CheckConstraintSatisfaction(InnerCond, Satisfaction))
+          Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
       } else if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
                            && !isa<IntegerLiteral>(InnerCond)) {
         Diag(InnerCond->getBeginLoc(),
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 5ecfdee21f09d..b9ab327d37247 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -50,6 +50,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaFixItUtils.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
@@ -294,7 +295,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
     // definition.
     if (!SkipTrailingRequiresClause && FD->getTrailingRequiresClause()) {
       ConstraintSatisfaction Satisfaction;
-      if (CheckFunctionConstraints(FD, Satisfaction, Loc,
+      if (Concept().CheckFunctionConstraints(FD, Satisfaction, Loc,
                                    /*ForOverloadResolution*/ true))
         // A diagnostic will have already been generated (non-constant
         // constraint expression, for example)
@@ -303,7 +304,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
         Diag(Loc,
              diag::err_reference_to_function_with_unsatisfied_constraints)
             << D;
-        DiagnoseUnsatisfiedConstraint(Satisfaction);
+        Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
         return true;
       }
     }
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e4601f7d6c47d..b75ff7f011ae8 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -39,6 +39,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaLambda.h"
 #include "clang/Sema/SemaObjC.h"
@@ -9389,7 +9390,7 @@ concepts::NestedRequirement *
 Sema::BuildNestedRequirement(Expr *Constraint) {
   ConstraintSatisfaction Satisfaction;
   if (!Constraint->isInstantiationDependent() &&
-      CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
+      Concept().CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
                                   Constraint->getSourceRange(), Satisfaction))
     return nullptr;
   return new (Context) concepts::NestedRequirement(Context, Constraint,
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 2eb25237a0de6..4dc433cc0b6c7 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -32,6 +32,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Overload.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/Template.h"
@@ -1518,7 +1519,7 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
     if ((NewRC != nullptr) != (OldRC != nullptr))
       return true;
     if (NewRC &&
-        !SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
+        !SemaRef.Concept().AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
       return true;
   }
 
@@ -7093,7 +7094,7 @@ void Sema::AddOverloadCandidate(
 
   if (Function->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
-    if (CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
+    if (Concept().CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
                                  /*ForOverloadResolution*/ true) ||
         !Satisfaction.IsSatisfied) {
       Candidate.Viable = false;
@@ -7611,7 +7612,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
 
   if (Method->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
-    if (CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
+    if (Concept().CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
                                  /*ForOverloadResolution*/ true) ||
         !Satisfaction.IsSatisfied) {
       Candidate.Viable = false;
@@ -8041,7 +8042,7 @@ void Sema::AddConversionCandidate(
 
   if (Conversion->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
-    if (CheckFunctionConstraints(Conversion, Satisfaction) ||
+    if (Concept().CheckFunctionConstraints(Conversion, Satisfaction) ||
         !Satisfaction.IsSatisfied) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -8324,7 +8325,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
 
   if (Conversion->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
-    if (CheckFunctionConstraints(Conversion, Satisfaction, /*Loc*/ {},
+    if (Concept().CheckFunctionConstraints(Conversion, Satisfaction, /*Loc*/ {},
                                  /*ForOverloadResolution*/ true) ||
         !Satisfaction.IsSatisfied) {
       Candidate.Viable = false;
@@ -11070,7 +11071,7 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
 
   if (FD->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
-    if (S.CheckFunctionConstraints(FD, Satisfaction, Loc))
+    if (S.Concept().CheckFunctionConstraints(FD, Satisfaction, Loc))
       return false;
     if (!Satisfaction.IsSatisfied) {
       if (Complain) {
@@ -11089,7 +11090,7 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
         } else
           S.Diag(Loc, diag::err_addrof_function_constraints_not_satisfied)
               << FD;
-        S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+        S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
       }
       return false;
     }
@@ -11220,7 +11221,7 @@ MaybeDiagnoseAmbiguousConstraints(Sema &S, ArrayRef<OverloadCandidate> Cands) {
     return;
   // The diagnostic can only happen if there are associated constraints on
   // both sides (there needs to be some identical atomic constraint).
-  if (S.MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
+  if (S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
                                                       SecondCand, SecondAC))
     // Just show the user one diagnostic, they'll probably figure it out
     // from here.
@@ -11746,7 +11747,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
            diag::note_ovl_candidate_unsatisfied_constraints)
         << TemplateArgString;
 
-    S.DiagnoseUnsatisfiedConstraint(
+    S.Concept().DiagnoseUnsatisfiedConstraint(
         static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
     return;
   }
@@ -12134,9 +12135,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
         << (unsigned)FnKindPair.first << (unsigned)ocs_non_template
         << FnDesc /* Ignored */;
     ConstraintSatisfaction Satisfaction;
-    if (S.CheckFunctionConstraints(Fn, Satisfaction))
+    if (S.Concept().CheckFunctionConstraints(Fn, Satisfaction))
       break;
-    S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+    S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
   }
   }
 }
@@ -12178,8 +12179,8 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
            diag::note_ovl_surrogate_constraints_not_satisfied)
         << Cand->Surrogate;
     ConstraintSatisfaction Satisfaction;
-    if (S.CheckFunctionConstraints(Cand->Surrogate, Satisfaction))
-      S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+    if (S.Concept().CheckFunctionConstraints(Cand->Surrogate, Satisfaction))
+      S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
   } else {
     S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
         << FnType;
@@ -13822,7 +13823,7 @@ DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
 namespace {
 class BuildRecoveryCallExprRAII {
   Sema &SemaRef;
-  Sema::SatisfactionStackResetRAII SatStack;
+  SemaConcept::SatisfactionStackResetRAII SatStack;
 
 public:
   BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S), SatStack(S) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4937cce4621f0..57ab161549450 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -34,6 +34,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/Template.h"
 #include "clang/Sema/TemplateDeduction.h"
@@ -5166,7 +5167,7 @@ static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
   SmallVector<const Expr *, 3> PartialAC, TemplateAC;
   Template->getAssociatedConstraints(TemplateAC);
   Partial->getAssociatedConstraints(PartialAC);
-  S.MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Partial, PartialAC, Template,
+  S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Partial, PartialAC, Template,
                                                   TemplateAC);
 }
 
@@ -5670,7 +5671,7 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
       *this, ExpressionEvaluationContext::ConstantEvaluated, CSD};
 
   if (!AreArgsDependent &&
-      CheckConstraintSatisfaction(
+      Concept().CheckConstraintSatisfaction(
           NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
           SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
                       TemplateArgs->getRAngleLoc()),
@@ -6946,7 +6947,7 @@ bool Sema::CheckTemplateArgumentList(
         /*RelativeToPrimary=*/true,
         /*Pattern=*/nullptr,
         /*ForConceptInstantiation=*/true);
-    if (EnsureTemplateArgumentListConstraints(
+    if (Concept().EnsureTemplateArgumentListConstraints(
             Template, MLTAL,
             SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) {
       if (ConstraintsNotSatisfied)
@@ -8545,7 +8546,7 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
       Template->getAssociatedConstraints(TemplateAC);
 
       bool IsParamAtLeastAsConstrained;
-      if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
+      if (Concept().IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
                                  IsParamAtLeastAsConstrained))
         return true;
       if (!IsParamAtLeastAsConstrained) {
@@ -8555,7 +8556,7 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
         Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
         Diag(Template->getLocation(), diag::note_entity_declared_at)
             << Template;
-        MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
+        Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
                                                       TemplateAC);
         return true;
       }
@@ -8884,7 +8885,7 @@ Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
 /// Match two template parameters within template parameter lists.
 static bool MatchTemplateParameterKind(
     Sema &S, NamedDecl *New,
-    const Sema::TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
+    const TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
     const NamedDecl *OldInstFrom, bool Complain,
     Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
   // Check the actual kind (type, non-type, template).
@@ -9019,7 +9020,7 @@ static bool MatchTemplateParameterKind(
     }
 
     if (NewC) {
-      if (!S.AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom,
+      if (!S.Concept().AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom,
                                            NewC)) {
         if (Complain)
           Diagnose();
@@ -9161,7 +9162,7 @@ bool Sema::TemplateParameterListsAreEqual(
     }
 
     if (NewRC) {
-      if (!AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom,
+      if (!Concept().AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom,
                                          NewRC)) {
         if (Complain)
           Diagnose();
@@ -10566,7 +10567,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
         continue;
       if (ConstraintSatisfaction Satisfaction;
           Method->getTrailingRequiresClause() &&
-          (CheckFunctionConstraints(Method, Satisfaction,
+          (Concept().CheckFunctionConstraints(Method, Satisfaction,
                                     /*UsageLoc=*/Member->getLocation(),
                                     /*ForOverloadResolution=*/true) ||
            !Satisfaction.IsSatisfied))
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 41fd210f29d09..26c0f8472dde1 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -39,6 +39,7 @@
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/Ownership.h"
 #include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/Template.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "llvm/ADT/APInt.h"
@@ -3088,7 +3089,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
   if (!Innermost)
     MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
 
-  if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
+  if (S.Concept().CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
                                     Info.getLocation(),
                                     Info.AssociatedConstraintsSatisfaction) ||
       !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
@@ -3940,7 +3941,7 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
   if (!PartialOverloading ||
       (CanonicalBuilder.size() ==
        FunctionTemplate->getTemplateParameters()->size())) {
-    if (CheckInstantiatedFunctionTemplateConstraints(
+    if (Concept().CheckInstantiatedFunctionTemplateConstraints(
             Info.getLocation(), Specialization, CanonicalBuilder,
             Info.AssociatedConstraintsSatisfaction))
       return TemplateDeductionResult::MiscellaneousDeductionFailure;
@@ -5100,7 +5101,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
     return true;
   MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted,
                                        /*Final=*/false);
-  if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
+  if (S.Concept().CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
                                     MLTAL, TypeLoc.getLocalSourceRange(),
                                     Satisfaction))
     return true;
@@ -5118,7 +5119,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
     S.Diag(TypeLoc.getConceptNameLoc(),
            diag::err_placeholder_constraints_not_satisfied)
         << Deduced << Buf << TypeLoc.getLocalSourceRange();
-    S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+    S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
     return true;
   }
   return false;
@@ -5853,9 +5854,9 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   FT1->getAssociatedConstraints(AC1);
   FT2->getAssociatedConstraints(AC2);
   bool AtLeastAsConstrained1, AtLeastAsConstrained2;
-  if (IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
+  if (Concept().IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
     return nullptr;
-  if (IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
+  if (Concept().IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
     return nullptr;
   if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
     return nullptr;
@@ -5996,9 +5997,9 @@ FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1,
   F1->getAssociatedConstraints(AC1);
   F2->getAssociatedConstraints(AC2);
   bool AtLeastAsConstrained1, AtLeastAsConstrained2;
-  if (IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
+  if (Concept().IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
     return nullptr;
-  if (IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
+  if (Concept().IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
     return nullptr;
   if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
     return nullptr;
@@ -6231,10 +6232,10 @@ getMoreSpecialized(Sema &S, QualType T1, QualType T2, TemplateLikeDecl *P1,
   P1->getAssociatedConstraints(AC1);
   P2->getAssociatedConstraints(AC2);
   bool AtLeastAsConstrained1, AtLeastAsConstrained2;
-  if (S.IsAtLeastAsConstrained(P1, AC1, P2, AC2, AtLeastAsConstrained1) ||
+  if (S.Concept().IsAtLeastAsConstrained(P1, AC1, P2, AC2, AtLeastAsConstrained1) ||
       (IsMoreSpecialThanPrimaryCheck && !AtLeastAsConstrained1))
     return nullptr;
-  if (S.IsAtLeastAsConstrained(P2, AC2, P1, AC1, AtLeastAsConstrained2))
+  if (S.Concept().IsAtLeastAsConstrained(P2, AC2, P1, AC1, AtLeastAsConstrained2))
     return nullptr;
   if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
     return nullptr;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 07626058c7977..537982d94570e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2802,7 +2802,7 @@ TemplateInstantiator::TransformNestedRequirement(
     if (ConstrInst.isInvalid())
       return nullptr;
     llvm::SmallVector<Expr *> Result;
-    if (!SemaRef.CheckConstraintSatisfaction(
+    if (!SemaRef.Concept().CheckConstraintSatisfaction(
             nullptr, {Req->getConstraintExpr()}, Result, TemplateArgs,
             Req->getConstraintExpr()->getSourceRange(), Satisfaction) &&
         !Result.empty())
@@ -4135,7 +4135,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
 
         if (Function->getTrailingRequiresClause()) {
           ConstraintSatisfaction Satisfaction;
-          if (CheckFunctionConstraints(Function, Satisfaction) ||
+          if (Concept().CheckFunctionConstraints(Function, Satisfaction) ||
               !Satisfaction.IsSatisfied) {
             continue;
           }
@@ -4634,3 +4634,40 @@ NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
 
   return nullptr;
 }
+
+bool Sema::addInstantiatedCapturesToScope(
+    FunctionDecl *Function, const FunctionDecl *PatternDecl,
+    LocalInstantiationScope &Scope,
+    const MultiLevelTemplateArgumentList &TemplateArgs) {
+  const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
+  const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
+
+  unsigned Instantiated = 0;
+
+  auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
+                              unsigned Index) {
+    ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
+    if (CapturedVar->isInitCapture())
+      Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
+  };
+
+  for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
+    if (!CapturePattern.capturesVariable()) {
+      Instantiated++;
+      continue;
+    }
+    const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
+    if (!CapturedPattern->isParameterPack()) {
+      AddSingleCapture(CapturedPattern, Instantiated++);
+    } else {
+      Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
+      std::optional<unsigned> NumArgumentsInExpansion =
+          SemaRef.getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
+      if (!NumArgumentsInExpansion)
+        continue;
+      for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
+        AddSingleCapture(CapturedPattern, Instantiated++);
+    }
+  }
+  return false;
+}

>From ed40814844abfe84afe83a357ebdf06ac1bc5deb Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 23:23:37 +0300
Subject: [PATCH 2/4] Move more functions to `SemaConcept`

---
 clang/include/clang/Sema/Sema.h               |  89 +--
 clang/include/clang/Sema/SemaConcept.h        | 119 ++++
 clang/lib/Parse/ParseDecl.cpp                 |   3 +-
 clang/lib/Parse/ParseDeclCXX.cpp              |   4 +-
 clang/lib/Parse/ParseExprCXX.cpp              |  21 +-
 clang/lib/Parse/ParseTemplate.cpp             |   9 +-
 clang/lib/Sema/SemaChecking.cpp               |   6 -
 clang/lib/Sema/SemaConcept.cpp                | 653 ++++++++++++++++++
 clang/lib/Sema/SemaDecl.cpp                   |   2 +-
 clang/lib/Sema/SemaDeclCXX.cpp                |  33 -
 clang/lib/Sema/SemaExprCXX.cpp                | 227 ------
 clang/lib/Sema/SemaOverload.cpp               |   6 +-
 clang/lib/Sema/SemaTemplate.cpp               | 383 +---------
 clang/lib/Sema/SemaTemplateDeduction.cpp      |  32 -
 clang/lib/Sema/SemaTemplateInstantiate.cpp    |   2 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   3 +-
 clang/lib/Sema/SemaType.cpp                   |   7 +-
 clang/lib/Sema/TreeTransform.h                |  15 +-
 18 files changed, 824 insertions(+), 790 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e92eb929e62e..06be666027742 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2036,8 +2036,6 @@ class Sema final : public SemaBase {
   void CheckTCBEnforcement(const SourceLocation CallExprLoc,
                            const NamedDecl *Callee);
 
-  void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc);
-
 private:
   void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
                         const ArraySubscriptExpr *ASE = nullptr,
@@ -4735,9 +4733,6 @@ class Sema final : public SemaBase {
 
   void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
                            StringLiteral *DeletedMessage = nullptr);
-  void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
-  ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
-  ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
 
   NamedDecl *
   ActOnDecompositionDeclarator(Scope *S, Declarator &D,
@@ -6819,45 +6814,6 @@ class Sema final : public SemaBase {
                                               bool IsIfExists, CXXScopeSpec &SS,
                                               UnqualifiedId &Name);
 
-  RequiresExprBodyDecl *
-  ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
-                         ArrayRef<ParmVarDecl *> LocalParameters,
-                         Scope *BodyScope);
-  void ActOnFinishRequiresExpr();
-  concepts::Requirement *ActOnSimpleRequirement(Expr *E);
-  concepts::Requirement *ActOnTypeRequirement(SourceLocation TypenameKWLoc,
-                                              CXXScopeSpec &SS,
-                                              SourceLocation NameLoc,
-                                              const IdentifierInfo *TypeName,
-                                              TemplateIdAnnotation *TemplateId);
-  concepts::Requirement *ActOnCompoundRequirement(Expr *E,
-                                                  SourceLocation NoexceptLoc);
-  concepts::Requirement *ActOnCompoundRequirement(
-      Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
-      TemplateIdAnnotation *TypeConstraint, unsigned Depth);
-  concepts::Requirement *ActOnNestedRequirement(Expr *Constraint);
-  concepts::ExprRequirement *BuildExprRequirement(
-      Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc,
-      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
-  concepts::ExprRequirement *BuildExprRequirement(
-      concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag,
-      bool IsSatisfied, SourceLocation NoexceptLoc,
-      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
-  concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type);
-  concepts::TypeRequirement *BuildTypeRequirement(
-      concepts::Requirement::SubstitutionDiagnostic *SubstDiag);
-  concepts::NestedRequirement *BuildNestedRequirement(Expr *E);
-  concepts::NestedRequirement *
-  BuildNestedRequirement(StringRef InvalidConstraintEntity,
-                         const ASTConstraintSatisfaction &Satisfaction);
-  ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc,
-                               RequiresExprBodyDecl *Body,
-                               SourceLocation LParenLoc,
-                               ArrayRef<ParmVarDecl *> LocalParameters,
-                               SourceLocation RParenLoc,
-                               ArrayRef<concepts::Requirement *> Requirements,
-                               SourceLocation ClosingBraceLoc);
-
 private:
   ExprResult BuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
                                                 bool IsDelete);
@@ -8855,30 +8811,6 @@ class Sema final : public SemaBase {
                                 unsigned Position, SourceLocation EqualLoc,
                                 ParsedType DefaultArg, bool HasTypeConstraint);
 
-  bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
-
-  bool ActOnTypeConstraint(const CXXScopeSpec &SS,
-                           TemplateIdAnnotation *TypeConstraint,
-                           TemplateTypeParmDecl *ConstrainedParameter,
-                           SourceLocation EllipsisLoc);
-  bool BuildTypeConstraint(const CXXScopeSpec &SS,
-                           TemplateIdAnnotation *TypeConstraint,
-                           TemplateTypeParmDecl *ConstrainedParameter,
-                           SourceLocation EllipsisLoc,
-                           bool AllowUnexpandedPack);
-
-  bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
-                            DeclarationNameInfo NameInfo,
-                            ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
-                            const TemplateArgumentListInfo *TemplateArgs,
-                            TemplateTypeParmDecl *ConstrainedParameter,
-                            SourceLocation EllipsisLoc);
-
-  bool AttachTypeConstraint(AutoTypeLoc TL,
-                            NonTypeTemplateParmDecl *NewConstrainedParm,
-                            NonTypeTemplateParmDecl *OrigConstrainedParm,
-                            SourceLocation EllipsisLoc);
-
   bool RequireStructuralType(QualType T, SourceLocation Loc);
 
   QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
@@ -8982,12 +8914,6 @@ class Sema final : public SemaBase {
                                 SourceLocation TemplateLoc,
                                 const TemplateArgumentListInfo *TemplateArgs);
 
-  ExprResult
-  CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
-                         const DeclarationNameInfo &ConceptNameInfo,
-                         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
-                         const TemplateArgumentListInfo *TemplateArgs);
-
   void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
 
   ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -9329,15 +9255,6 @@ class Sema final : public SemaBase {
 
   void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
 
-  Decl *ActOnConceptDefinition(Scope *S,
-                               MultiTemplateParamsArg TemplateParameterLists,
-                               const IdentifierInfo *Name,
-                               SourceLocation NameLoc, Expr *ConstraintExpr,
-                               const ParsedAttributesView &Attrs);
-
-  void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
-                                bool &AddToScope);
-
   TypeResult ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
                                const CXXScopeSpec &SS,
                                const IdentifierInfo *Name,
@@ -9354,6 +9271,9 @@ class Sema final : public SemaBase {
   void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
   void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec);
 
+  TemplateArgumentListInfo
+  makeTemplateArgumentListInfo(TemplateIdAnnotation &TemplateId);
+
   ///@}
 
   //
@@ -9621,9 +9541,6 @@ class Sema final : public SemaBase {
                      const PartialDiagnostic &CandidateDiag,
                      bool Complain = true, QualType TargetType = QualType());
 
-  FunctionDecl *getMoreConstrainedFunction(FunctionDecl *FD1,
-                                           FunctionDecl *FD2);
-
   ///@}
 
   //
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 7104e91f24b61..1e24921354cdc 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -14,13 +14,35 @@
 #define LLVM_CLANG_SEMA_SEMACONCEPT_H
 #include "clang/AST/ASTConcept.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Lex/Token.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaBase.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include <optional>
 #include <string>
 #include <utility>
@@ -153,6 +175,7 @@ struct NormalizedConstraint {
 };
 
 class LocalInstantiationScope;
+class LookupResult;
 class MultiLevelTemplateArgumentList;
 
 // A struct to represent the 'new' declaration, which is either itself just
@@ -399,6 +422,102 @@ class SemaConcept : public SemaBase {
                        const MultiLevelTemplateArgumentList &MLTAL,
                        LocalInstantiationScope &Scope);
 
+  RequiresExprBodyDecl *
+  ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
+                         ArrayRef<ParmVarDecl *> LocalParameters,
+                         Scope *BodyScope);
+  void ActOnFinishRequiresExpr();
+  concepts::Requirement *ActOnSimpleRequirement(Expr *E);
+  concepts::Requirement *ActOnTypeRequirement(SourceLocation TypenameKWLoc,
+                                              CXXScopeSpec &SS,
+                                              SourceLocation NameLoc,
+                                              const IdentifierInfo *TypeName,
+                                              TemplateIdAnnotation *TemplateId);
+  concepts::Requirement *ActOnCompoundRequirement(Expr *E,
+                                                  SourceLocation NoexceptLoc);
+  concepts::Requirement *ActOnCompoundRequirement(
+      Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
+      TemplateIdAnnotation *TypeConstraint, unsigned Depth);
+  concepts::Requirement *ActOnNestedRequirement(Expr *Constraint);
+  concepts::ExprRequirement *BuildExprRequirement(
+      Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc,
+      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
+  concepts::ExprRequirement *BuildExprRequirement(
+      concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag,
+      bool IsSatisfied, SourceLocation NoexceptLoc,
+      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
+  concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type);
+  concepts::TypeRequirement *BuildTypeRequirement(
+      concepts::Requirement::SubstitutionDiagnostic *SubstDiag);
+  concepts::NestedRequirement *BuildNestedRequirement(Expr *E);
+  concepts::NestedRequirement *
+  BuildNestedRequirement(StringRef InvalidConstraintEntity,
+                         const ASTConstraintSatisfaction &Satisfaction);
+  ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc,
+                               RequiresExprBodyDecl *Body,
+                               SourceLocation LParenLoc,
+                               ArrayRef<ParmVarDecl *> LocalParameters,
+                               SourceLocation RParenLoc,
+                               ArrayRef<concepts::Requirement *> Requirements,
+                               SourceLocation ClosingBraceLoc);
+
+  bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
+
+  bool ActOnTypeConstraint(const CXXScopeSpec &SS,
+                           TemplateIdAnnotation *TypeConstraint,
+                           TemplateTypeParmDecl *ConstrainedParameter,
+                           SourceLocation EllipsisLoc);
+  bool BuildTypeConstraint(const CXXScopeSpec &SS,
+                           TemplateIdAnnotation *TypeConstraint,
+                           TemplateTypeParmDecl *ConstrainedParameter,
+                           SourceLocation EllipsisLoc,
+                           bool AllowUnexpandedPack);
+  
+  bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
+                            DeclarationNameInfo NameInfo,
+                            ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
+                            const TemplateArgumentListInfo *TemplateArgs,
+                            TemplateTypeParmDecl *ConstrainedParameter,
+                            SourceLocation EllipsisLoc);
+
+  bool AttachTypeConstraint(AutoTypeLoc TL,
+                            NonTypeTemplateParmDecl *NewConstrainedParm,
+                            NonTypeTemplateParmDecl *OrigConstrainedParm,
+                            SourceLocation EllipsisLoc);
+
+  ExprResult
+  CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                         const DeclarationNameInfo &ConceptNameInfo,
+                         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+                         const TemplateArgumentListInfo *TemplateArgs);
+
+  Decl *ActOnConceptDefinition(Scope *S,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                               const IdentifierInfo *Name,
+                               SourceLocation NameLoc, Expr *ConstraintExpr,
+                               const ParsedAttributesView &Attrs);
+
+  void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
+                                bool &AddToScope);
+
+  void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
+  ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
+  ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
+
+  void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc);
+
+  /// Returns the more constrained function according to the rules of
+  /// partial ordering by constraints (C++ [temp.constr.order]).
+  ///
+  /// \param FD1 the first function
+  ///
+  /// \param FD2 the second function
+  ///
+  /// \returns the more constrained function. If neither function is
+  /// more constrained, returns NULL.
+  FunctionDecl *getMoreConstrainedFunction(FunctionDecl *FD1,
+                                           FunctionDecl *FD2);
+
 private:
   /// Caches pairs of template-like decls whose associated constraints were
   /// checked for subsumption and whether or not the first's constraints did in
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 8405b44685ae4..bd66ef5318c80 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -28,6 +28,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCUDA.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -4082,7 +4083,7 @@ void Parser::ParseDeclarationSpecifiers(
         if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
             goto DoneWithDeclSpec;
 
-        if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId))
+        if (TemplateId && !isInvalid && Actions.Concept().CheckTypeConstraint(TemplateId))
             TemplateId = nullptr;
 
         ConsumeAnnotationToken();
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 5eaec2b621e6f..a658c03eda4bc 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4290,7 +4290,7 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) {
                                   Scope::FunctionDeclarationScope |
                                   Scope::FunctionPrototypeScope);
 
-  Actions.ActOnStartTrailingRequiresClause(getCurScope(), D);
+  Actions.Concept().ActOnStartTrailingRequiresClause(getCurScope(), D);
 
   std::optional<Sema::CXXThisScopeRAII> ThisScope;
   InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope);
@@ -4299,7 +4299,7 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) {
       ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);
 
   TrailingRequiresClause =
-      Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause);
+      Actions.Concept().ActOnFinishTrailingRequiresClause(TrailingRequiresClause);
 
   if (!D.isDeclarationOfFunction()) {
     Diag(RequiresKWLoc,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index e149b1a0fb5ef..224431846fc0f 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -24,6 +24,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaConcept.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <numeric>
@@ -1418,7 +1419,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
       ExprResult RequiresClause;
       if (TryConsumeToken(tok::kw_requires)) {
         RequiresClause =
-            Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+            Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
                 /*IsTrailingRequiresClause=*/false));
         if (RequiresClause.isInvalid())
           SkipUntil({tok::l_brace, tok::l_paren}, StopAtSemi | StopBeforeMatch);
@@ -3628,7 +3629,7 @@ ExprResult Parser::ParseRequiresExpression() {
   // Dependent diagnostics are attached to this Decl and non-depenedent
   // diagnostics are surfaced after this parse.
   ParsingDeclRAIIObject ParsingBodyDecl(*this, ParsingDeclRAIIObject::NoParent);
-  RequiresExprBodyDecl *Body = Actions.ActOnStartRequiresExpr(
+  RequiresExprBodyDecl *Body = Actions.Concept().ActOnStartRequiresExpr(
       RequiresKWLoc, LocalParameterDecls, getCurScope());
 
   if (Tok.is(tok::r_brace)) {
@@ -3669,7 +3670,7 @@ ExprResult Parser::ParseRequiresExpression() {
         SourceLocation NoexceptLoc;
         TryConsumeToken(tok::kw_noexcept, NoexceptLoc);
         if (Tok.is(tok::semi)) {
-          Req = Actions.ActOnCompoundRequirement(Expression.get(), NoexceptLoc);
+          Req = Actions.Concept().ActOnCompoundRequirement(Expression.get(), NoexceptLoc);
           if (Req)
             Requirements.push_back(Req);
           break;
@@ -3696,7 +3697,7 @@ ExprResult Parser::ParseRequiresExpression() {
           ConsumeAnnotationToken();
         }
 
-        Req = Actions.ActOnCompoundRequirement(
+        Req = Actions.Concept().ActOnCompoundRequirement(
             Expression.get(), NoexceptLoc, SS, takeTemplateIdAnnotation(Tok),
             TemplateParameterDepth);
         ConsumeAnnotationToken();
@@ -3765,7 +3766,7 @@ ExprResult Parser::ParseRequiresExpression() {
               break;
             }
             if (auto *Req =
-                    Actions.ActOnNestedRequirement(ConstraintExpr.get()))
+                    Actions.Concept().ActOnNestedRequirement(ConstraintExpr.get()))
               Requirements.push_back(Req);
             else {
               SkipUntil(tok::semi, tok::r_brace,
@@ -3810,7 +3811,7 @@ ExprResult Parser::ParseRequiresExpression() {
                 break;
             }
 
-            if (auto *Req = Actions.ActOnTypeRequirement(TypenameKWLoc, SS,
+            if (auto *Req = Actions.Concept().ActOnTypeRequirement(TypenameKWLoc, SS,
                                                          NameLoc, II,
                                                          TemplateId)) {
               Requirements.push_back(Req);
@@ -3833,7 +3834,7 @@ ExprResult Parser::ParseRequiresExpression() {
         if (!Expression.isInvalid() && PossibleRequiresExprInSimpleRequirement)
           Diag(StartLoc, diag::err_requires_expr_in_simple_requirement)
               << FixItHint::CreateInsertion(StartLoc, "requires");
-        if (auto *Req = Actions.ActOnSimpleRequirement(Expression.get()))
+        if (auto *Req = Actions.Concept().ActOnSimpleRequirement(Expression.get()))
           Requirements.push_back(Req);
         else {
           SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
@@ -3861,14 +3862,14 @@ ExprResult Parser::ParseRequiresExpression() {
       // other diagnostics quoting an empty requires expression they never
       // wrote.
       Braces.consumeClose();
-      Actions.ActOnFinishRequiresExpr();
+      Actions.Concept().ActOnFinishRequiresExpr();
       return ExprError();
     }
   }
   Braces.consumeClose();
-  Actions.ActOnFinishRequiresExpr();
+  Actions.Concept().ActOnFinishRequiresExpr();
   ParsingBodyDecl.complete(Body);
-  return Actions.ActOnRequiresExpr(
+  return Actions.Concept().ActOnRequiresExpr(
       RequiresKWLoc, Body, Parens.getOpenLocation(), LocalParameterDecls,
       Parens.getCloseLocation(), Requirements, Braces.getCloseLocation());
 }
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index a5130f56600e5..bd732dc50cf9d 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -20,6 +20,7 @@
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "llvm/Support/TimeProfiler.h"
 using namespace clang;
@@ -145,7 +146,7 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(
 
       if (TryConsumeToken(tok::kw_requires)) {
         OptionalRequiresClauseConstraintER =
-            Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+            Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
                 /*IsTrailingRequiresClause=*/false));
         if (!OptionalRequiresClauseConstraintER.isUsable()) {
           // Skip until the semi-colon or a '}'.
@@ -339,7 +340,7 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
   DeclEnd = Tok.getLocation();
   ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
   Expr *ConstraintExpr = ConstraintExprResult.get();
-  return Actions.ActOnConceptDefinition(getCurScope(),
+  return Actions.Concept().ActOnConceptDefinition(getCurScope(),
                                         *TemplateInfo.TemplateParams, Id, IdLoc,
                                         ConstraintExpr, Attrs);
 }
@@ -763,7 +764,7 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
                                                   TypeConstraint != nullptr);
 
   if (TypeConstraint) {
-    Actions.ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
+    Actions.Concept().ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
                                 cast<TemplateTypeParmDecl>(NewDecl),
                                 EllipsisLoc);
   }
@@ -800,7 +801,7 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
     }
     if (TryConsumeToken(tok::kw_requires)) {
       OptionalRequiresClauseConstraintER =
-          Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+          Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
               /*IsTrailingRequiresClause=*/false));
       if (!OptionalRequiresClauseConstraintER.isUsable()) {
         SkipUntil(tok::comma, tok::greater, tok::greatergreater,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index f2dc8e9dd0050..ecd1821651140 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -8092,12 +8092,6 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
     diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
 }
 
-void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
-  if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
-    DiagnoseUseOfDecl(Decl, Loc);
-  }
-}
-
 /// CheckConstructorCall - Check a constructor call for correctness and safety
 /// properties not enforced by the C type system.
 void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 3f92eac2e5769..8957c1d658cb1 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1668,6 +1668,659 @@ concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
                                                         : SS_Satisfied) {}
 
+RequiresExprBodyDecl *
+SemaConcept::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
+                             ArrayRef<ParmVarDecl *> LocalParameters,
+                             Scope *BodyScope) {
+  assert(BodyScope);
+
+  RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(SemaRef.Context, SemaRef.CurContext,
+                                                            RequiresKWLoc);
+
+  SemaRef.PushDeclContext(BodyScope, Body);
+
+  for (ParmVarDecl *Param : LocalParameters) {
+    if (Param->hasDefaultArg())
+      // C++2a [expr.prim.req] p4
+      //     [...] A local parameter of a requires-expression shall not have a
+      //     default argument. [...]
+      Diag(Param->getDefaultArgRange().getBegin(),
+           diag::err_requires_expr_local_parameter_default_argument);
+    // Ignore default argument and move on
+
+    Param->setDeclContext(Body);
+    // If this has an identifier, add it to the scope stack.
+    if (Param->getIdentifier()) {
+      SemaRef.CheckShadow(BodyScope, Param);
+      SemaRef.PushOnScopeChains(Param, BodyScope);
+    }
+  }
+  return Body;
+}
+
+void SemaConcept::ActOnFinishRequiresExpr() {
+  assert(SemaRef.CurContext && "DeclContext imbalance!");
+  SemaRef.CurContext = SemaRef.CurContext->getLexicalParent();
+  assert(SemaRef.CurContext && "Popped translation unit!");
+}
+
+concepts::Requirement *SemaConcept::ActOnSimpleRequirement(Expr *E) {
+  return BuildExprRequirement(E, /*IsSimple=*/true,
+                              /*NoexceptLoc=*/SourceLocation(),
+                              /*ReturnTypeRequirement=*/{});
+}
+
+concepts::Requirement *SemaConcept::ActOnTypeRequirement(
+    SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc,
+    const IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId) {
+  assert(((!TypeName && TemplateId) || (TypeName && !TemplateId)) &&
+         "Exactly one of TypeName and TemplateId must be specified.");
+  TypeSourceInfo *TSI = nullptr;
+  if (TypeName) {
+    QualType T =
+        SemaRef.CheckTypenameType(ElaboratedTypeKeyword::Typename, TypenameKWLoc,
+                          SS.getWithLocInContext(SemaRef.Context), *TypeName, NameLoc,
+                          &TSI, /*DeducedTSTContext=*/false);
+    if (T.isNull())
+      return nullptr;
+  } else {
+    ASTTemplateArgsPtr ArgsPtr(TemplateId->getTemplateArgs(),
+                               TemplateId->NumArgs);
+    TypeResult T = SemaRef.ActOnTypenameType(SemaRef.getCurScope(), TypenameKWLoc, SS,
+                                     TemplateId->TemplateKWLoc,
+                                     TemplateId->Template, TemplateId->Name,
+                                     TemplateId->TemplateNameLoc,
+                                     TemplateId->LAngleLoc, ArgsPtr,
+                                     TemplateId->RAngleLoc);
+    if (T.isInvalid())
+      return nullptr;
+    if (SemaRef.GetTypeFromParser(T.get(), &TSI).isNull())
+      return nullptr;
+  }
+  return BuildTypeRequirement(TSI);
+}
+
+concepts::Requirement *
+SemaConcept::ActOnCompoundRequirement(Expr *E, SourceLocation NoexceptLoc) {
+  return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc,
+                              /*ReturnTypeRequirement=*/{});
+}
+
+concepts::Requirement *
+SemaConcept::ActOnCompoundRequirement(
+    Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
+    TemplateIdAnnotation *TypeConstraint, unsigned Depth) {
+  // C++2a [expr.prim.req.compound] p1.3.3
+  //   [..] the expression is deduced against an invented function template
+  //   F [...] F is a void function template with a single type template
+  //   parameter T declared with the constrained-parameter. Form a new
+  //   cv-qualifier-seq cv by taking the union of const and volatile specifiers
+  //   around the constrained-parameter. F has a single parameter whose
+  //   type-specifier is cv T followed by the abstract-declarator. [...]
+  //
+  // The cv part is done in the calling function - we get the concept with
+  // arguments and the abstract declarator with the correct CV qualification and
+  // have to synthesize T and the single parameter of F.
+  auto &II = SemaRef.Context.Idents.get("expr-type");
+  auto *TParam = TemplateTypeParmDecl::Create(SemaRef.Context, SemaRef.CurContext,
+                                              SourceLocation(),
+                                              SourceLocation(), Depth,
+                                              /*Index=*/0, &II,
+                                              /*Typename=*/true,
+                                              /*ParameterPack=*/false,
+                                              /*HasTypeConstraint=*/true);
+
+  if (BuildTypeConstraint(SS, TypeConstraint, TParam,
+                          /*EllipsisLoc=*/SourceLocation(),
+                          /*AllowUnexpandedPack=*/true))
+    // Just produce a requirement with no type requirements.
+    return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {});
+
+  auto *TPL = TemplateParameterList::Create(SemaRef.Context, SourceLocation(),
+                                            SourceLocation(),
+                                            ArrayRef<NamedDecl *>(TParam),
+                                            SourceLocation(),
+                                            /*RequiresClause=*/nullptr);
+  return BuildExprRequirement(
+      E, /*IsSimple=*/false, NoexceptLoc,
+      concepts::ExprRequirement::ReturnTypeRequirement(TPL));
+}
+
+concepts::ExprRequirement *
+SemaConcept::BuildExprRequirement(
+    Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
+    concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
+  auto Status = concepts::ExprRequirement::SS_Satisfied;
+  ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
+  if (E->isInstantiationDependent() || E->getType()->isPlaceholderType() ||
+      ReturnTypeRequirement.isDependent())
+    Status = concepts::ExprRequirement::SS_Dependent;
+  else if (NoexceptLoc.isValid() && SemaRef.canThrow(E) == CanThrowResult::CT_Can)
+    Status = concepts::ExprRequirement::SS_NoexceptNotMet;
+  else if (ReturnTypeRequirement.isSubstitutionFailure())
+    Status = concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure;
+  else if (ReturnTypeRequirement.isTypeConstraint()) {
+    // C++2a [expr.prim.req]p1.3.3
+    //     The immediately-declared constraint ([temp]) of decltype((E)) shall
+    //     be satisfied.
+    TemplateParameterList *TPL =
+        ReturnTypeRequirement.getTypeConstraintTemplateParameterList();
+    QualType MatchedType =
+        SemaRef.Context.getReferenceQualifiedType(E).getCanonicalType();
+    llvm::SmallVector<TemplateArgument, 1> Args;
+    Args.push_back(TemplateArgument(MatchedType));
+
+    auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
+
+    MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false);
+    MLTAL.addOuterRetainedLevels(TPL->getDepth());
+    const TypeConstraint *TC = Param->getTypeConstraint();
+    assert(TC && "Type Constraint cannot be null here");
+    auto *IDC = TC->getImmediatelyDeclaredConstraint();
+    assert(IDC && "ImmediatelyDeclaredConstraint can't be null here.");
+    ExprResult Constraint = SemaRef.SubstExpr(IDC, MLTAL);
+    if (Constraint.isInvalid()) {
+      return new (SemaRef.Context) concepts::ExprRequirement(
+          concepts::createSubstDiagAt(SemaRef, IDC->getExprLoc(),
+                                      [&](llvm::raw_ostream &OS) {
+                                        IDC->printPretty(OS, /*Helper=*/nullptr,
+                                                         SemaRef.getPrintingPolicy());
+                                      }),
+          IsSimple, NoexceptLoc, ReturnTypeRequirement);
+    }
+    SubstitutedConstraintExpr =
+        cast<ConceptSpecializationExpr>(Constraint.get());
+    if (!SubstitutedConstraintExpr->isSatisfied())
+      Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
+  }
+  return new (SemaRef.Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
+                                                 ReturnTypeRequirement, Status,
+                                                 SubstitutedConstraintExpr);
+}
+
+concepts::ExprRequirement *
+SemaConcept::BuildExprRequirement(
+    concepts::Requirement::SubstitutionDiagnostic *ExprSubstitutionDiagnostic,
+    bool IsSimple, SourceLocation NoexceptLoc,
+    concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
+  return new (SemaRef.Context) concepts::ExprRequirement(ExprSubstitutionDiagnostic,
+                                                 IsSimple, NoexceptLoc,
+                                                 ReturnTypeRequirement);
+}
+
+concepts::TypeRequirement *
+SemaConcept::BuildTypeRequirement(TypeSourceInfo *Type) {
+  return new (SemaRef.Context) concepts::TypeRequirement(Type);
+}
+
+concepts::TypeRequirement *
+SemaConcept::BuildTypeRequirement(
+    concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
+  return new (SemaRef.Context) concepts::TypeRequirement(SubstDiag);
+}
+
+concepts::Requirement *SemaConcept::ActOnNestedRequirement(Expr *Constraint) {
+  return BuildNestedRequirement(Constraint);
+}
+
+concepts::NestedRequirement *
+SemaConcept::BuildNestedRequirement(Expr *Constraint) {
+  ConstraintSatisfaction Satisfaction;
+  if (!Constraint->isInstantiationDependent() &&
+      CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
+                                  Constraint->getSourceRange(), Satisfaction))
+    return nullptr;
+  return new (SemaRef.Context) concepts::NestedRequirement(SemaRef.Context, Constraint,
+                                                   Satisfaction);
+}
+
+concepts::NestedRequirement *
+SemaConcept::BuildNestedRequirement(StringRef InvalidConstraintEntity,
+                       const ASTConstraintSatisfaction &Satisfaction) {
+  return new (SemaRef.Context) concepts::NestedRequirement(
+      InvalidConstraintEntity,
+      ASTConstraintSatisfaction::Rebuild(SemaRef.Context, Satisfaction));
+}
+
+ExprResult SemaConcept::ActOnRequiresExpr(
+    SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
+    SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
+    SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
+    SourceLocation ClosingBraceLoc) {
+  auto *RE = RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body, LParenLoc,
+                                  LocalParameters, RParenLoc, Requirements,
+                                  ClosingBraceLoc);
+  if (SemaRef.DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
+    return ExprError();
+  return RE;
+}
+
+bool SemaConcept::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
+
+  TemplateName TN = TypeConstr->Template.get();
+  ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
+
+  // C++2a [temp.param]p4:
+  //     [...] The concept designated by a type-constraint shall be a type
+  //     concept ([temp.concept]).
+  if (!CD->isTypeConcept()) {
+    Diag(TypeConstr->TemplateNameLoc,
+         diag::err_type_constraint_non_type_concept);
+    return true;
+  }
+
+  bool WereArgsSpecified = TypeConstr->LAngleLoc.isValid();
+
+  if (!WereArgsSpecified &&
+      CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
+    Diag(TypeConstr->TemplateNameLoc,
+         diag::err_type_constraint_missing_arguments)
+        << CD;
+    return true;
+  }
+  return false;
+}
+
+bool SemaConcept::ActOnTypeConstraint(const CXXScopeSpec &SS,
+                               TemplateIdAnnotation *TypeConstr,
+                               TemplateTypeParmDecl *ConstrainedParameter,
+                               SourceLocation EllipsisLoc) {
+  return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
+                             false);
+}
+
+bool SemaConcept::BuildTypeConstraint(const CXXScopeSpec &SS,
+                               TemplateIdAnnotation *TypeConstr,
+                               TemplateTypeParmDecl *ConstrainedParameter,
+                               SourceLocation EllipsisLoc,
+                               bool AllowUnexpandedPack) {
+
+  if (CheckTypeConstraint(TypeConstr))
+    return true;
+
+  TemplateName TN = TypeConstr->Template.get();
+  ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
+  UsingShadowDecl *USD = TN.getAsUsingShadowDecl();
+
+  DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
+                                  TypeConstr->TemplateNameLoc);
+
+  TemplateArgumentListInfo TemplateArgs;
+  if (TypeConstr->LAngleLoc.isValid()) {
+    TemplateArgs =
+        SemaRef.makeTemplateArgumentListInfo(*TypeConstr);
+
+    if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
+      for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
+        if (SemaRef.DiagnoseUnexpandedParameterPack(Arg, Sema::UPPC_TypeConstraint))
+          return true;
+      }
+    }
+  }
+  return AttachTypeConstraint(
+      SS.isSet() ? SS.getWithLocInContext(SemaRef.Context) : NestedNameSpecifierLoc(),
+      ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD,
+      TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
+      ConstrainedParameter, EllipsisLoc);
+}
+
+template <typename ArgumentLocAppender>
+static ExprResult formImmediatelyDeclaredConstraint(
+    Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
+    ConceptDecl *NamedConcept, NamedDecl *FoundDecl, SourceLocation LAngleLoc,
+    SourceLocation RAngleLoc, QualType ConstrainedType,
+    SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
+    SourceLocation EllipsisLoc) {
+
+  TemplateArgumentListInfo ConstraintArgs;
+  ConstraintArgs.addArgument(
+    S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
+                                    /*NTTPType=*/QualType(), ParamNameLoc));
+
+  ConstraintArgs.setRAngleLoc(RAngleLoc);
+  ConstraintArgs.setLAngleLoc(LAngleLoc);
+  Appender(ConstraintArgs);
+
+  // C++2a [temp.param]p4:
+  //     [...] This constraint-expression E is called the immediately-declared
+  //     constraint of T. [...]
+  CXXScopeSpec SS;
+  SS.Adopt(NS);
+  ExprResult ImmediatelyDeclaredConstraint = S.Concept().CheckConceptTemplateId(
+      SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
+      /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, NamedConcept,
+      &ConstraintArgs);
+  if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid())
+    return ImmediatelyDeclaredConstraint;
+
+  // C++2a [temp.param]p4:
+  //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
+  //
+  // We have the following case:
+  //
+  // template<typename T> concept C1 = true;
+  // template<C1... T> struct s1;
+  //
+  // The constraint: (C1<T> && ...)
+  //
+  // Note that the type of C1<T> is known to be 'bool', so we don't need to do
+  // any unqualified lookups for 'operator&&' here.
+  return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr,
+                            /*LParenLoc=*/SourceLocation(),
+                            ImmediatelyDeclaredConstraint.get(), BO_LAnd,
+                            EllipsisLoc, /*RHS=*/nullptr,
+                            /*RParenLoc=*/SourceLocation(),
+                            /*NumExpansions=*/std::nullopt);
+}
+
+/// Attach a type-constraint to a template parameter.
+/// \returns true if an error occurred. This can happen if the
+/// immediately-declared constraint could not be formed (e.g. incorrect number
+/// of arguments for the named concept).
+bool SemaConcept::AttachTypeConstraint(NestedNameSpecifierLoc NS,
+                                DeclarationNameInfo NameInfo,
+                                ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
+                                const TemplateArgumentListInfo *TemplateArgs,
+                                TemplateTypeParmDecl *ConstrainedParameter,
+                                SourceLocation EllipsisLoc) {
+  // C++2a [temp.param]p4:
+  //     [...] If Q is of the form C<A1, ..., An>, then let E' be
+  //     C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
+  const ASTTemplateArgumentListInfo *ArgsAsWritten =
+    TemplateArgs ? ASTTemplateArgumentListInfo::Create(SemaRef.Context,
+                                                       *TemplateArgs) : nullptr;
+
+  QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
+
+  ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
+      SemaRef, NS, NameInfo, NamedConcept, FoundDecl,
+      TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
+      TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
+      ParamAsArgument, ConstrainedParameter->getLocation(),
+      [&](TemplateArgumentListInfo &ConstraintArgs) {
+        if (TemplateArgs)
+          for (const auto &ArgLoc : TemplateArgs->arguments())
+            ConstraintArgs.addArgument(ArgLoc);
+      },
+      EllipsisLoc);
+  if (ImmediatelyDeclaredConstraint.isInvalid())
+    return true;
+
+  auto *CL = ConceptReference::Create(SemaRef.Context, /*NNS=*/NS,
+                                      /*TemplateKWLoc=*/SourceLocation{},
+                                      /*ConceptNameInfo=*/NameInfo,
+                                      /*FoundDecl=*/FoundDecl,
+                                      /*NamedConcept=*/NamedConcept,
+                                      /*ArgsWritten=*/ArgsAsWritten);
+  ConstrainedParameter->setTypeConstraint(CL,
+                                          ImmediatelyDeclaredConstraint.get());
+  return false;
+}
+
+bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
+                                NonTypeTemplateParmDecl *NewConstrainedParm,
+                                NonTypeTemplateParmDecl *OrigConstrainedParm,
+                                SourceLocation EllipsisLoc) {
+  if (NewConstrainedParm->getType() != TL.getType() ||
+      TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
+    Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+         diag::err_unsupported_placeholder_constraint)
+        << NewConstrainedParm->getTypeSourceInfo()
+               ->getTypeLoc()
+               .getSourceRange();
+    return true;
+  }
+  // FIXME: Concepts: This should be the type of the placeholder, but this is
+  // unclear in the wording right now.
+  DeclRefExpr *Ref =
+      SemaRef.BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
+                       VK_PRValue, OrigConstrainedParm->getLocation());
+  if (!Ref)
+    return true;
+  ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
+      SemaRef, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
+      TL.getNamedConcept(), /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(),
+      TL.getRAngleLoc(), SemaRef.BuildDecltypeType(Ref),
+      OrigConstrainedParm->getLocation(),
+      [&](TemplateArgumentListInfo &ConstraintArgs) {
+        for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
+          ConstraintArgs.addArgument(TL.getArgLoc(I));
+      },
+      EllipsisLoc);
+  if (ImmediatelyDeclaredConstraint.isInvalid() ||
+      !ImmediatelyDeclaredConstraint.isUsable())
+    return true;
+
+  NewConstrainedParm->setPlaceholderTypeConstraint(
+      ImmediatelyDeclaredConstraint.get());
+  return false;
+}
+
+ExprResult
+SemaConcept::CheckConceptTemplateId(const CXXScopeSpec &SS,
+                             SourceLocation TemplateKWLoc,
+                             const DeclarationNameInfo &ConceptNameInfo,
+                             NamedDecl *FoundDecl,
+                             ConceptDecl *NamedConcept,
+                             const TemplateArgumentListInfo *TemplateArgs) {
+  assert(NamedConcept && "A concept template id without a template?");
+  ASTContext &Context = getASTContext();
+
+  llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+  if (SemaRef.CheckTemplateArgumentList(
+          NamedConcept, ConceptNameInfo.getLoc(),
+          const_cast<TemplateArgumentListInfo &>(*TemplateArgs),
+          /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted,
+          /*UpdateArgsWithConversions=*/false))
+    return ExprError();
+
+  SemaRef.DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc());
+
+  auto *CSD = ImplicitConceptSpecializationDecl::Create(
+      Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
+      CanonicalConverted);
+  ConstraintSatisfaction Satisfaction;
+  bool AreArgsDependent =
+      TemplateSpecializationType::anyDependentTemplateArguments(
+          *TemplateArgs, CanonicalConverted);
+  MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
+                                       /*Final=*/false);
+  LocalInstantiationScope Scope(SemaRef);
+
+  EnterExpressionEvaluationContext EECtx{
+      SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated, CSD};
+
+  if (!AreArgsDependent &&
+      CheckConstraintSatisfaction(
+          NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
+          SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
+                      TemplateArgs->getRAngleLoc()),
+          Satisfaction))
+    return ExprError();
+  auto *CL = ConceptReference::Create(
+      Context,
+      SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
+      TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
+      ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs));
+  return ConceptSpecializationExpr::Create(
+      Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction);
+}
+
+Decl *SemaConcept::ActOnConceptDefinition(
+    Scope *S, MultiTemplateParamsArg TemplateParameterLists,
+    const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr,
+    const ParsedAttributesView &Attrs) {
+  DeclContext *DC = SemaRef.CurContext;
+
+  if (!DC->getRedeclContext()->isFileContext()) {
+    Diag(NameLoc,
+      diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
+    return nullptr;
+  }
+
+  if (TemplateParameterLists.size() > 1) {
+    Diag(NameLoc, diag::err_concept_extra_headers);
+    return nullptr;
+  }
+
+  TemplateParameterList *Params = TemplateParameterLists.front();
+
+  if (Params->size() == 0) {
+    Diag(NameLoc, diag::err_concept_no_parameters);
+    return nullptr;
+  }
+
+  // Ensure that the parameter pack, if present, is the last parameter in the
+  // template.
+  for (TemplateParameterList::const_iterator ParamIt = Params->begin(),
+                                             ParamEnd = Params->end();
+       ParamIt != ParamEnd; ++ParamIt) {
+    Decl const *Param = *ParamIt;
+    if (Param->isParameterPack()) {
+      if (++ParamIt == ParamEnd)
+        break;
+      Diag(Param->getLocation(),
+           diag::err_template_param_pack_must_be_last_template_parameter);
+      return nullptr;
+    }
+  }
+
+  if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr))
+    return nullptr;
+
+  ConceptDecl *NewDecl =
+      ConceptDecl::Create(SemaRef.Context, DC, NameLoc, Name, Params, ConstraintExpr);
+
+  if (NewDecl->hasAssociatedConstraints()) {
+    // C++2a [temp.concept]p4:
+    // A concept shall not have associated constraints.
+    Diag(NameLoc, diag::err_concept_no_associated_constraints);
+    NewDecl->setInvalidDecl();
+  }
+
+  // Check for conflicting previous declaration.
+  DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc);
+  LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
+                        SemaRef.forRedeclarationInCurContext());
+  SemaRef.LookupName(Previous, S);
+  SemaRef.FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false,
+                       /*AllowInlineNamespace*/false);
+  bool AddToScope = true;
+  CheckConceptRedefinition(NewDecl, Previous, AddToScope);
+
+  SemaRef.ActOnDocumentableDecl(NewDecl);
+  if (AddToScope)
+    SemaRef.PushOnScopeChains(NewDecl, S);
+
+  SemaRef.ProcessDeclAttributeList(S, NewDecl, Attrs);
+
+  return NewDecl;
+}
+
+void SemaConcept::CheckConceptRedefinition(ConceptDecl *NewDecl,
+                                    LookupResult &Previous, bool &AddToScope) {
+  AddToScope = true;
+
+  if (Previous.empty())
+    return;
+
+  auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
+  if (!OldConcept) {
+    auto *Old = Previous.getRepresentativeDecl();
+    Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
+        << NewDecl->getDeclName();
+    SemaRef.notePreviousDefinition(Old, NewDecl->getLocation());
+    AddToScope = false;
+    return;
+  }
+  // Check if we can merge with a concept declaration.
+  bool IsSame = SemaRef.Context.isSameEntity(NewDecl, OldConcept);
+  if (!IsSame) {
+    Diag(NewDecl->getLocation(), diag::err_redefinition_different_concept)
+        << NewDecl->getDeclName();
+    SemaRef.notePreviousDefinition(OldConcept, NewDecl->getLocation());
+    AddToScope = false;
+    return;
+  }
+  if (SemaRef.hasReachableDefinition(OldConcept) &&
+      SemaRef.IsRedefinitionInModule(NewDecl, OldConcept)) {
+    Diag(NewDecl->getLocation(), diag::err_redefinition)
+        << NewDecl->getDeclName();
+    SemaRef.notePreviousDefinition(OldConcept, NewDecl->getLocation());
+    AddToScope = false;
+    return;
+  }
+  if (!Previous.isSingleResult()) {
+    // FIXME: we should produce an error in case of ambig and failed lookups.
+    //        Other decls (e.g. namespaces) also have this shortcoming.
+    return;
+  }
+  // We unwrap canonical decl late to check for module visibility.
+  SemaRef.Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl());
+}
+
+void SemaConcept::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
+  if (!D.isFunctionDeclarator())
+    return;
+  auto &FTI = D.getFunctionTypeInfo();
+  if (!FTI.Params)
+    return;
+  for (auto &Param : ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params,
+                                                          FTI.NumParams)) {
+    auto *ParamDecl = cast<NamedDecl>(Param.Param);
+    if (ParamDecl->getDeclName())
+      SemaRef.PushOnScopeChains(ParamDecl, S, /*AddToContext=*/false);
+  }
+}
+
+ExprResult SemaConcept::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
+  return ActOnRequiresClause(ConstraintExpr);
+}
+
+ExprResult SemaConcept::ActOnRequiresClause(ExprResult ConstraintExpr) {
+  if (ConstraintExpr.isInvalid())
+    return ExprError();
+
+  ConstraintExpr = SemaRef.CorrectDelayedTyposInExpr(ConstraintExpr);
+  if (ConstraintExpr.isInvalid())
+    return ExprError();
+
+  if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
+                                      Sema::UPPC_RequiresClause))
+    return ExprError();
+
+  return ConstraintExpr;
+}
+
+void SemaConcept::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
+  if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
+    SemaRef.DiagnoseUseOfDecl(Decl, Loc);
+  }
+}
+
+FunctionDecl *SemaConcept::getMoreConstrainedFunction(FunctionDecl *FD1,
+                                               FunctionDecl *FD2) {
+  assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
+         "not for function templates");
+  FunctionDecl *F1 = FD1;
+  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+    F1 = MF;
+  FunctionDecl *F2 = FD2;
+  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+    F2 = MF;
+  llvm::SmallVector<const Expr *, 1> AC1, AC2;
+  F1->getAssociatedConstraints(AC1);
+  F2->getAssociatedConstraints(AC2);
+  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+  if (IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
+    return nullptr;
+  if (IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
+    return nullptr;
+  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+    return nullptr;
+  return AtLeastAsConstrained1 ? FD1 : FD2;
+}
+
 clang::SemaConcept::SemaConcept(Sema &S) : SemaBase(S), SatisfactionCache(S.Context) {}
 
 clang::SemaConcept::~SemaConcept() {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 50715866b357d..1aeb6b87b680a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7575,7 +7575,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
                                     /*DiagID=*/0);
 
   if (const AutoType *AutoT = R->getAs<AutoType>())
-    CheckConstrainedAuto(
+    SemaRef.Concept().CheckConstrainedAuto(
         AutoT,
         TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc());
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a087b8592bdb0..8d99f970118b4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4195,39 +4195,6 @@ void Sema::ActOnStartCXXInClassMemberInitializer() {
   PushFunctionScope();
 }
 
-void Sema::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
-  if (!D.isFunctionDeclarator())
-    return;
-  auto &FTI = D.getFunctionTypeInfo();
-  if (!FTI.Params)
-    return;
-  for (auto &Param : ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params,
-                                                          FTI.NumParams)) {
-    auto *ParamDecl = cast<NamedDecl>(Param.Param);
-    if (ParamDecl->getDeclName())
-      PushOnScopeChains(ParamDecl, S, /*AddToContext=*/false);
-  }
-}
-
-ExprResult Sema::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
-  return ActOnRequiresClause(ConstraintExpr);
-}
-
-ExprResult Sema::ActOnRequiresClause(ExprResult ConstraintExpr) {
-  if (ConstraintExpr.isInvalid())
-    return ExprError();
-
-  ConstraintExpr = CorrectDelayedTyposInExpr(ConstraintExpr);
-  if (ConstraintExpr.isInvalid())
-    return ExprError();
-
-  if (DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
-                                      UPPC_RequiresClause))
-    return ExprError();
-
-  return ConstraintExpr;
-}
-
 ExprResult Sema::ConvertMemberDefaultInitExpression(FieldDecl *FD,
                                                     Expr *InitExpr,
                                                     SourceLocation InitLoc) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index b75ff7f011ae8..b926383dccc4a 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -9226,230 +9226,3 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
 
   return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
 }
-
-concepts::Requirement *Sema::ActOnSimpleRequirement(Expr *E) {
-  return BuildExprRequirement(E, /*IsSimple=*/true,
-                              /*NoexceptLoc=*/SourceLocation(),
-                              /*ReturnTypeRequirement=*/{});
-}
-
-concepts::Requirement *Sema::ActOnTypeRequirement(
-    SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc,
-    const IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId) {
-  assert(((!TypeName && TemplateId) || (TypeName && !TemplateId)) &&
-         "Exactly one of TypeName and TemplateId must be specified.");
-  TypeSourceInfo *TSI = nullptr;
-  if (TypeName) {
-    QualType T =
-        CheckTypenameType(ElaboratedTypeKeyword::Typename, TypenameKWLoc,
-                          SS.getWithLocInContext(Context), *TypeName, NameLoc,
-                          &TSI, /*DeducedTSTContext=*/false);
-    if (T.isNull())
-      return nullptr;
-  } else {
-    ASTTemplateArgsPtr ArgsPtr(TemplateId->getTemplateArgs(),
-                               TemplateId->NumArgs);
-    TypeResult T = ActOnTypenameType(CurScope, TypenameKWLoc, SS,
-                                     TemplateId->TemplateKWLoc,
-                                     TemplateId->Template, TemplateId->Name,
-                                     TemplateId->TemplateNameLoc,
-                                     TemplateId->LAngleLoc, ArgsPtr,
-                                     TemplateId->RAngleLoc);
-    if (T.isInvalid())
-      return nullptr;
-    if (GetTypeFromParser(T.get(), &TSI).isNull())
-      return nullptr;
-  }
-  return BuildTypeRequirement(TSI);
-}
-
-concepts::Requirement *
-Sema::ActOnCompoundRequirement(Expr *E, SourceLocation NoexceptLoc) {
-  return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc,
-                              /*ReturnTypeRequirement=*/{});
-}
-
-concepts::Requirement *
-Sema::ActOnCompoundRequirement(
-    Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
-    TemplateIdAnnotation *TypeConstraint, unsigned Depth) {
-  // C++2a [expr.prim.req.compound] p1.3.3
-  //   [..] the expression is deduced against an invented function template
-  //   F [...] F is a void function template with a single type template
-  //   parameter T declared with the constrained-parameter. Form a new
-  //   cv-qualifier-seq cv by taking the union of const and volatile specifiers
-  //   around the constrained-parameter. F has a single parameter whose
-  //   type-specifier is cv T followed by the abstract-declarator. [...]
-  //
-  // The cv part is done in the calling function - we get the concept with
-  // arguments and the abstract declarator with the correct CV qualification and
-  // have to synthesize T and the single parameter of F.
-  auto &II = Context.Idents.get("expr-type");
-  auto *TParam = TemplateTypeParmDecl::Create(Context, CurContext,
-                                              SourceLocation(),
-                                              SourceLocation(), Depth,
-                                              /*Index=*/0, &II,
-                                              /*Typename=*/true,
-                                              /*ParameterPack=*/false,
-                                              /*HasTypeConstraint=*/true);
-
-  if (BuildTypeConstraint(SS, TypeConstraint, TParam,
-                          /*EllipsisLoc=*/SourceLocation(),
-                          /*AllowUnexpandedPack=*/true))
-    // Just produce a requirement with no type requirements.
-    return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {});
-
-  auto *TPL = TemplateParameterList::Create(Context, SourceLocation(),
-                                            SourceLocation(),
-                                            ArrayRef<NamedDecl *>(TParam),
-                                            SourceLocation(),
-                                            /*RequiresClause=*/nullptr);
-  return BuildExprRequirement(
-      E, /*IsSimple=*/false, NoexceptLoc,
-      concepts::ExprRequirement::ReturnTypeRequirement(TPL));
-}
-
-concepts::ExprRequirement *
-Sema::BuildExprRequirement(
-    Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
-    concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
-  auto Status = concepts::ExprRequirement::SS_Satisfied;
-  ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
-  if (E->isInstantiationDependent() || E->getType()->isPlaceholderType() ||
-      ReturnTypeRequirement.isDependent())
-    Status = concepts::ExprRequirement::SS_Dependent;
-  else if (NoexceptLoc.isValid() && canThrow(E) == CanThrowResult::CT_Can)
-    Status = concepts::ExprRequirement::SS_NoexceptNotMet;
-  else if (ReturnTypeRequirement.isSubstitutionFailure())
-    Status = concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure;
-  else if (ReturnTypeRequirement.isTypeConstraint()) {
-    // C++2a [expr.prim.req]p1.3.3
-    //     The immediately-declared constraint ([temp]) of decltype((E)) shall
-    //     be satisfied.
-    TemplateParameterList *TPL =
-        ReturnTypeRequirement.getTypeConstraintTemplateParameterList();
-    QualType MatchedType =
-        Context.getReferenceQualifiedType(E).getCanonicalType();
-    llvm::SmallVector<TemplateArgument, 1> Args;
-    Args.push_back(TemplateArgument(MatchedType));
-
-    auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
-
-    MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false);
-    MLTAL.addOuterRetainedLevels(TPL->getDepth());
-    const TypeConstraint *TC = Param->getTypeConstraint();
-    assert(TC && "Type Constraint cannot be null here");
-    auto *IDC = TC->getImmediatelyDeclaredConstraint();
-    assert(IDC && "ImmediatelyDeclaredConstraint can't be null here.");
-    ExprResult Constraint = SubstExpr(IDC, MLTAL);
-    if (Constraint.isInvalid()) {
-      return new (Context) concepts::ExprRequirement(
-          concepts::createSubstDiagAt(*this, IDC->getExprLoc(),
-                                      [&](llvm::raw_ostream &OS) {
-                                        IDC->printPretty(OS, /*Helper=*/nullptr,
-                                                         getPrintingPolicy());
-                                      }),
-          IsSimple, NoexceptLoc, ReturnTypeRequirement);
-    }
-    SubstitutedConstraintExpr =
-        cast<ConceptSpecializationExpr>(Constraint.get());
-    if (!SubstitutedConstraintExpr->isSatisfied())
-      Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
-  }
-  return new (Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
-                                                 ReturnTypeRequirement, Status,
-                                                 SubstitutedConstraintExpr);
-}
-
-concepts::ExprRequirement *
-Sema::BuildExprRequirement(
-    concepts::Requirement::SubstitutionDiagnostic *ExprSubstitutionDiagnostic,
-    bool IsSimple, SourceLocation NoexceptLoc,
-    concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
-  return new (Context) concepts::ExprRequirement(ExprSubstitutionDiagnostic,
-                                                 IsSimple, NoexceptLoc,
-                                                 ReturnTypeRequirement);
-}
-
-concepts::TypeRequirement *
-Sema::BuildTypeRequirement(TypeSourceInfo *Type) {
-  return new (Context) concepts::TypeRequirement(Type);
-}
-
-concepts::TypeRequirement *
-Sema::BuildTypeRequirement(
-    concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
-  return new (Context) concepts::TypeRequirement(SubstDiag);
-}
-
-concepts::Requirement *Sema::ActOnNestedRequirement(Expr *Constraint) {
-  return BuildNestedRequirement(Constraint);
-}
-
-concepts::NestedRequirement *
-Sema::BuildNestedRequirement(Expr *Constraint) {
-  ConstraintSatisfaction Satisfaction;
-  if (!Constraint->isInstantiationDependent() &&
-      Concept().CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
-                                  Constraint->getSourceRange(), Satisfaction))
-    return nullptr;
-  return new (Context) concepts::NestedRequirement(Context, Constraint,
-                                                   Satisfaction);
-}
-
-concepts::NestedRequirement *
-Sema::BuildNestedRequirement(StringRef InvalidConstraintEntity,
-                       const ASTConstraintSatisfaction &Satisfaction) {
-  return new (Context) concepts::NestedRequirement(
-      InvalidConstraintEntity,
-      ASTConstraintSatisfaction::Rebuild(Context, Satisfaction));
-}
-
-RequiresExprBodyDecl *
-Sema::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
-                             ArrayRef<ParmVarDecl *> LocalParameters,
-                             Scope *BodyScope) {
-  assert(BodyScope);
-
-  RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(Context, CurContext,
-                                                            RequiresKWLoc);
-
-  PushDeclContext(BodyScope, Body);
-
-  for (ParmVarDecl *Param : LocalParameters) {
-    if (Param->hasDefaultArg())
-      // C++2a [expr.prim.req] p4
-      //     [...] A local parameter of a requires-expression shall not have a
-      //     default argument. [...]
-      Diag(Param->getDefaultArgRange().getBegin(),
-           diag::err_requires_expr_local_parameter_default_argument);
-    // Ignore default argument and move on
-
-    Param->setDeclContext(Body);
-    // If this has an identifier, add it to the scope stack.
-    if (Param->getIdentifier()) {
-      CheckShadow(BodyScope, Param);
-      PushOnScopeChains(Param, BodyScope);
-    }
-  }
-  return Body;
-}
-
-void Sema::ActOnFinishRequiresExpr() {
-  assert(CurContext && "DeclContext imbalance!");
-  CurContext = CurContext->getLexicalParent();
-  assert(CurContext && "Popped translation unit!");
-}
-
-ExprResult Sema::ActOnRequiresExpr(
-    SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
-    SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
-    SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
-    SourceLocation ClosingBraceLoc) {
-  auto *RE = RequiresExpr::Create(Context, RequiresKWLoc, Body, LParenLoc,
-                                  LocalParameters, RParenLoc, Requirements,
-                                  ClosingBraceLoc);
-  if (DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
-    return ExprError();
-  return RE;
-}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4dc433cc0b6c7..f138db5467030 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -10636,7 +10636,7 @@ bool clang::isBetterOverloadCandidate(
   //      parameter-type-lists, and F1 is more constrained than F2 [...],
   if (!Cand1IsSpecialization && !Cand2IsSpecialization &&
       sameFunctionParameterTypeLists(S, Cand1, Cand2) &&
-      S.getMoreConstrainedFunction(Cand1.Function, Cand2.Function) ==
+      S.Concept().getMoreConstrainedFunction(Cand1.Function, Cand2.Function) ==
           Cand1.Function)
     return true;
 
@@ -13342,7 +13342,7 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
       }
       // FD has the same CUDA prefernece than Result. Continue check
       // constraints.
-      FunctionDecl *MoreConstrained = getMoreConstrainedFunction(FD, Result);
+      FunctionDecl *MoreConstrained = Concept().getMoreConstrainedFunction(FD, Result);
       if (MoreConstrained != FD) {
         if (!MoreConstrained) {
           IsResultAmbiguous = true;
@@ -13368,7 +13368,7 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
       // constraints.
       if (getLangOpts().CUDA && CheckCUDAPreference(Skipped, Result) != 0)
         continue;
-      if (!getMoreConstrainedFunction(Skipped, Result))
+      if (!Concept().getMoreConstrainedFunction(Skipped, Result))
         return nullptr;
     }
     Pair = DAP;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 57ab161549450..73abb59857a97 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1099,217 +1099,16 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
 }
 
 /// Convert the parser's template argument list representation into our form.
-static TemplateArgumentListInfo
-makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
+TemplateArgumentListInfo
+Sema::makeTemplateArgumentListInfo(TemplateIdAnnotation &TemplateId) {
   TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
                                         TemplateId.RAngleLoc);
   ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
                                      TemplateId.NumArgs);
-  S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+  translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
   return TemplateArgs;
 }
 
-bool Sema::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
-
-  TemplateName TN = TypeConstr->Template.get();
-  ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
-
-  // C++2a [temp.param]p4:
-  //     [...] The concept designated by a type-constraint shall be a type
-  //     concept ([temp.concept]).
-  if (!CD->isTypeConcept()) {
-    Diag(TypeConstr->TemplateNameLoc,
-         diag::err_type_constraint_non_type_concept);
-    return true;
-  }
-
-  bool WereArgsSpecified = TypeConstr->LAngleLoc.isValid();
-
-  if (!WereArgsSpecified &&
-      CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
-    Diag(TypeConstr->TemplateNameLoc,
-         diag::err_type_constraint_missing_arguments)
-        << CD;
-    return true;
-  }
-  return false;
-}
-
-bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS,
-                               TemplateIdAnnotation *TypeConstr,
-                               TemplateTypeParmDecl *ConstrainedParameter,
-                               SourceLocation EllipsisLoc) {
-  return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
-                             false);
-}
-
-bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
-                               TemplateIdAnnotation *TypeConstr,
-                               TemplateTypeParmDecl *ConstrainedParameter,
-                               SourceLocation EllipsisLoc,
-                               bool AllowUnexpandedPack) {
-
-  if (CheckTypeConstraint(TypeConstr))
-    return true;
-
-  TemplateName TN = TypeConstr->Template.get();
-  ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
-  UsingShadowDecl *USD = TN.getAsUsingShadowDecl();
-
-  DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
-                                  TypeConstr->TemplateNameLoc);
-
-  TemplateArgumentListInfo TemplateArgs;
-  if (TypeConstr->LAngleLoc.isValid()) {
-    TemplateArgs =
-        makeTemplateArgumentListInfo(*this, *TypeConstr);
-
-    if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
-      for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
-        if (DiagnoseUnexpandedParameterPack(Arg, UPPC_TypeConstraint))
-          return true;
-      }
-    }
-  }
-  return AttachTypeConstraint(
-      SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc(),
-      ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD,
-      TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
-      ConstrainedParameter, EllipsisLoc);
-}
-
-template <typename ArgumentLocAppender>
-static ExprResult formImmediatelyDeclaredConstraint(
-    Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
-    ConceptDecl *NamedConcept, NamedDecl *FoundDecl, SourceLocation LAngleLoc,
-    SourceLocation RAngleLoc, QualType ConstrainedType,
-    SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
-    SourceLocation EllipsisLoc) {
-
-  TemplateArgumentListInfo ConstraintArgs;
-  ConstraintArgs.addArgument(
-    S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
-                                    /*NTTPType=*/QualType(), ParamNameLoc));
-
-  ConstraintArgs.setRAngleLoc(RAngleLoc);
-  ConstraintArgs.setLAngleLoc(LAngleLoc);
-  Appender(ConstraintArgs);
-
-  // C++2a [temp.param]p4:
-  //     [...] This constraint-expression E is called the immediately-declared
-  //     constraint of T. [...]
-  CXXScopeSpec SS;
-  SS.Adopt(NS);
-  ExprResult ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId(
-      SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
-      /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, NamedConcept,
-      &ConstraintArgs);
-  if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid())
-    return ImmediatelyDeclaredConstraint;
-
-  // C++2a [temp.param]p4:
-  //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
-  //
-  // We have the following case:
-  //
-  // template<typename T> concept C1 = true;
-  // template<C1... T> struct s1;
-  //
-  // The constraint: (C1<T> && ...)
-  //
-  // Note that the type of C1<T> is known to be 'bool', so we don't need to do
-  // any unqualified lookups for 'operator&&' here.
-  return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr,
-                            /*LParenLoc=*/SourceLocation(),
-                            ImmediatelyDeclaredConstraint.get(), BO_LAnd,
-                            EllipsisLoc, /*RHS=*/nullptr,
-                            /*RParenLoc=*/SourceLocation(),
-                            /*NumExpansions=*/std::nullopt);
-}
-
-/// Attach a type-constraint to a template parameter.
-/// \returns true if an error occurred. This can happen if the
-/// immediately-declared constraint could not be formed (e.g. incorrect number
-/// of arguments for the named concept).
-bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
-                                DeclarationNameInfo NameInfo,
-                                ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
-                                const TemplateArgumentListInfo *TemplateArgs,
-                                TemplateTypeParmDecl *ConstrainedParameter,
-                                SourceLocation EllipsisLoc) {
-  // C++2a [temp.param]p4:
-  //     [...] If Q is of the form C<A1, ..., An>, then let E' be
-  //     C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
-  const ASTTemplateArgumentListInfo *ArgsAsWritten =
-    TemplateArgs ? ASTTemplateArgumentListInfo::Create(Context,
-                                                       *TemplateArgs) : nullptr;
-
-  QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
-
-  ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
-      *this, NS, NameInfo, NamedConcept, FoundDecl,
-      TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
-      TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
-      ParamAsArgument, ConstrainedParameter->getLocation(),
-      [&](TemplateArgumentListInfo &ConstraintArgs) {
-        if (TemplateArgs)
-          for (const auto &ArgLoc : TemplateArgs->arguments())
-            ConstraintArgs.addArgument(ArgLoc);
-      },
-      EllipsisLoc);
-  if (ImmediatelyDeclaredConstraint.isInvalid())
-    return true;
-
-  auto *CL = ConceptReference::Create(Context, /*NNS=*/NS,
-                                      /*TemplateKWLoc=*/SourceLocation{},
-                                      /*ConceptNameInfo=*/NameInfo,
-                                      /*FoundDecl=*/FoundDecl,
-                                      /*NamedConcept=*/NamedConcept,
-                                      /*ArgsWritten=*/ArgsAsWritten);
-  ConstrainedParameter->setTypeConstraint(CL,
-                                          ImmediatelyDeclaredConstraint.get());
-  return false;
-}
-
-bool Sema::AttachTypeConstraint(AutoTypeLoc TL,
-                                NonTypeTemplateParmDecl *NewConstrainedParm,
-                                NonTypeTemplateParmDecl *OrigConstrainedParm,
-                                SourceLocation EllipsisLoc) {
-  if (NewConstrainedParm->getType() != TL.getType() ||
-      TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
-    Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
-         diag::err_unsupported_placeholder_constraint)
-        << NewConstrainedParm->getTypeSourceInfo()
-               ->getTypeLoc()
-               .getSourceRange();
-    return true;
-  }
-  // FIXME: Concepts: This should be the type of the placeholder, but this is
-  // unclear in the wording right now.
-  DeclRefExpr *Ref =
-      BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
-                       VK_PRValue, OrigConstrainedParm->getLocation());
-  if (!Ref)
-    return true;
-  ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
-      *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
-      TL.getNamedConcept(), /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(),
-      TL.getRAngleLoc(), BuildDecltypeType(Ref),
-      OrigConstrainedParm->getLocation(),
-      [&](TemplateArgumentListInfo &ConstraintArgs) {
-        for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
-          ConstraintArgs.addArgument(TL.getArgLoc(I));
-      },
-      EllipsisLoc);
-  if (ImmediatelyDeclaredConstraint.isInvalid() ||
-      !ImmediatelyDeclaredConstraint.isUsable())
-    return true;
-
-  NewConstrainedParm->setPlaceholderTypeConstraint(
-      ImmediatelyDeclaredConstraint.get());
-  return false;
-}
-
 /// Check that the type of a non-type template parameter is
 /// well-formed.
 ///
@@ -1586,7 +1385,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
 
   if (AutoTypeLoc TL = TInfo->getTypeLoc().getContainedAutoTypeLoc())
     if (TL.isConstrained())
-      if (AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc()))
+      if (Concept().AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc()))
         Invalid = true;
 
   if (Invalid)
@@ -5262,7 +5061,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
 
   TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
   TemplateArgumentListInfo TemplateArgs =
-      makeTemplateArgumentListInfo(*this, *TemplateId);
+      makeTemplateArgumentListInfo(*TemplateId);
   SourceLocation TemplateNameLoc = D.getIdentifierLoc();
   SourceLocation LAngleLoc = TemplateId->LAngleLoc;
   SourceLocation RAngleLoc = TemplateId->RAngleLoc;
@@ -5637,55 +5436,6 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
   }
 }
 
-ExprResult
-Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
-                             SourceLocation TemplateKWLoc,
-                             const DeclarationNameInfo &ConceptNameInfo,
-                             NamedDecl *FoundDecl,
-                             ConceptDecl *NamedConcept,
-                             const TemplateArgumentListInfo *TemplateArgs) {
-  assert(NamedConcept && "A concept template id without a template?");
-
-  llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
-  if (CheckTemplateArgumentList(
-          NamedConcept, ConceptNameInfo.getLoc(),
-          const_cast<TemplateArgumentListInfo &>(*TemplateArgs),
-          /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted,
-          /*UpdateArgsWithConversions=*/false))
-    return ExprError();
-
-  DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc());
-
-  auto *CSD = ImplicitConceptSpecializationDecl::Create(
-      Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
-      CanonicalConverted);
-  ConstraintSatisfaction Satisfaction;
-  bool AreArgsDependent =
-      TemplateSpecializationType::anyDependentTemplateArguments(
-          *TemplateArgs, CanonicalConverted);
-  MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
-                                       /*Final=*/false);
-  LocalInstantiationScope Scope(*this);
-
-  EnterExpressionEvaluationContext EECtx{
-      *this, ExpressionEvaluationContext::ConstantEvaluated, CSD};
-
-  if (!AreArgsDependent &&
-      Concept().CheckConstraintSatisfaction(
-          NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
-          SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
-                      TemplateArgs->getRAngleLoc()),
-          Satisfaction))
-    return ExprError();
-  auto *CL = ConceptReference::Create(
-      Context,
-      SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
-      TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
-      ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs));
-  return ConceptSpecializationExpr::Create(
-      Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction);
-}
-
 ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
                                      SourceLocation TemplateKWLoc,
                                      LookupResult &R,
@@ -5724,7 +5474,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
   }
 
   if (R.getAsSingle<ConceptDecl>()) {
-    return CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(),
+    return Concept().CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(),
                                   R.getRepresentativeDecl(),
                                   R.getAsSingle<ConceptDecl>(), TemplateArgs);
   }
@@ -9602,7 +9352,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
 
   // Translate the parser's template argument list in our AST format.
   TemplateArgumentListInfo TemplateArgs =
-      makeTemplateArgumentListInfo(*this, TemplateId);
+      makeTemplateArgumentListInfo(TemplateId);
 
   // Check for unexpanded parameter packs in any of the template arguments.
   for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -9860,119 +9610,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
   return NewDecl;
 }
 
-Decl *Sema::ActOnConceptDefinition(
-    Scope *S, MultiTemplateParamsArg TemplateParameterLists,
-    const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr,
-    const ParsedAttributesView &Attrs) {
-  DeclContext *DC = CurContext;
-
-  if (!DC->getRedeclContext()->isFileContext()) {
-    Diag(NameLoc,
-      diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
-    return nullptr;
-  }
-
-  if (TemplateParameterLists.size() > 1) {
-    Diag(NameLoc, diag::err_concept_extra_headers);
-    return nullptr;
-  }
-
-  TemplateParameterList *Params = TemplateParameterLists.front();
-
-  if (Params->size() == 0) {
-    Diag(NameLoc, diag::err_concept_no_parameters);
-    return nullptr;
-  }
-
-  // Ensure that the parameter pack, if present, is the last parameter in the
-  // template.
-  for (TemplateParameterList::const_iterator ParamIt = Params->begin(),
-                                             ParamEnd = Params->end();
-       ParamIt != ParamEnd; ++ParamIt) {
-    Decl const *Param = *ParamIt;
-    if (Param->isParameterPack()) {
-      if (++ParamIt == ParamEnd)
-        break;
-      Diag(Param->getLocation(),
-           diag::err_template_param_pack_must_be_last_template_parameter);
-      return nullptr;
-    }
-  }
-
-  if (DiagnoseUnexpandedParameterPack(ConstraintExpr))
-    return nullptr;
-
-  ConceptDecl *NewDecl =
-      ConceptDecl::Create(Context, DC, NameLoc, Name, Params, ConstraintExpr);
-
-  if (NewDecl->hasAssociatedConstraints()) {
-    // C++2a [temp.concept]p4:
-    // A concept shall not have associated constraints.
-    Diag(NameLoc, diag::err_concept_no_associated_constraints);
-    NewDecl->setInvalidDecl();
-  }
-
-  // Check for conflicting previous declaration.
-  DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc);
-  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
-                        forRedeclarationInCurContext());
-  LookupName(Previous, S);
-  FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false,
-                       /*AllowInlineNamespace*/false);
-  bool AddToScope = true;
-  CheckConceptRedefinition(NewDecl, Previous, AddToScope);
-
-  ActOnDocumentableDecl(NewDecl);
-  if (AddToScope)
-    PushOnScopeChains(NewDecl, S);
-
-  ProcessDeclAttributeList(S, NewDecl, Attrs);
-
-  return NewDecl;
-}
-
-void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl,
-                                    LookupResult &Previous, bool &AddToScope) {
-  AddToScope = true;
-
-  if (Previous.empty())
-    return;
-
-  auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
-  if (!OldConcept) {
-    auto *Old = Previous.getRepresentativeDecl();
-    Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
-        << NewDecl->getDeclName();
-    notePreviousDefinition(Old, NewDecl->getLocation());
-    AddToScope = false;
-    return;
-  }
-  // Check if we can merge with a concept declaration.
-  bool IsSame = Context.isSameEntity(NewDecl, OldConcept);
-  if (!IsSame) {
-    Diag(NewDecl->getLocation(), diag::err_redefinition_different_concept)
-        << NewDecl->getDeclName();
-    notePreviousDefinition(OldConcept, NewDecl->getLocation());
-    AddToScope = false;
-    return;
-  }
-  if (hasReachableDefinition(OldConcept) &&
-      IsRedefinitionInModule(NewDecl, OldConcept)) {
-    Diag(NewDecl->getLocation(), diag::err_redefinition)
-        << NewDecl->getDeclName();
-    notePreviousDefinition(OldConcept, NewDecl->getLocation());
-    AddToScope = false;
-    return;
-  }
-  if (!Previous.isSingleResult()) {
-    // FIXME: we should produce an error in case of ambig and failed lookups.
-    //        Other decls (e.g. namespaces) also have this shortcoming.
-    return;
-  }
-  // We unwrap canonical decl late to check for module visibility.
-  Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl());
-}
-
 /// \brief Strips various properties off an implicit instantiation
 /// that has just been explicitly specialized.
 static void StripImplicitInstantiation(NamedDecl *D, bool MinGW) {
@@ -10574,7 +10211,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
         continue;
       Candidates.push_back(Method);
       FunctionDecl *MoreConstrained =
-          Instantiation ? getMoreConstrainedFunction(
+          Instantiation ? Concept().getMoreConstrainedFunction(
                               Method, cast<FunctionDecl>(Instantiation))
                         : Method;
       if (!MoreConstrained) {
@@ -11438,7 +11075,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
 
       // Translate the parser's template argument list into our AST format.
       TemplateArgumentListInfo TemplateArgs =
-          makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
+          makeTemplateArgumentListInfo(*D.getName().TemplateId);
 
       DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
                                           D.getIdentifierLoc(), TemplateArgs);
@@ -11519,7 +11156,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
   bool HasExplicitTemplateArgs = false;
   TemplateArgumentListInfo TemplateArgs;
   if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
-    TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
+    TemplateArgs = makeTemplateArgumentListInfo(*D.getName().TemplateId);
     HasExplicitTemplateArgs = true;
   }
 
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 26c0f8472dde1..25a36706b8039 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5974,38 +5974,6 @@ UnresolvedSetIterator Sema::getMostSpecialized(
   return SpecEnd;
 }
 
-/// Returns the more constrained function according to the rules of
-/// partial ordering by constraints (C++ [temp.constr.order]).
-///
-/// \param FD1 the first function
-///
-/// \param FD2 the second function
-///
-/// \returns the more constrained function. If neither function is
-/// more constrained, returns NULL.
-FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1,
-                                               FunctionDecl *FD2) {
-  assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
-         "not for function templates");
-  FunctionDecl *F1 = FD1;
-  if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
-    F1 = MF;
-  FunctionDecl *F2 = FD2;
-  if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
-    F2 = MF;
-  llvm::SmallVector<const Expr *, 1> AC1, AC2;
-  F1->getAssociatedConstraints(AC1);
-  F2->getAssociatedConstraints(AC2);
-  bool AtLeastAsConstrained1, AtLeastAsConstrained2;
-  if (Concept().IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
-    return nullptr;
-  if (Concept().IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
-    return nullptr;
-  if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
-    return nullptr;
-  return AtLeastAsConstrained1 ? FD1 : FD2;
-}
-
 /// Determine whether one partial specialization, P1, is at least as
 /// specialized than another, P2.
 ///
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 537982d94570e..c2b6d151cdf45 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3131,7 +3131,7 @@ bool Sema::SubstTypeConstraint(
                                InstArgs))
       return true;
   }
-  return AttachTypeConstraint(
+  return Concept().AttachTypeConstraint(
       TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
       TC->getNamedConcept(),
       /*FoundDecl=*/TC->getConceptReference()->getFoundDecl(), &InstArgs, Inst,
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 381d79b2fcd46..729f7442cbe06 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -27,6 +27,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -3111,7 +3112,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
       // Note: We attach the uninstantiated constriant here, so that it can be
       // instantiated relative to the top level, like all our other
       // constraints.
-      if (SemaRef.AttachTypeConstraint(AutoLoc, /*NewConstrainedParm=*/Param,
+      if (SemaRef.Concept().AttachTypeConstraint(AutoLoc, /*NewConstrainedParm=*/Param,
                                        /*OrigConstrainedParm=*/D, EllipsisLoc))
         Invalid = true;
     }
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index ef0b6b701a52c..f9f0ee6d99c9a 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -34,6 +34,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -3089,7 +3090,7 @@ InventTemplateParameter(TypeProcessingState &state, QualType T,
       }
 
       if (!Invalid) {
-        S.AttachTypeConstraint(
+        S.Concept().AttachTypeConstraint(
             AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(),
             AutoLoc.getNamedConcept(), /*FoundDecl=*/AutoLoc.getFoundDecl(),
             AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr,
@@ -3122,7 +3123,7 @@ InventTemplateParameter(TypeProcessingState &state, QualType T,
             TemplateId->Template.get().getAsUsingShadowDecl();
         auto *CD =
             cast<ConceptDecl>(TemplateId->Template.get().getAsTemplateDecl());
-        S.AttachTypeConstraint(
+        S.Concept().AttachTypeConstraint(
             D.getDeclSpec().getTypeSpecScope().getWithLocInContext(S.Context),
             DeclarationNameInfo(DeclarationName(TemplateId->Name),
                                 TemplateId->TemplateNameLoc),
@@ -6393,7 +6394,7 @@ TypeResult Sema::ActOnTypeName(Declarator &D) {
   }
 
   if (const AutoType *AutoT = T->getAs<AutoType>())
-    CheckConstrainedAuto(
+    SemaRef.Concept().CheckConstrainedAuto(
         AutoT,
         TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc());
 
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 29444f0edc2ae..0172b49ced0cf 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -37,6 +37,7 @@
 #include "clang/Sema/Ownership.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
@@ -3662,7 +3663,7 @@ class TreeTransform {
       TemplateArgumentListInfo *TALI) {
     CXXScopeSpec SS;
     SS.Adopt(NNS);
-    ExprResult Result = getSema().CheckConceptTemplateId(SS, TemplateKWLoc,
+    ExprResult Result = getSema().Concept().CheckConceptTemplateId(SS, TemplateKWLoc,
                                                          ConceptNameInfo,
                                                          FoundDecl,
                                                          NamedConcept, TALI);
@@ -3690,11 +3691,11 @@ class TreeTransform {
   concepts::TypeRequirement *
   RebuildTypeRequirement(
       concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
-    return SemaRef.BuildTypeRequirement(SubstDiag);
+    return SemaRef.Concept().BuildTypeRequirement(SubstDiag);
   }
 
   concepts::TypeRequirement *RebuildTypeRequirement(TypeSourceInfo *T) {
-    return SemaRef.BuildTypeRequirement(T);
+    return SemaRef.Concept().BuildTypeRequirement(T);
   }
 
   concepts::ExprRequirement *
@@ -3702,26 +3703,26 @@ class TreeTransform {
       concepts::Requirement::SubstitutionDiagnostic *SubstDiag, bool IsSimple,
       SourceLocation NoexceptLoc,
       concepts::ExprRequirement::ReturnTypeRequirement Ret) {
-    return SemaRef.BuildExprRequirement(SubstDiag, IsSimple, NoexceptLoc,
+    return SemaRef.Concept().BuildExprRequirement(SubstDiag, IsSimple, NoexceptLoc,
                                         std::move(Ret));
   }
 
   concepts::ExprRequirement *
   RebuildExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
                          concepts::ExprRequirement::ReturnTypeRequirement Ret) {
-    return SemaRef.BuildExprRequirement(E, IsSimple, NoexceptLoc,
+    return SemaRef.Concept().BuildExprRequirement(E, IsSimple, NoexceptLoc,
                                         std::move(Ret));
   }
 
   concepts::NestedRequirement *
   RebuildNestedRequirement(StringRef InvalidConstraintEntity,
                            const ASTConstraintSatisfaction &Satisfaction) {
-    return SemaRef.BuildNestedRequirement(InvalidConstraintEntity,
+    return SemaRef.Concept().BuildNestedRequirement(InvalidConstraintEntity,
                                           Satisfaction);
   }
 
   concepts::NestedRequirement *RebuildNestedRequirement(Expr *Constraint) {
-    return SemaRef.BuildNestedRequirement(Constraint);
+    return SemaRef.Concept().BuildNestedRequirement(Constraint);
   }
 
   /// \brief Build a new Objective-C boxed expression.

>From 354e8ff9f82d26b3611766d6b78b5da76ec87e69 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 23:28:18 +0300
Subject: [PATCH 3/4] Run clang-format

---
 clang/include/clang/Sema/Sema.h               |   3 +-
 clang/include/clang/Sema/SemaConcept.h        |  10 +-
 clang/lib/Parse/ParseDecl.cpp                 |   5 +-
 clang/lib/Parse/ParseDeclCXX.cpp              |   4 +-
 clang/lib/Parse/ParseExpr.cpp                 |  10 +-
 clang/lib/Parse/ParseExprCXX.cpp              |  19 +-
 clang/lib/Parse/ParseTemplate.cpp             |  20 +-
 clang/lib/Sema/SemaConcept.cpp                | 366 +++++++++---------
 clang/lib/Sema/SemaDecl.cpp                   |   6 +-
 clang/lib/Sema/SemaExpr.cpp                   |   2 +-
 clang/lib/Sema/SemaOverload.cpp               |  19 +-
 clang/lib/Sema/SemaTemplate.cpp               |  39 +-
 clang/lib/Sema/SemaTemplateDeduction.cpp      |  24 +-
 clang/lib/Sema/SemaTemplateInstantiate.cpp    |   3 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   5 +-
 clang/lib/Sema/TreeTransform.h                |  14 +-
 16 files changed, 278 insertions(+), 271 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 06be666027742..be4aebf1d04e2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10287,8 +10287,7 @@ class Sema final : public SemaBase {
     return CodeSynthesisContexts.size() > NonInstantiationEntries;
   }
 
-  private:
-
+private:
   /// Introduce the instantiated captures of the lambda into the local
   /// instantiation scope.
   bool addInstantiatedCapturesToScope(
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 1e24921354cdc..7591f28acbd7b 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -190,13 +190,13 @@ class TemplateCompareNewDeclInfo {
 public:
   TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
   TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
-                              const DeclContext *LexicalDeclCtx,
-                              SourceLocation Loc)
+                             const DeclContext *LexicalDeclCtx,
+                             SourceLocation Loc)
 
       : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
     assert(DC && LexicalDC &&
-            "Constructor only for cases where we have the information to put "
-            "in here");
+           "Constructor only for cases where we have the information to put "
+           "in here");
   }
 
   // If this was constructed with no information, we cannot do substitution
@@ -472,7 +472,7 @@ class SemaConcept : public SemaBase {
                            TemplateTypeParmDecl *ConstrainedParameter,
                            SourceLocation EllipsisLoc,
                            bool AllowUnexpandedPack);
-  
+
   bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
                             DeclarationNameInfo NameInfo,
                             ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index bd66ef5318c80..eb851091a14a7 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4083,8 +4083,9 @@ void Parser::ParseDeclarationSpecifiers(
         if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
             goto DoneWithDeclSpec;
 
-        if (TemplateId && !isInvalid && Actions.Concept().CheckTypeConstraint(TemplateId))
-            TemplateId = nullptr;
+        if (TemplateId && !isInvalid &&
+            Actions.Concept().CheckTypeConstraint(TemplateId))
+          TemplateId = nullptr;
 
         ConsumeAnnotationToken();
         SourceLocation AutoLoc = Tok.getLocation();
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index a658c03eda4bc..3a923a599af22 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4298,8 +4298,8 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) {
   TrailingRequiresClause =
       ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);
 
-  TrailingRequiresClause =
-      Actions.Concept().ActOnFinishTrailingRequiresClause(TrailingRequiresClause);
+  TrailingRequiresClause = Actions.Concept().ActOnFinishTrailingRequiresClause(
+      TrailingRequiresClause);
 
   if (!D.isDeclarationOfFunction()) {
     Diag(RequiresKWLoc,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 175e0bce683f7..c81a29549cb92 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -31,8 +31,8 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaCUDA.h"
-#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaCodeCompletion.h"
+#include "clang/Sema/SemaConcept.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenACC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -269,7 +269,8 @@ ExprResult Parser::ParseConstraintExpression() {
       Actions, Sema::ExpressionEvaluationContext::Unevaluated);
   ExprResult LHS(ParseCastExpression(AnyCastExpr));
   ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
-  if (Res.isUsable() && !Actions.Concept().CheckConstraintExpression(Res.get())) {
+  if (Res.isUsable() &&
+      !Actions.Concept().CheckConstraintExpression(Res.get())) {
     Actions.CorrectDelayedTyposInExpr(Res);
     return ExprError();
   }
@@ -330,9 +331,8 @@ Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
       NotPrimaryExpression = false;
     }
     bool PossibleNonPrimary;
-    bool IsConstraintExpr =
-        Actions.Concept().CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,
-                                          IsTrailingRequiresClause);
+    bool IsConstraintExpr = Actions.Concept().CheckConstraintExpression(
+        E.get(), Tok, &PossibleNonPrimary, IsTrailingRequiresClause);
     if (!IsConstraintExpr || PossibleNonPrimary) {
       // Atomic constraint might be an unparenthesized non-primary expression
       // (such as a binary operator), in which case we might get here (e.g. in
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 224431846fc0f..2c240b4c20dbb 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1418,8 +1418,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
       ++CurTemplateDepthTracker;
       ExprResult RequiresClause;
       if (TryConsumeToken(tok::kw_requires)) {
-        RequiresClause =
-            Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+        RequiresClause = Actions.Concept().ActOnRequiresClause(
+            ParseConstraintLogicalOrExpression(
                 /*IsTrailingRequiresClause=*/false));
         if (RequiresClause.isInvalid())
           SkipUntil({tok::l_brace, tok::l_paren}, StopAtSemi | StopBeforeMatch);
@@ -3670,7 +3670,8 @@ ExprResult Parser::ParseRequiresExpression() {
         SourceLocation NoexceptLoc;
         TryConsumeToken(tok::kw_noexcept, NoexceptLoc);
         if (Tok.is(tok::semi)) {
-          Req = Actions.Concept().ActOnCompoundRequirement(Expression.get(), NoexceptLoc);
+          Req = Actions.Concept().ActOnCompoundRequirement(Expression.get(),
+                                                           NoexceptLoc);
           if (Req)
             Requirements.push_back(Req);
           break;
@@ -3765,8 +3766,8 @@ ExprResult Parser::ParseRequiresExpression() {
                         SkipUntilFlags::StopBeforeMatch);
               break;
             }
-            if (auto *Req =
-                    Actions.Concept().ActOnNestedRequirement(ConstraintExpr.get()))
+            if (auto *Req = Actions.Concept().ActOnNestedRequirement(
+                    ConstraintExpr.get()))
               Requirements.push_back(Req);
             else {
               SkipUntil(tok::semi, tok::r_brace,
@@ -3811,9 +3812,8 @@ ExprResult Parser::ParseRequiresExpression() {
                 break;
             }
 
-            if (auto *Req = Actions.Concept().ActOnTypeRequirement(TypenameKWLoc, SS,
-                                                         NameLoc, II,
-                                                         TemplateId)) {
+            if (auto *Req = Actions.Concept().ActOnTypeRequirement(
+                    TypenameKWLoc, SS, NameLoc, II, TemplateId)) {
               Requirements.push_back(Req);
             }
             break;
@@ -3834,7 +3834,8 @@ ExprResult Parser::ParseRequiresExpression() {
         if (!Expression.isInvalid() && PossibleRequiresExprInSimpleRequirement)
           Diag(StartLoc, diag::err_requires_expr_in_simple_requirement)
               << FixItHint::CreateInsertion(StartLoc, "requires");
-        if (auto *Req = Actions.Concept().ActOnSimpleRequirement(Expression.get()))
+        if (auto *Req =
+                Actions.Concept().ActOnSimpleRequirement(Expression.get()))
           Requirements.push_back(Req);
         else {
           SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index bd732dc50cf9d..5aeef7a8227bb 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -146,8 +146,9 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(
 
       if (TryConsumeToken(tok::kw_requires)) {
         OptionalRequiresClauseConstraintER =
-            Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
-                /*IsTrailingRequiresClause=*/false));
+            Actions.Concept().ActOnRequiresClause(
+                ParseConstraintLogicalOrExpression(
+                    /*IsTrailingRequiresClause=*/false));
         if (!OptionalRequiresClauseConstraintER.isUsable()) {
           // Skip until the semi-colon or a '}'.
           SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
@@ -340,9 +341,9 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
   DeclEnd = Tok.getLocation();
   ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
   Expr *ConstraintExpr = ConstraintExprResult.get();
-  return Actions.Concept().ActOnConceptDefinition(getCurScope(),
-                                        *TemplateInfo.TemplateParams, Id, IdLoc,
-                                        ConstraintExpr, Attrs);
+  return Actions.Concept().ActOnConceptDefinition(
+      getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc, ConstraintExpr,
+      Attrs);
 }
 
 /// ParseTemplateParameters - Parses a template-parameter-list enclosed in
@@ -765,8 +766,8 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
 
   if (TypeConstraint) {
     Actions.Concept().ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
-                                cast<TemplateTypeParmDecl>(NewDecl),
-                                EllipsisLoc);
+                                          cast<TemplateTypeParmDecl>(NewDecl),
+                                          EllipsisLoc);
   }
 
   return NewDecl;
@@ -801,8 +802,9 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
     }
     if (TryConsumeToken(tok::kw_requires)) {
       OptionalRequiresClauseConstraintER =
-          Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
-              /*IsTrailingRequiresClause=*/false));
+          Actions.Concept().ActOnRequiresClause(
+              ParseConstraintLogicalOrExpression(
+                  /*IsTrailingRequiresClause=*/false));
       if (!OptionalRequiresClauseConstraintER.isUsable()) {
         SkipUntil(tok::comma, tok::greater, tok::greatergreater,
                   StopAtSemi | StopBeforeMatch);
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 8957c1d658cb1..de7c83e353b21 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -89,8 +89,9 @@ class LogicalBinOp {
 }
 
 bool SemaConcept::CheckConstraintExpression(const Expr *ConstraintExpression,
-                                     Token NextToken, bool *PossibleNonPrimary,
-                                     bool IsTrailingRequiresClause) {
+                                            Token NextToken,
+                                            bool *PossibleNonPrimary,
+                                            bool IsTrailingRequiresClause) {
   ASTContext &Context = getASTContext();
   // C++2a [temp.constr.atomic]p1
   // ..E shall be a constant expression of type bool.
@@ -167,8 +168,8 @@ struct SatisfactionStackRAII {
                         const llvm::FoldingSetNodeID &FSNID)
       : SemaRef(SemaRef) {
       if (ND) {
-      SemaRef.Concept().PushSatisfactionStackEntry(ND, FSNID);
-      Inserted = true;
+        SemaRef.Concept().PushSatisfactionStackEntry(ND, FSNID);
+        Inserted = true;
       }
   }
   ~SatisfactionStackRAII() {
@@ -536,8 +537,8 @@ bool SemaConcept::CheckConstraintSatisfaction(
   return false;
 }
 
-bool SemaConcept::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
-                                       ConstraintSatisfaction &Satisfaction) {
+bool SemaConcept::CheckConstraintSatisfaction(
+    const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
   return calculateConstraintSatisfaction(
              SemaRef, ConstraintExpr, Satisfaction,
              [this](const Expr *AtomicExpr) -> ExprResult {
@@ -585,8 +586,8 @@ bool SemaConcept::SetupConstraintScope(
             PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
       while (FromMemTempl->getInstantiatedFromMemberTemplate())
         FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
-      if (SemaRef.addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
-                                           Scope, MLTAL))
+      if (SemaRef.addInstantiatedParametersToScope(
+              FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL))
         return true;
     }
 
@@ -610,7 +611,8 @@ bool SemaConcept::SetupConstraintScope(
 
     // Case where this was not a template, but instantiated as a
     // child-function.
-    if (SemaRef.addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
+    if (SemaRef.addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope,
+                                                 MLTAL))
       return true;
   }
 
@@ -623,20 +625,21 @@ bool SemaConcept::SetupConstraintScope(
 /// lists, and calls SetupConstraintScope to set up the
 /// LocalInstantiationScope to have the proper set of ParVarDecls configured.
 static std::optional<MultiLevelTemplateArgumentList>
-SetupConstraintCheckingTemplateArgumentsAndScope(Sema &SemaRef,
-    FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
+SetupConstraintCheckingTemplateArgumentsAndScope(
+    Sema &SemaRef, FunctionDecl *FD,
+    std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
     LocalInstantiationScope &Scope) {
   MultiLevelTemplateArgumentList MLTAL;
 
   // Collect the list of template arguments relative to the 'primary' template.
   // We need the entire list, since the constraint is completely uninstantiated
   // at this point.
-  MLTAL =
-      SemaRef.getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
-                                   /*Final=*/false, /*Innermost=*/std::nullopt,
-                                   /*RelativeToPrimary=*/true,
-                                   /*Pattern=*/nullptr,
-                                   /*ForConstraintInstantiation=*/true);
+  MLTAL = SemaRef.getTemplateInstantiationArgs(
+      FD, FD->getLexicalDeclContext(),
+      /*Final=*/false, /*Innermost=*/std::nullopt,
+      /*RelativeToPrimary=*/true,
+      /*Pattern=*/nullptr,
+      /*ForConstraintInstantiation=*/true);
   if (SemaRef.Concept().SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
     return std::nullopt;
 
@@ -644,9 +647,9 @@ SetupConstraintCheckingTemplateArgumentsAndScope(Sema &SemaRef,
 }
 
 bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
-                                    ConstraintSatisfaction &Satisfaction,
-                                    SourceLocation UsageLoc,
-                                    bool ForOverloadResolution) {
+                                           ConstraintSatisfaction &Satisfaction,
+                                           SourceLocation UsageLoc,
+                                           bool ForOverloadResolution) {
   // Don't check constraints if the function is dependent. Also don't check if
   // this is a function template specialization, as the call to
   // CheckinstantiatedFunctionTemplateConstraints after this will check it
@@ -683,8 +686,8 @@ bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
   Sema::ContextRAII SavedContext{SemaRef, CtxToSave};
   LocalInstantiationScope Scope(SemaRef, !ForOverloadResolution);
   std::optional<MultiLevelTemplateArgumentList> MLTAL =
-      SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef,
-          const_cast<FunctionDecl *>(FD), {}, Scope);
+      SetupConstraintCheckingTemplateArgumentsAndScope(
+          SemaRef, const_cast<FunctionDecl *>(FD), {}, Scope);
 
   if (!MLTAL)
     return true;
@@ -695,7 +698,8 @@ bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
     ThisQuals = Method->getMethodQualifiers();
     Record = const_cast<CXXRecordDecl *>(Method->getParent());
   }
-  Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
+  Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals,
+                                   Record != nullptr);
 
   Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
       SemaRef, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
@@ -707,7 +711,6 @@ bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
       Satisfaction);
 }
 
-
 // Figure out the to-translation-unit depth for this function declaration for
 // the purpose of seeing if they differ by constraints. This isn't the same as
 // getTemplateDepth, because it includes already instantiated parents.
@@ -804,10 +807,9 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
   return SubstConstr.get();
 }
 
-bool SemaConcept::AreConstraintExpressionsEqual(const NamedDecl *Old,
-                                         const Expr *OldConstr,
-                                         const TemplateCompareNewDeclInfo &New,
-                                         const Expr *NewConstr) {
+bool SemaConcept::AreConstraintExpressionsEqual(
+    const NamedDecl *Old, const Expr *OldConstr,
+    const TemplateCompareNewDeclInfo &New, const Expr *NewConstr) {
   if (OldConstr == NewConstr)
     return true;
   // C++ [temp.constr.decl]p4
@@ -833,7 +835,8 @@ bool SemaConcept::AreConstraintExpressionsEqual(const NamedDecl *Old,
   return ID1 == ID2;
 }
 
-bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
+bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(
+    const FunctionDecl *FD) {
   assert(FD->getFriendObjectKind() && "Must be a friend!");
 
   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
@@ -847,8 +850,8 @@ bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl
 
   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(SemaRef, FD);
   for (const Expr *Constraint : ACs)
-    if (SemaRef.ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
-                                                       Constraint))
+    if (SemaRef.ConstraintExpressionDependsOnEnclosingTemplate(
+            FD, OldTemplateDepth, Constraint))
       return true;
 
   return false;
@@ -873,8 +876,8 @@ bool SemaConcept::EnsureTemplateArgumentListConstraints(
 
     Diag(TemplateIDRange.getBegin(),
          diag::err_template_arg_list_constraints_not_satisfied)
-        << (int)SemaRef.getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
-        << TemplateArgString << TemplateIDRange;
+        << (int)SemaRef.getTemplateNameKindForDiagnostics(TemplateName(TD))
+        << TD << TemplateArgString << TemplateIDRange;
     DiagnoseUnsatisfiedConstraint(Satisfaction);
     return true;
   }
@@ -902,8 +905,8 @@ bool SemaConcept::CheckInstantiatedFunctionTemplateConstraints(
   LocalInstantiationScope Scope(SemaRef);
 
   std::optional<MultiLevelTemplateArgumentList> MLTAL =
-      SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef, Decl, TemplateArgs,
-                                                       Scope);
+      SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef, Decl,
+                                                       TemplateArgs, Scope);
 
   if (!MLTAL)
     return true;
@@ -915,7 +918,8 @@ bool SemaConcept::CheckInstantiatedFunctionTemplateConstraints(
     Record = Method->getParent();
   }
 
-  Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
+  Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals,
+                                   Record != nullptr);
   Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
       SemaRef, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
 
@@ -981,7 +985,8 @@ static void diagnoseUnsatisfiedRequirement(Sema &S,
                diag::note_expr_requirement_constraints_not_satisfied)
             << (int)First << ConstraintExpr;
       }
-      S.Concept().DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
+      S.Concept().DiagnoseUnsatisfiedConstraint(
+          ConstraintExpr->getSatisfaction());
       break;
     }
     case concepts::ExprRequirement::SS_Satisfied:
@@ -1158,9 +1163,8 @@ static void diagnoseUnsatisfiedConstraintExpr(
       Record.template get<Expr *>(), First);
 }
 
-void
-SemaConcept::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
-                                    bool First) {
+void SemaConcept::DiagnoseUnsatisfiedConstraint(
+    const ConstraintSatisfaction &Satisfaction, bool First) {
   assert(!Satisfaction.IsSatisfied &&
          "Attempted to diagnose a satisfied constraint");
   for (auto &Pair : Satisfaction.Details) {
@@ -1170,8 +1174,7 @@ SemaConcept::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfa
 }
 
 void SemaConcept::DiagnoseUnsatisfiedConstraint(
-    const ASTConstraintSatisfaction &Satisfaction,
-    bool First) {
+    const ASTConstraintSatisfaction &Satisfaction, bool First) {
   assert(!Satisfaction.IsSatisfied &&
          "Attempted to diagnose a satisfied constraint");
   for (auto &Pair : Satisfaction) {
@@ -1180,8 +1183,7 @@ void SemaConcept::DiagnoseUnsatisfiedConstraint(
   }
 }
 
-const NormalizedConstraint *
-SemaConcept::getNormalizedAssociatedConstraints(
+const NormalizedConstraint *SemaConcept::getNormalizedAssociatedConstraints(
     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
   // In case the ConstrainedDecl comes from modules, it is necessary to use
   // the canonical decl to avoid different atomic constraints with the 'same'
@@ -1190,15 +1192,14 @@ SemaConcept::getNormalizedAssociatedConstraints(
 
   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
   if (CacheEntry == NormalizationCache.end()) {
-    auto Normalized =
-        NormalizedConstraint::fromConstraintExprs(SemaRef, ConstrainedDecl,
-                                                  AssociatedConstraints);
+    auto Normalized = NormalizedConstraint::fromConstraintExprs(
+        SemaRef, ConstrainedDecl, AssociatedConstraints);
     CacheEntry =
         NormalizationCache
             .try_emplace(ConstrainedDecl,
                          Normalized
-                             ? new (SemaRef.Context) NormalizedConstraint(
-                                 std::move(*Normalized))
+                             ? new (SemaRef.Context)
+                                   NormalizedConstraint(std::move(*Normalized))
                              : nullptr)
             .first;
   }
@@ -1344,8 +1345,8 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
       // expression, the program is ill-formed; no diagnostic is required.
       // [...]
       ConceptDecl *CD = CSE->getNamedConcept();
-      SubNF = S.Concept().getNormalizedAssociatedConstraints(CD,
-                                                   {CD->getConstraintExpr()});
+      SubNF = S.Concept().getNormalizedAssociatedConstraints(
+          CD, {CD->getConstraintExpr()});
       if (!SubNF)
         return std::nullopt;
     }
@@ -1478,10 +1479,10 @@ static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
 }
 
 bool SemaConcept::IsAtLeastAsConstrained(NamedDecl *D1,
-                                  MutableArrayRef<const Expr *> AC1,
-                                  NamedDecl *D2,
-                                  MutableArrayRef<const Expr *> AC2,
-                                  bool &Result) {
+                                         MutableArrayRef<const Expr *> AC1,
+                                         NamedDecl *D2,
+                                         MutableArrayRef<const Expr *> AC2,
+                                         bool &Result) {
   if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
     auto IsExpectedEntity = [](const FunctionDecl *FD) {
       FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
@@ -1530,16 +1531,17 @@ bool SemaConcept::IsAtLeastAsConstrained(NamedDecl *D1,
   }
 
   if (subsumes(SemaRef, D1, AC1, D2, AC2, Result,
-        [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
-          return A.subsumes(SemaRef.Context, B);
-        }))
+               [this](const AtomicConstraint &A, const AtomicConstraint &B) {
+                 return A.subsumes(SemaRef.Context, B);
+               }))
     return true;
   SubsumptionCache.try_emplace(Key, Result);
   return false;
 }
 
-bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
-    ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
+bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+    NamedDecl *D1, ArrayRef<const Expr *> AC1, NamedDecl *D2,
+    ArrayRef<const Expr *> AC2) {
   if (SemaRef.isSFINAEContext())
     // No need to work here because our notes would be discarded.
     return false;
@@ -1547,32 +1549,32 @@ bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
   if (AC1.empty() || AC2.empty())
     return false;
 
-  auto NormalExprEvaluator =
-      [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
-        return A.subsumes(SemaRef.Context, B);
-      };
+  auto NormalExprEvaluator = [this](const AtomicConstraint &A,
+                                    const AtomicConstraint &B) {
+    return A.subsumes(SemaRef.Context, B);
+  };
 
   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
-  auto IdenticalExprEvaluator =
-      [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
-        if (!A.hasMatchingParameterMapping(SemaRef.Context, B))
-          return false;
-        const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
-        if (EA == EB)
-          return true;
+  auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
+                                    const AtomicConstraint &B) {
+    if (!A.hasMatchingParameterMapping(SemaRef.Context, B))
+      return false;
+    const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
+    if (EA == EB)
+      return true;
 
-        // Not the same source level expression - are the expressions
-        // identical?
-        llvm::FoldingSetNodeID IDA, IDB;
-        EA->Profile(IDA, SemaRef.Context, /*Canonical=*/true);
-        EB->Profile(IDB, SemaRef.Context, /*Canonical=*/true);
-        if (IDA != IDB)
-          return false;
+    // Not the same source level expression - are the expressions
+    // identical?
+    llvm::FoldingSetNodeID IDA, IDB;
+    EA->Profile(IDA, SemaRef.Context, /*Canonical=*/true);
+    EB->Profile(IDB, SemaRef.Context, /*Canonical=*/true);
+    if (IDA != IDB)
+      return false;
 
-        AmbiguousAtomic1 = EA;
-        AmbiguousAtomic2 = EB;
-        return true;
-      };
+    AmbiguousAtomic1 = EA;
+    AmbiguousAtomic2 = EB;
+    return true;
+  };
 
   {
     // The subsumption checks might cause diagnostics
@@ -1670,12 +1672,12 @@ concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
 
 RequiresExprBodyDecl *
 SemaConcept::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
-                             ArrayRef<ParmVarDecl *> LocalParameters,
-                             Scope *BodyScope) {
+                                    ArrayRef<ParmVarDecl *> LocalParameters,
+                                    Scope *BodyScope) {
   assert(BodyScope);
 
-  RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(SemaRef.Context, SemaRef.CurContext,
-                                                            RequiresKWLoc);
+  RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(
+      SemaRef.Context, SemaRef.CurContext, RequiresKWLoc);
 
   SemaRef.PushDeclContext(BodyScope, Body);
 
@@ -1717,21 +1719,19 @@ concepts::Requirement *SemaConcept::ActOnTypeRequirement(
          "Exactly one of TypeName and TemplateId must be specified.");
   TypeSourceInfo *TSI = nullptr;
   if (TypeName) {
-    QualType T =
-        SemaRef.CheckTypenameType(ElaboratedTypeKeyword::Typename, TypenameKWLoc,
-                          SS.getWithLocInContext(SemaRef.Context), *TypeName, NameLoc,
-                          &TSI, /*DeducedTSTContext=*/false);
+    QualType T = SemaRef.CheckTypenameType(
+        ElaboratedTypeKeyword::Typename, TypenameKWLoc,
+        SS.getWithLocInContext(SemaRef.Context), *TypeName, NameLoc, &TSI,
+        /*DeducedTSTContext=*/false);
     if (T.isNull())
       return nullptr;
   } else {
     ASTTemplateArgsPtr ArgsPtr(TemplateId->getTemplateArgs(),
                                TemplateId->NumArgs);
-    TypeResult T = SemaRef.ActOnTypenameType(SemaRef.getCurScope(), TypenameKWLoc, SS,
-                                     TemplateId->TemplateKWLoc,
-                                     TemplateId->Template, TemplateId->Name,
-                                     TemplateId->TemplateNameLoc,
-                                     TemplateId->LAngleLoc, ArgsPtr,
-                                     TemplateId->RAngleLoc);
+    TypeResult T = SemaRef.ActOnTypenameType(
+        SemaRef.getCurScope(), TypenameKWLoc, SS, TemplateId->TemplateKWLoc,
+        TemplateId->Template, TemplateId->Name, TemplateId->TemplateNameLoc,
+        TemplateId->LAngleLoc, ArgsPtr, TemplateId->RAngleLoc);
     if (T.isInvalid())
       return nullptr;
     if (SemaRef.GetTypeFromParser(T.get(), &TSI).isNull())
@@ -1746,8 +1746,7 @@ SemaConcept::ActOnCompoundRequirement(Expr *E, SourceLocation NoexceptLoc) {
                               /*ReturnTypeRequirement=*/{});
 }
 
-concepts::Requirement *
-SemaConcept::ActOnCompoundRequirement(
+concepts::Requirement *SemaConcept::ActOnCompoundRequirement(
     Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
     TemplateIdAnnotation *TypeConstraint, unsigned Depth) {
   // C++2a [expr.prim.req.compound] p1.3.3
@@ -1762,13 +1761,13 @@ SemaConcept::ActOnCompoundRequirement(
   // arguments and the abstract declarator with the correct CV qualification and
   // have to synthesize T and the single parameter of F.
   auto &II = SemaRef.Context.Idents.get("expr-type");
-  auto *TParam = TemplateTypeParmDecl::Create(SemaRef.Context, SemaRef.CurContext,
-                                              SourceLocation(),
-                                              SourceLocation(), Depth,
-                                              /*Index=*/0, &II,
-                                              /*Typename=*/true,
-                                              /*ParameterPack=*/false,
-                                              /*HasTypeConstraint=*/true);
+  auto *TParam =
+      TemplateTypeParmDecl::Create(SemaRef.Context, SemaRef.CurContext,
+                                   SourceLocation(), SourceLocation(), Depth,
+                                   /*Index=*/0, &II,
+                                   /*Typename=*/true,
+                                   /*ParameterPack=*/false,
+                                   /*HasTypeConstraint=*/true);
 
   if (BuildTypeConstraint(SS, TypeConstraint, TParam,
                           /*EllipsisLoc=*/SourceLocation(),
@@ -1776,18 +1775,16 @@ SemaConcept::ActOnCompoundRequirement(
     // Just produce a requirement with no type requirements.
     return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {});
 
-  auto *TPL = TemplateParameterList::Create(SemaRef.Context, SourceLocation(),
-                                            SourceLocation(),
-                                            ArrayRef<NamedDecl *>(TParam),
-                                            SourceLocation(),
-                                            /*RequiresClause=*/nullptr);
+  auto *TPL = TemplateParameterList::Create(
+      SemaRef.Context, SourceLocation(), SourceLocation(),
+      ArrayRef<NamedDecl *>(TParam), SourceLocation(),
+      /*RequiresClause=*/nullptr);
   return BuildExprRequirement(
       E, /*IsSimple=*/false, NoexceptLoc,
       concepts::ExprRequirement::ReturnTypeRequirement(TPL));
 }
 
-concepts::ExprRequirement *
-SemaConcept::BuildExprRequirement(
+concepts::ExprRequirement *SemaConcept::BuildExprRequirement(
     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
     concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
   auto Status = concepts::ExprRequirement::SS_Satisfied;
@@ -1795,7 +1792,8 @@ SemaConcept::BuildExprRequirement(
   if (E->isInstantiationDependent() || E->getType()->isPlaceholderType() ||
       ReturnTypeRequirement.isDependent())
     Status = concepts::ExprRequirement::SS_Dependent;
-  else if (NoexceptLoc.isValid() && SemaRef.canThrow(E) == CanThrowResult::CT_Can)
+  else if (NoexceptLoc.isValid() &&
+           SemaRef.canThrow(E) == CanThrowResult::CT_Can)
     Status = concepts::ExprRequirement::SS_NoexceptNotMet;
   else if (ReturnTypeRequirement.isSubstitutionFailure())
     Status = concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure;
@@ -1823,8 +1821,9 @@ SemaConcept::BuildExprRequirement(
       return new (SemaRef.Context) concepts::ExprRequirement(
           concepts::createSubstDiagAt(SemaRef, IDC->getExprLoc(),
                                       [&](llvm::raw_ostream &OS) {
-                                        IDC->printPretty(OS, /*Helper=*/nullptr,
-                                                         SemaRef.getPrintingPolicy());
+                                        IDC->printPretty(
+                                            OS, /*Helper=*/nullptr,
+                                            SemaRef.getPrintingPolicy());
                                       }),
           IsSimple, NoexceptLoc, ReturnTypeRequirement);
     }
@@ -1833,19 +1832,17 @@ SemaConcept::BuildExprRequirement(
     if (!SubstitutedConstraintExpr->isSatisfied())
       Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
   }
-  return new (SemaRef.Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
-                                                 ReturnTypeRequirement, Status,
-                                                 SubstitutedConstraintExpr);
+  return new (SemaRef.Context)
+      concepts::ExprRequirement(E, IsSimple, NoexceptLoc, ReturnTypeRequirement,
+                                Status, SubstitutedConstraintExpr);
 }
 
-concepts::ExprRequirement *
-SemaConcept::BuildExprRequirement(
+concepts::ExprRequirement *SemaConcept::BuildExprRequirement(
     concepts::Requirement::SubstitutionDiagnostic *ExprSubstitutionDiagnostic,
     bool IsSimple, SourceLocation NoexceptLoc,
     concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
-  return new (SemaRef.Context) concepts::ExprRequirement(ExprSubstitutionDiagnostic,
-                                                 IsSimple, NoexceptLoc,
-                                                 ReturnTypeRequirement);
+  return new (SemaRef.Context) concepts::ExprRequirement(
+      ExprSubstitutionDiagnostic, IsSimple, NoexceptLoc, ReturnTypeRequirement);
 }
 
 concepts::TypeRequirement *
@@ -1853,8 +1850,7 @@ SemaConcept::BuildTypeRequirement(TypeSourceInfo *Type) {
   return new (SemaRef.Context) concepts::TypeRequirement(Type);
 }
 
-concepts::TypeRequirement *
-SemaConcept::BuildTypeRequirement(
+concepts::TypeRequirement *SemaConcept::BuildTypeRequirement(
     concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
   return new (SemaRef.Context) concepts::TypeRequirement(SubstDiag);
 }
@@ -1870,13 +1866,13 @@ SemaConcept::BuildNestedRequirement(Expr *Constraint) {
       CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
                                   Constraint->getSourceRange(), Satisfaction))
     return nullptr;
-  return new (SemaRef.Context) concepts::NestedRequirement(SemaRef.Context, Constraint,
-                                                   Satisfaction);
+  return new (SemaRef.Context)
+      concepts::NestedRequirement(SemaRef.Context, Constraint, Satisfaction);
 }
 
-concepts::NestedRequirement *
-SemaConcept::BuildNestedRequirement(StringRef InvalidConstraintEntity,
-                       const ASTConstraintSatisfaction &Satisfaction) {
+concepts::NestedRequirement *SemaConcept::BuildNestedRequirement(
+    StringRef InvalidConstraintEntity,
+    const ASTConstraintSatisfaction &Satisfaction) {
   return new (SemaRef.Context) concepts::NestedRequirement(
       InvalidConstraintEntity,
       ASTConstraintSatisfaction::Rebuild(SemaRef.Context, Satisfaction));
@@ -1887,9 +1883,9 @@ ExprResult SemaConcept::ActOnRequiresExpr(
     SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
     SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
     SourceLocation ClosingBraceLoc) {
-  auto *RE = RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body, LParenLoc,
-                                  LocalParameters, RParenLoc, Requirements,
-                                  ClosingBraceLoc);
+  auto *RE = RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body,
+                                  LParenLoc, LocalParameters, RParenLoc,
+                                  Requirements, ClosingBraceLoc);
   if (SemaRef.DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
     return ExprError();
   return RE;
@@ -1921,19 +1917,17 @@ bool SemaConcept::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
   return false;
 }
 
-bool SemaConcept::ActOnTypeConstraint(const CXXScopeSpec &SS,
-                               TemplateIdAnnotation *TypeConstr,
-                               TemplateTypeParmDecl *ConstrainedParameter,
-                               SourceLocation EllipsisLoc) {
+bool SemaConcept::ActOnTypeConstraint(
+    const CXXScopeSpec &SS, TemplateIdAnnotation *TypeConstr,
+    TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc) {
   return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
                              false);
 }
 
-bool SemaConcept::BuildTypeConstraint(const CXXScopeSpec &SS,
-                               TemplateIdAnnotation *TypeConstr,
-                               TemplateTypeParmDecl *ConstrainedParameter,
-                               SourceLocation EllipsisLoc,
-                               bool AllowUnexpandedPack) {
+bool SemaConcept::BuildTypeConstraint(
+    const CXXScopeSpec &SS, TemplateIdAnnotation *TypeConstr,
+    TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc,
+    bool AllowUnexpandedPack) {
 
   if (CheckTypeConstraint(TypeConstr))
     return true;
@@ -1947,18 +1941,19 @@ bool SemaConcept::BuildTypeConstraint(const CXXScopeSpec &SS,
 
   TemplateArgumentListInfo TemplateArgs;
   if (TypeConstr->LAngleLoc.isValid()) {
-    TemplateArgs =
-        SemaRef.makeTemplateArgumentListInfo(*TypeConstr);
+    TemplateArgs = SemaRef.makeTemplateArgumentListInfo(*TypeConstr);
 
     if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
       for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
-        if (SemaRef.DiagnoseUnexpandedParameterPack(Arg, Sema::UPPC_TypeConstraint))
+        if (SemaRef.DiagnoseUnexpandedParameterPack(Arg,
+                                                    Sema::UPPC_TypeConstraint))
           return true;
       }
     }
   }
   return AttachTypeConstraint(
-      SS.isSet() ? SS.getWithLocInContext(SemaRef.Context) : NestedNameSpecifierLoc(),
+      SS.isSet() ? SS.getWithLocInContext(SemaRef.Context)
+                 : NestedNameSpecifierLoc(),
       ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD,
       TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
       ConstrainedParameter, EllipsisLoc);
@@ -1974,8 +1969,8 @@ static ExprResult formImmediatelyDeclaredConstraint(
 
   TemplateArgumentListInfo ConstraintArgs;
   ConstraintArgs.addArgument(
-    S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
-                                    /*NTTPType=*/QualType(), ParamNameLoc));
+      S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
+                                      /*NTTPType=*/QualType(), ParamNameLoc));
 
   ConstraintArgs.setRAngleLoc(RAngleLoc);
   ConstraintArgs.setLAngleLoc(LAngleLoc);
@@ -2017,18 +2012,18 @@ static ExprResult formImmediatelyDeclaredConstraint(
 /// \returns true if an error occurred. This can happen if the
 /// immediately-declared constraint could not be formed (e.g. incorrect number
 /// of arguments for the named concept).
-bool SemaConcept::AttachTypeConstraint(NestedNameSpecifierLoc NS,
-                                DeclarationNameInfo NameInfo,
-                                ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
-                                const TemplateArgumentListInfo *TemplateArgs,
-                                TemplateTypeParmDecl *ConstrainedParameter,
-                                SourceLocation EllipsisLoc) {
+bool SemaConcept::AttachTypeConstraint(
+    NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
+    ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
+    const TemplateArgumentListInfo *TemplateArgs,
+    TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc) {
   // C++2a [temp.param]p4:
   //     [...] If Q is of the form C<A1, ..., An>, then let E' be
   //     C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
   const ASTTemplateArgumentListInfo *ArgsAsWritten =
-    TemplateArgs ? ASTTemplateArgumentListInfo::Create(SemaRef.Context,
-                                                       *TemplateArgs) : nullptr;
+      TemplateArgs
+          ? ASTTemplateArgumentListInfo::Create(SemaRef.Context, *TemplateArgs)
+          : nullptr;
 
   QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
 
@@ -2057,10 +2052,9 @@ bool SemaConcept::AttachTypeConstraint(NestedNameSpecifierLoc NS,
   return false;
 }
 
-bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
-                                NonTypeTemplateParmDecl *NewConstrainedParm,
-                                NonTypeTemplateParmDecl *OrigConstrainedParm,
-                                SourceLocation EllipsisLoc) {
+bool SemaConcept::AttachTypeConstraint(
+    AutoTypeLoc TL, NonTypeTemplateParmDecl *NewConstrainedParm,
+    NonTypeTemplateParmDecl *OrigConstrainedParm, SourceLocation EllipsisLoc) {
   if (NewConstrainedParm->getType() != TL.getType() ||
       TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
     Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
@@ -2072,9 +2066,9 @@ bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
   }
   // FIXME: Concepts: This should be the type of the placeholder, but this is
   // unclear in the wording right now.
-  DeclRefExpr *Ref =
-      SemaRef.BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
-                       VK_PRValue, OrigConstrainedParm->getLocation());
+  DeclRefExpr *Ref = SemaRef.BuildDeclRefExpr(
+      OrigConstrainedParm, OrigConstrainedParm->getType(), VK_PRValue,
+      OrigConstrainedParm->getLocation());
   if (!Ref)
     return true;
   ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
@@ -2096,13 +2090,10 @@ bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
   return false;
 }
 
-ExprResult
-SemaConcept::CheckConceptTemplateId(const CXXScopeSpec &SS,
-                             SourceLocation TemplateKWLoc,
-                             const DeclarationNameInfo &ConceptNameInfo,
-                             NamedDecl *FoundDecl,
-                             ConceptDecl *NamedConcept,
-                             const TemplateArgumentListInfo *TemplateArgs) {
+ExprResult SemaConcept::CheckConceptTemplateId(
+    const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+    const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl,
+    ConceptDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs) {
   assert(NamedConcept && "A concept template id without a template?");
   ASTContext &Context = getASTContext();
 
@@ -2154,7 +2145,7 @@ Decl *SemaConcept::ActOnConceptDefinition(
 
   if (!DC->getRedeclContext()->isFileContext()) {
     Diag(NameLoc,
-      diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
+         diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
     return nullptr;
   }
 
@@ -2188,8 +2179,8 @@ Decl *SemaConcept::ActOnConceptDefinition(
   if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr))
     return nullptr;
 
-  ConceptDecl *NewDecl =
-      ConceptDecl::Create(SemaRef.Context, DC, NameLoc, Name, Params, ConstraintExpr);
+  ConceptDecl *NewDecl = ConceptDecl::Create(SemaRef.Context, DC, NameLoc, Name,
+                                             Params, ConstraintExpr);
 
   if (NewDecl->hasAssociatedConstraints()) {
     // C++2a [temp.concept]p4:
@@ -2204,7 +2195,7 @@ Decl *SemaConcept::ActOnConceptDefinition(
                         SemaRef.forRedeclarationInCurContext());
   SemaRef.LookupName(Previous, S);
   SemaRef.FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false,
-                       /*AllowInlineNamespace*/false);
+                               /*AllowInlineNamespace*/ false);
   bool AddToScope = true;
   CheckConceptRedefinition(NewDecl, Previous, AddToScope);
 
@@ -2218,13 +2209,15 @@ Decl *SemaConcept::ActOnConceptDefinition(
 }
 
 void SemaConcept::CheckConceptRedefinition(ConceptDecl *NewDecl,
-                                    LookupResult &Previous, bool &AddToScope) {
+                                           LookupResult &Previous,
+                                           bool &AddToScope) {
   AddToScope = true;
 
   if (Previous.empty())
     return;
 
-  auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
+  auto *OldConcept = dyn_cast<ConceptDecl>(
+      Previous.getRepresentativeDecl()->getUnderlyingDecl());
   if (!OldConcept) {
     auto *Old = Previous.getRepresentativeDecl();
     Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
@@ -2265,15 +2258,16 @@ void SemaConcept::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
   auto &FTI = D.getFunctionTypeInfo();
   if (!FTI.Params)
     return;
-  for (auto &Param : ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params,
-                                                          FTI.NumParams)) {
+  for (auto &Param :
+       ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params, FTI.NumParams)) {
     auto *ParamDecl = cast<NamedDecl>(Param.Param);
     if (ParamDecl->getDeclName())
       SemaRef.PushOnScopeChains(ParamDecl, S, /*AddToContext=*/false);
   }
 }
 
-ExprResult SemaConcept::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
+ExprResult
+SemaConcept::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
   return ActOnRequiresClause(ConstraintExpr);
 }
 
@@ -2286,20 +2280,21 @@ ExprResult SemaConcept::ActOnRequiresClause(ExprResult ConstraintExpr) {
     return ExprError();
 
   if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
-                                      Sema::UPPC_RequiresClause))
+                                              Sema::UPPC_RequiresClause))
     return ExprError();
 
   return ConstraintExpr;
 }
 
-void SemaConcept::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
+void SemaConcept::CheckConstrainedAuto(const AutoType *AutoT,
+                                       SourceLocation Loc) {
   if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
     SemaRef.DiagnoseUseOfDecl(Decl, Loc);
   }
 }
 
 FunctionDecl *SemaConcept::getMoreConstrainedFunction(FunctionDecl *FD1,
-                                               FunctionDecl *FD2) {
+                                                      FunctionDecl *FD2) {
   assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
          "not for function templates");
   FunctionDecl *F1 = FD1;
@@ -2321,7 +2316,8 @@ FunctionDecl *SemaConcept::getMoreConstrainedFunction(FunctionDecl *FD1,
   return AtLeastAsConstrained1 ? FD1 : FD2;
 }
 
-clang::SemaConcept::SemaConcept(Sema &S) : SemaBase(S), SatisfactionCache(S.Context) {}
+clang::SemaConcept::SemaConcept(Sema &S)
+    : SemaBase(S), SatisfactionCache(S.Context) {}
 
 clang::SemaConcept::~SemaConcept() {
   // Delete cached satisfactions.
@@ -2333,7 +2329,9 @@ clang::SemaConcept::~SemaConcept() {
     delete Node;
 }
 
-clang::SemaConcept::SatisfactionStackResetRAII::SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
+clang::SemaConcept::SatisfactionStackResetRAII::SatisfactionStackResetRAII(
+    Sema &S)
+    : SemaRef(S) {
   SemaRef.Concept().SwapSatisfactionStack(BackupSatisfactionStack);
 }
 
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1aeb6b87b680a..b4560bd41052c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -19013,9 +19013,9 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
         AnotherMethodIsMoreConstrained = true;
         break;
       }
-      if (S.Concept().IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, OrigMethod,
-                                   {Constraints},
-                                   AnotherMethodIsMoreConstrained)) {
+      if (S.Concept().IsAtLeastAsConstrained(OtherMethod, {OtherConstraints},
+                                             OrigMethod, {Constraints},
+                                             AnotherMethodIsMoreConstrained)) {
         // There was an error with the constraints comparison. Exit the loop
         // and don't consider this function eligible.
         AnotherMethodIsMoreConstrained = true;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b9ab327d37247..63d579266ba16 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -296,7 +296,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
     if (!SkipTrailingRequiresClause && FD->getTrailingRequiresClause()) {
       ConstraintSatisfaction Satisfaction;
       if (Concept().CheckFunctionConstraints(FD, Satisfaction, Loc,
-                                   /*ForOverloadResolution*/ true))
+                                             /*ForOverloadResolution*/ true))
         // A diagnostic will have already been generated (non-constant
         // constraint expression, for example)
         return true;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index f138db5467030..7947c061d6a9c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1518,8 +1518,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
          *OldRC = Old->getTrailingRequiresClause();
     if ((NewRC != nullptr) != (OldRC != nullptr))
       return true;
-    if (NewRC &&
-        !SemaRef.Concept().AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
+    if (NewRC && !SemaRef.Concept().AreConstraintExpressionsEqual(
+                     OldDecl, OldRC, NewDecl, NewRC))
       return true;
   }
 
@@ -7095,7 +7095,7 @@ void Sema::AddOverloadCandidate(
   if (Function->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
     if (Concept().CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
-                                 /*ForOverloadResolution*/ true) ||
+                                           /*ForOverloadResolution*/ true) ||
         !Satisfaction.IsSatisfied) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -7613,7 +7613,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
   if (Method->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
     if (Concept().CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
-                                 /*ForOverloadResolution*/ true) ||
+                                           /*ForOverloadResolution*/ true) ||
         !Satisfaction.IsSatisfied) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -8326,7 +8326,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
   if (Conversion->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
     if (Concept().CheckFunctionConstraints(Conversion, Satisfaction, /*Loc*/ {},
-                                 /*ForOverloadResolution*/ true) ||
+                                           /*ForOverloadResolution*/ true) ||
         !Satisfaction.IsSatisfied) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -11221,8 +11221,8 @@ MaybeDiagnoseAmbiguousConstraints(Sema &S, ArrayRef<OverloadCandidate> Cands) {
     return;
   // The diagnostic can only happen if there are associated constraints on
   // both sides (there needs to be some identical atomic constraint).
-  if (S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
-                                                      SecondCand, SecondAC))
+  if (S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+          FirstCand, FirstAC, SecondCand, SecondAC))
     // Just show the user one diagnostic, they'll probably figure it out
     // from here.
     return;
@@ -11748,7 +11748,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
         << TemplateArgString;
 
     S.Concept().DiagnoseUnsatisfiedConstraint(
-        static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
+        static_cast<CNSInfo *>(DeductionFailure.Data)->Satisfaction);
     return;
   }
   case TemplateDeductionResult::TooManyArguments:
@@ -13342,7 +13342,8 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
       }
       // FD has the same CUDA prefernece than Result. Continue check
       // constraints.
-      FunctionDecl *MoreConstrained = Concept().getMoreConstrainedFunction(FD, Result);
+      FunctionDecl *MoreConstrained =
+          Concept().getMoreConstrainedFunction(FD, Result);
       if (MoreConstrained != FD) {
         if (!MoreConstrained) {
           IsResultAmbiguous = true;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 73abb59857a97..3083a0909a35f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4966,8 +4966,8 @@ static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
   SmallVector<const Expr *, 3> PartialAC, TemplateAC;
   Template->getAssociatedConstraints(TemplateAC);
   Partial->getAssociatedConstraints(PartialAC);
-  S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Partial, PartialAC, Template,
-                                                  TemplateAC);
+  S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+      Partial, PartialAC, Template, TemplateAC);
 }
 
 static void
@@ -5474,9 +5474,9 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
   }
 
   if (R.getAsSingle<ConceptDecl>()) {
-    return Concept().CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(),
-                                  R.getRepresentativeDecl(),
-                                  R.getAsSingle<ConceptDecl>(), TemplateArgs);
+    return Concept().CheckConceptTemplateId(
+        SS, TemplateKWLoc, R.getLookupNameInfo(), R.getRepresentativeDecl(),
+        R.getAsSingle<ConceptDecl>(), TemplateArgs);
   }
 
   // We don't want lookup warnings at this point.
@@ -8296,8 +8296,9 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
       Template->getAssociatedConstraints(TemplateAC);
 
       bool IsParamAtLeastAsConstrained;
-      if (Concept().IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
-                                 IsParamAtLeastAsConstrained))
+      if (Concept().IsAtLeastAsConstrained(Param, ParamsAC, Template,
+                                           TemplateAC,
+                                           IsParamAtLeastAsConstrained))
         return true;
       if (!IsParamAtLeastAsConstrained) {
         Diag(Arg.getLocation(),
@@ -8306,8 +8307,8 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
         Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
         Diag(Template->getLocation(), diag::note_entity_declared_at)
             << Template;
-        Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
-                                                      TemplateAC);
+        Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+            Param, ParamsAC, Template, TemplateAC);
         return true;
       }
       return false;
@@ -8634,9 +8635,8 @@ Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
 
 /// Match two template parameters within template parameter lists.
 static bool MatchTemplateParameterKind(
-    Sema &S, NamedDecl *New,
-    const TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
-    const NamedDecl *OldInstFrom, bool Complain,
+    Sema &S, NamedDecl *New, const TemplateCompareNewDeclInfo &NewInstFrom,
+    NamedDecl *Old, const NamedDecl *OldInstFrom, bool Complain,
     Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
   // Check the actual kind (type, non-type, template).
   if (Old->getKind() != New->getKind()) {
@@ -8770,8 +8770,8 @@ static bool MatchTemplateParameterKind(
     }
 
     if (NewC) {
-      if (!S.Concept().AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom,
-                                           NewC)) {
+      if (!S.Concept().AreConstraintExpressionsEqual(OldInstFrom, OldC,
+                                                     NewInstFrom, NewC)) {
         if (Complain)
           Diagnose();
         return false;
@@ -8912,8 +8912,8 @@ bool Sema::TemplateParameterListsAreEqual(
     }
 
     if (NewRC) {
-      if (!Concept().AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom,
-                                         NewRC)) {
+      if (!Concept().AreConstraintExpressionsEqual(OldInstFrom, OldRC,
+                                                   NewInstFrom, NewRC)) {
         if (Complain)
           Diagnose();
         return false;
@@ -10204,9 +10204,10 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
         continue;
       if (ConstraintSatisfaction Satisfaction;
           Method->getTrailingRequiresClause() &&
-          (Concept().CheckFunctionConstraints(Method, Satisfaction,
-                                    /*UsageLoc=*/Member->getLocation(),
-                                    /*ForOverloadResolution=*/true) ||
+          (Concept().CheckFunctionConstraints(
+               Method, Satisfaction,
+               /*UsageLoc=*/Member->getLocation(),
+               /*ForOverloadResolution=*/true) ||
            !Satisfaction.IsSatisfied))
         continue;
       Candidates.push_back(Method);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 25a36706b8039..dacfa18cfb467 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3089,9 +3089,9 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
   if (!Innermost)
     MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
 
-  if (S.Concept().CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
-                                    Info.getLocation(),
-                                    Info.AssociatedConstraintsSatisfaction) ||
+  if (S.Concept().CheckConstraintSatisfaction(
+          Template, AssociatedConstraints, MLTAL, Info.getLocation(),
+          Info.AssociatedConstraintsSatisfaction) ||
       !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
     Info.reset(
         TemplateArgumentList::CreateCopy(S.Context, SugaredDeducedArgs),
@@ -5101,9 +5101,9 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
     return true;
   MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted,
                                        /*Final=*/false);
-  if (S.Concept().CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
-                                    MLTAL, TypeLoc.getLocalSourceRange(),
-                                    Satisfaction))
+  if (S.Concept().CheckConstraintSatisfaction(
+          Concept, {Concept->getConstraintExpr()}, MLTAL,
+          TypeLoc.getLocalSourceRange(), Satisfaction))
     return true;
   if (!Satisfaction.IsSatisfied) {
     std::string Buf;
@@ -5854,9 +5854,11 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   FT1->getAssociatedConstraints(AC1);
   FT2->getAssociatedConstraints(AC2);
   bool AtLeastAsConstrained1, AtLeastAsConstrained2;
-  if (Concept().IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
+  if (Concept().IsAtLeastAsConstrained(FT1, AC1, FT2, AC2,
+                                       AtLeastAsConstrained1))
     return nullptr;
-  if (Concept().IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
+  if (Concept().IsAtLeastAsConstrained(FT2, AC2, FT1, AC1,
+                                       AtLeastAsConstrained2))
     return nullptr;
   if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
     return nullptr;
@@ -6200,10 +6202,12 @@ getMoreSpecialized(Sema &S, QualType T1, QualType T2, TemplateLikeDecl *P1,
   P1->getAssociatedConstraints(AC1);
   P2->getAssociatedConstraints(AC2);
   bool AtLeastAsConstrained1, AtLeastAsConstrained2;
-  if (S.Concept().IsAtLeastAsConstrained(P1, AC1, P2, AC2, AtLeastAsConstrained1) ||
+  if (S.Concept().IsAtLeastAsConstrained(P1, AC1, P2, AC2,
+                                         AtLeastAsConstrained1) ||
       (IsMoreSpecialThanPrimaryCheck && !AtLeastAsConstrained1))
     return nullptr;
-  if (S.Concept().IsAtLeastAsConstrained(P2, AC2, P1, AC1, AtLeastAsConstrained2))
+  if (S.Concept().IsAtLeastAsConstrained(P2, AC2, P1, AC1,
+                                         AtLeastAsConstrained2))
     return nullptr;
   if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
     return nullptr;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c2b6d151cdf45..2bb7b1f99af50 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -4662,7 +4662,8 @@ bool Sema::addInstantiatedCapturesToScope(
     } else {
       Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
       std::optional<unsigned> NumArgumentsInExpansion =
-          SemaRef.getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
+          SemaRef.getNumArgumentsInExpansion(CapturedPattern->getType(),
+                                             TemplateArgs);
       if (!NumArgumentsInExpansion)
         continue;
       for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 729f7442cbe06..e13f5ecfe724e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3112,8 +3112,9 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
       // Note: We attach the uninstantiated constriant here, so that it can be
       // instantiated relative to the top level, like all our other
       // constraints.
-      if (SemaRef.Concept().AttachTypeConstraint(AutoLoc, /*NewConstrainedParm=*/Param,
-                                       /*OrigConstrainedParm=*/D, EllipsisLoc))
+      if (SemaRef.Concept().AttachTypeConstraint(
+              AutoLoc, /*NewConstrainedParm=*/Param,
+              /*OrigConstrainedParm=*/D, EllipsisLoc))
         Invalid = true;
     }
 
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0172b49ced0cf..f063030937837 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3663,10 +3663,8 @@ class TreeTransform {
       TemplateArgumentListInfo *TALI) {
     CXXScopeSpec SS;
     SS.Adopt(NNS);
-    ExprResult Result = getSema().Concept().CheckConceptTemplateId(SS, TemplateKWLoc,
-                                                         ConceptNameInfo,
-                                                         FoundDecl,
-                                                         NamedConcept, TALI);
+    ExprResult Result = getSema().Concept().CheckConceptTemplateId(
+        SS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, TALI);
     if (Result.isInvalid())
       return ExprError();
     return Result;
@@ -3703,22 +3701,22 @@ class TreeTransform {
       concepts::Requirement::SubstitutionDiagnostic *SubstDiag, bool IsSimple,
       SourceLocation NoexceptLoc,
       concepts::ExprRequirement::ReturnTypeRequirement Ret) {
-    return SemaRef.Concept().BuildExprRequirement(SubstDiag, IsSimple, NoexceptLoc,
-                                        std::move(Ret));
+    return SemaRef.Concept().BuildExprRequirement(SubstDiag, IsSimple,
+                                                  NoexceptLoc, std::move(Ret));
   }
 
   concepts::ExprRequirement *
   RebuildExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
                          concepts::ExprRequirement::ReturnTypeRequirement Ret) {
     return SemaRef.Concept().BuildExprRequirement(E, IsSimple, NoexceptLoc,
-                                        std::move(Ret));
+                                                  std::move(Ret));
   }
 
   concepts::NestedRequirement *
   RebuildNestedRequirement(StringRef InvalidConstraintEntity,
                            const ASTConstraintSatisfaction &Satisfaction) {
     return SemaRef.Concept().BuildNestedRequirement(InvalidConstraintEntity,
-                                          Satisfaction);
+                                                    Satisfaction);
   }
 
   concepts::NestedRequirement *RebuildNestedRequirement(Expr *Constraint) {

>From 02bce366b11c44e214b4cd11e2aaa99b8dc15a27 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 23:41:05 +0300
Subject: [PATCH 4/4] Remove duplicated include

---
 clang/include/clang/Sema/SemaConcept.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 7591f28acbd7b..96e36dc8a188c 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -21,7 +21,6 @@
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprConcepts.h"
-#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/Type.h"



More information about the cfe-commits mailing list