https://github.com/zyn0217 created 
https://github.com/llvm/llvm-project/pull/218618

We used to drop SFINAE errors that occurred during parameter mapping 
instantiation
on the floor, making our diagnostics worse for some cases.

This patch corrects that behavior. Moreover it fixes some clients where
the errors were not properly handled for invalid expressions.


>From a4d8587ef8a41cff0dcfda65eadbd1f5214ab285 Mon Sep 17 00:00:00 2001
From: Younan Zhang <[email protected]>
Date: Tue, 25 Aug 2026 11:17:35 +0800
Subject: [PATCH 1/2] [Clang] Fix C++26 fold expression normalization of
 PackIndexingExpr

It turns out that PackIndexingExpr doesn't create any PackExpansionTypes
for unexpanded packs and thus we don't have to remove the packs
during the normalization.

This also reverts the previous attempt f3fd5b2dd9 that doesn't completely
solve the problem.
---
 clang/lib/Sema/SemaConcept.cpp          |  6 ++++++
 clang/lib/Sema/TreeTransform.h          |  4 ----
 clang/test/SemaCXX/cxx2c-fold-exprs.cpp | 18 ++++++++++++++++++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index def80e274e10c..e6ef73b5a2d53 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -269,6 +269,12 @@ class AdjustConstraints : public 
TreeTransform<AdjustConstraints> {
     return Result;
   }
 
+  QualType TransformPackIndexingType(TypeLocBuilder &TLB,
+                                     PackIndexingTypeLoc TL) {
+    llvm::SaveAndRestore _1(RemoveNonPackExpansionPacks, false);
+    return inherited::TransformPackIndexingType(TLB, TL);
+  }
+
   bool AlreadyTransformed(QualType T) {
     if (T.isNull())
       return true;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index b0c836325a971..4799f72dd6177 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -7124,10 +7124,6 @@ 
TreeTransform<Derived>::TransformPackIndexingType(TypeLocBuilder &TLB,
 
   for (QualType T : Types) {
     if (!T->containsUnexpandedParameterPack()) {
-      // A pack indexing type can appear in a larger pack expansion,
-      // e.g. `Pack...[pack_of_indexes]...`
-      // so we need to temporarily disable substitution of pack elements
-      Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), std::nullopt);
       QualType Transformed = getDerived().TransformType(T);
       if (Transformed.isNull())
         return QualType();
diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp 
b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
index 79d57a6f94d58..b7b03278da54e 100644
--- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
+++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
@@ -641,3 +641,21 @@ void f()
 void g() { f<long long, float>(); }
 
 }
+
+namespace GH218548 {
+
+template <class T>
+concept same_as_impl = sizeof(T) == 2;
+template <typename... P>
+void f() requires(same_as_impl<P...[sizeof(P)]> && ...) // #GH218548_f
+{}
+void g() {
+  f<char, short, short>();
+
+  f<char, int, short>();
+  // expected-error@-1 {{no matching function}}
+  // expected-note@#GH218548_f {{constraints not satisfied}}
+  // expected-note@#GH218548_f {{invalid index}}
+}
+
+}

>From 5f9f3b92c69b41074e6faf4ec5d8d90d710040fb Mon Sep 17 00:00:00 2001
From: Younan Zhang <[email protected]>
Date: Tue, 25 Aug 2026 15:47:44 +0800
Subject: [PATCH 2/2] [Clang] Improve concept diagnostics

We used to drop SFINAE errors that occurred during parameter mapping 
instantiation
on the floor, making our diagnostics worse for some cases.

This patch corrects that behavior. Moreover it fixes some clients where
the errors were not properly handled for invalid expressions.
---
 clang/lib/Sema/SemaConcept.cpp                | 77 ++++++++-----------
 clang/lib/Sema/SemaTemplateDeduction.cpp      | 11 +--
 .../non-function-templates.cpp                |  2 +
 clang/test/SemaCXX/cxx23-assume.cpp           |  1 +
 clang/test/SemaCXX/cxx2c-fold-exprs.cpp       | 63 +++++++++++----
 clang/test/SemaTemplate/concepts.cpp          |  4 +
 .../SemaTemplate/cxx2a-constraint-exprs.cpp   |  1 +
 .../instantiate-requires-expr.cpp             |  1 +
 8 files changed, 93 insertions(+), 67 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e6ef73b5a2d53..5c785d9129dda 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -555,6 +555,31 @@ class ConstraintSatisfactionChecker {
                                         : PackSubstitutionIndex;
   }
 
+  StringRef allocateStringFromConceptDiagnostic(const PartialDiagnostic &Diag) 
{
+    SmallString<128> DiagString;
+    DiagString = ": ";
+    Diag.EmitToString(S.getDiagnostics(), DiagString);
+    return S.getASTContext().backupStr(DiagString);
+  }
+
+  void consumeSFINAEFailure(TemplateDeductionInfo &Info,
+                            ConstraintSatisfaction &Satisfaction) {
+    PartialDiagnosticAt SubstDiag{SourceLocation(),
+                                  PartialDiagnostic::NullDiagnostic()};
+    Info.takeSFINAEDiagnostic(SubstDiag);
+    // FIXME: This is an unfortunate consequence of there
+    //  being no serialization code for PartialDiagnostics and the fact
+    //  that serializing them would likely take a lot more storage than
+    //  just storing them as strings. We would still like, in the
+    //  future, to serialize the proper PartialDiagnostic as serializing
+    //  it as a string defeats the purpose of the diagnostic mechanism.
+    Satisfaction.Details.emplace_back(
+        new (S.Context) ConstraintSubstitutionDiagnostic{
+            SubstDiag.first,
+            allocateStringFromConceptDiagnostic(SubstDiag.second)});
+    Satisfaction.IsSatisfied = false;
+  }
+
   ExprResult
   EvaluateAtomicConstraint(const Expr *AtomicExpr,
                            const MultiLevelTemplateArgumentList &MLTAL);
@@ -607,14 +632,6 @@ class ConstraintSatisfactionChecker {
                       const MultiLevelTemplateArgumentList &MLTAL);
 };
 
-StringRef allocateStringFromConceptDiagnostic(const Sema &S,
-                                              const PartialDiagnostic Diag) {
-  SmallString<128> DiagString;
-  DiagString = ": ";
-  Diag.EmitToString(S.getDiagnostics(), DiagString);
-  return S.getASTContext().backupStr(DiagString);
-}
-
 } // namespace
 
 ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
@@ -653,21 +670,7 @@ ExprResult 
ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
         // A non-SFINAE error has occurred as a result of this
         // substitution.
         return ExprError();
-
-      PartialDiagnosticAt SubstDiag{SourceLocation(),
-                                    PartialDiagnostic::NullDiagnostic()};
-      Info.takeSFINAEDiagnostic(SubstDiag);
-      // FIXME: This is an unfortunate consequence of there
-      //  being no serialization code for PartialDiagnostics and the fact
-      //  that serializing them would likely take a lot more storage than
-      //  just storing them as strings. We would still like, in the
-      //  future, to serialize the proper PartialDiagnostic as serializing
-      //  it as a string defeats the purpose of the diagnostic mechanism.
-      Satisfaction.Details.emplace_back(
-          new (S.Context) ConstraintSubstitutionDiagnostic{
-              SubstDiag.first,
-              allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
-      Satisfaction.IsSatisfied = false;
+      consumeSFINAEFailure(Info, Satisfaction);
       return ExprEmpty();
     }
   }
@@ -732,7 +735,7 @@ 
ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
   if (S.SubstTemplateArgumentsInParameterMapping(
           Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
           SubstArgs)) {
-    Satisfaction.IsSatisfied = false;
+    consumeSFINAEFailure(Info, Satisfaction);
     return std::nullopt;
   }
 
@@ -793,7 +796,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
       SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
   if (!SubstitutedArgs) {
     Satisfaction.IsSatisfied = false;
-    return ExprEmpty();
+    return ExprError();
   }
 
   // Make sure that concepts are not evaluated in the context they are used,
@@ -827,7 +830,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
     Satisfaction.Details.emplace_back(
         new (S.Context) ConstraintSubstitutionDiagnostic{
             SubstitutedAtomicExpr.get()->getBeginLoc(),
-            allocateStringFromConceptDiagnostic(S, Msg)});
+            allocateStringFromConceptDiagnostic(Msg)});
     return SubstitutedAtomicExpr;
   }
 
@@ -1033,7 +1036,6 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
 
   if (!SubstitutedArgs) {
     Satisfaction.IsSatisfied = false;
-    // FIXME: diagnostics?
     return ExprError();
   }
 
@@ -1063,20 +1065,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
     if (!Trap.hasErrorOccurred())
       return ExprError();
 
-    PartialDiagnosticAt SubstDiag{SourceLocation(),
-                                  PartialDiagnostic::NullDiagnostic()};
-    Info.takeSFINAEDiagnostic(SubstDiag);
-    // FIXME: This is an unfortunate consequence of there
-    //  being no serialization code for PartialDiagnostics and the fact
-    //  that serializing them would likely take a lot more storage than
-    //  just storing them as strings. We would still like, in the
-    //  future, to serialize the proper PartialDiagnostic as serializing
-    //  it as a string defeats the purpose of the diagnostic mechanism.
-    Satisfaction.Details.insert(
-        Satisfaction.Details.begin() + Size,
-        new (S.Context) ConstraintSubstitutionDiagnostic{
-            SubstDiag.first,
-            allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
+    consumeSFINAEFailure(Info, Satisfaction);
     return ExprError();
   }
 
@@ -1726,10 +1715,8 @@ bool Sema::EnsureTemplateArgumentListConstraints(
   llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
   TD->getAssociatedConstraints(AssociatedConstraints);
   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
-                                  TemplateIDRange, Satisfaction))
-    return true;
-
-  if (!Satisfaction.IsSatisfied) {
+                                  TemplateIDRange, Satisfaction) ||
+      !Satisfaction.IsSatisfied) {
     SmallString<128> TemplateArgString;
     TemplateArgString = " ";
     TemplateArgString += getTemplateArgumentBindingsText(
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index f177f0aa8645e..a554feae3dfb9 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3987,9 +3987,8 @@ TemplateDeductionResult 
Sema::FinishTemplateArgumentDeduction(
     if (CheckFunctionTemplateConstraints(
             Info.getLocation(),
             FunctionTemplate->getCanonicalDecl()->getTemplatedDecl(),
-            CTAI.CanonicalConverted, Info.AssociatedConstraintsSatisfaction))
-      return TemplateDeductionResult::MiscellaneousDeductionFailure;
-    if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+            CTAI.CanonicalConverted, Info.AssociatedConstraintsSatisfaction) ||
+        !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
       Info.reset(Info.takeSugared(), TemplateArgumentList::CreateCopy(
                                          Context, CTAI.CanonicalConverted));
       return TemplateDeductionResult::ConstraintsNotSatisfied;
@@ -4035,10 +4034,8 @@ TemplateDeductionResult 
Sema::FinishTemplateArgumentDeduction(
   if (IsLambda && !IsIncomplete) {
     if (CheckFunctionTemplateConstraints(
             Info.getLocation(), Specialization, CTAI.CanonicalConverted,
-            Info.AssociatedConstraintsSatisfaction))
-      return TemplateDeductionResult::MiscellaneousDeductionFailure;
-
-    if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+            Info.AssociatedConstraintsSatisfaction) ||
+        !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
       Info.reset(Info.takeSugared(), TemplateArgumentList::CreateCopy(
                                          Context, CTAI.CanonicalConverted));
       return TemplateDeductionResult::ConstraintsNotSatisfied;
diff --git 
a/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp 
b/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
index 15e00e4481e75..97c0d2e57c004 100644
--- 
a/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
+++ 
b/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
@@ -89,7 +89,9 @@ template<typename T> requires (T{}) // expected-error{{atomic 
constraint must be
 struct D { };
 
 static_assert(C<int>{}); // expected-note{{while checking constraint 
satisfaction for template 'C<int>' required here}}
+// expected-error@-1 {{constraints not satisfied for class template 'C'}}
 static_assert(D<int>{}); // expected-note{{while checking constraint 
satisfaction for template 'D<int>' required here}}
+// expected-error@-1 {{constraints not satisfied for class template 'D'}}
 
 // Test the delayed instantiation, the 'foo' implementation shouldn't cause the
 // constraint failure(or crash!) until the use to create 'y'.
diff --git a/clang/test/SemaCXX/cxx23-assume.cpp 
b/clang/test/SemaCXX/cxx23-assume.cpp
index a594a1a44337b..d2563c1c45107 100644
--- a/clang/test/SemaCXX/cxx23-assume.cpp
+++ b/clang/test/SemaCXX/cxx23-assume.cpp
@@ -129,6 +129,7 @@ struct F {
 template <typename T>
 constexpr int f5() requires C<T> { return 1; } // expected-note {{while 
checking the satisfaction}}
                                                // expected-note@-1 {{candidate 
template ignored}}
+                                               // expected-note@-2 {{because 
'T' does not satisfy 'C'}}
 
 template <typename T>
 constexpr int f5() requires (!C<T>) { return 2; } // expected-note 3 {{while 
checking the satisfaction}} \
diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp 
b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
index b7b03278da54e..d3e681f22ab26 100644
--- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
+++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
@@ -154,58 +154,84 @@ consteval int Or3() requires (C<typename T::type> || ... 
|| C<typename U::type>)
 static_assert(And1<>() == 1);
 static_assert(And1<S>() == 1);
 static_assert(And1<S, S>() == 1);
-// FIXME: The diagnostics are not so great
 static_assert(And1<int>() == 1); // expected-error {{no matching function for 
call to 'And1'}}
                                  // expected-note@#and1 {{candidate template 
ignored: constraints not satisfied [with T = <int>]}}
-                                 // expected-note@#and1 {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+                                 // expected-note@#and1 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                 // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                 // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 
 static_assert(And1<S, int>() == 1); // expected-error {{no matching function 
for call to 'And1'}}
                                    // expected-note@#and1 {{candidate template 
ignored: constraints not satisfied [with T = <S, int>]}}
-                                   // expected-note@#and1 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                   // expected-note@#and1 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                   // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                   // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+
 
 static_assert(And1<int, S>() == 1); // expected-error {{no matching function 
for call to 'And1'}}
                                    // expected-note@#and1 {{candidate template 
ignored: constraints not satisfied [with T = <int, S>]}}
-                                   // expected-note@#and1 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                   // expected-note@#and1 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                   // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                   // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+
 
 static_assert(And2<S>() == 2);
 static_assert(And2<S, S>() == 2);
 static_assert(And2<int>() == 2);  // expected-error {{no matching function for 
call to 'And2'}}
                                   // expected-note@#and2 {{candidate template 
ignored: constraints not satisfied [with T = int, U = <>]}}
-                                  // expected-note@#and2 {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+                                  // expected-note@#and2 {{because 'typename 
U::type' does not satisfy 'C'}}
+                                  // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                  // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+
 
 
 static_assert(And2<int, int>() == 2);  // expected-error {{no matching 
function for call to 'And2'}}
                                       // expected-note@#and2 {{candidate 
template ignored: constraints not satisfied [with T = S, U = <int>]}} \
-                                      // expected-note@#and2 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                      // expected-note@#and2 {{because 
'typename U::type' does not satisfy 'C'}}
+                                      // expected-note@#C {{because 'T' does 
not satisfy 'A'}}
+                                      // expected-note@#C {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+
 
 static_assert(And2<S, int>() == 2); // expected-error {{no matching function 
for call to 'And2'}}
                                    // expected-note@#and2 {{candidate template 
ignored: constraints not satisfied [with T = int, U = <S>]}}
-                                   // expected-note@#and2 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                   // expected-note@#and2 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                   // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                   // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+
 
 static_assert(And2<int, S>() == 2); // expected-error {{no matching function 
for call to 'And2'}}
                                    // expected-note@#and2 {{candidate template 
ignored: constraints not satisfied [with T = int, U = <int>]}}
-                                   // expected-note@#and2 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                   // expected-note@#and2 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                   // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                   // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 
 static_assert(And3<S>() == 3);
 static_assert(And3<S, S>() == 3);
 static_assert(And3<int>() == 3);   // expected-error {{no matching function 
for call to 'And3'}}
                                    // expected-note@#and3 {{candidate template 
ignored: constraints not satisfied [with T = int, U = <>]}}
-                                   // expected-note@#and3 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                   // expected-note@#and3 {{because 'typename 
U::type' does not satisfy 'C'}}
+                                   // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                   // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 
 
 static_assert(And3<int, int>() == 3);  // expected-error {{no matching 
function for call to 'And3'}}
                                       // expected-note@#and3 {{candidate 
template ignored: constraints not satisfied [with T = int, U = <int>]}}
-                                      // expected-note@#and3 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                      // expected-note@#and3 {{because 
'typename T::type' does not satisfy 'C'}}
+                                      // expected-note@#C {{because 'T' does 
not satisfy 'A'}}
+                                      // expected-note@#C {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
 
 
 static_assert(And3<S, int>() == 3); // expected-error {{no matching function 
for call to 'And3'}}
                                    // expected-note@#and3 {{candidate template 
ignored: constraints not satisfied [with T = S, U = <int>]}}
-                                   // expected-note@#and3 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                   // expected-note@#and3 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                   // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                   // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 
 
 static_assert(And3<int, S>() == 3); // expected-error {{no matching function 
for call to 'And3'}}
                                    // expected-note@#and3 {{candidate template 
ignored: constraints not satisfied [with T = int, U = <S>]}}
-                                   // expected-note@#and3 {{because 
substituted constraint expression is ill-formed: type 'int' cannot be used 
prior to '::' because it has no members}}
+                                   // expected-note@#and3 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                   // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                   // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 
 
 static_assert(Or1<>() == 1); // expected-error {{no matching function for call 
to 'Or1'}}
@@ -216,7 +242,9 @@ static_assert(Or1<S, int>() == 1);
 static_assert(Or1<S, S>() == 1);
 static_assert(Or1<int>() == 1); // expected-error {{no matching function for 
call to 'Or1'}}
                                 // expected-note@#or1 {{candidate template 
ignored: constraints not satisfied}}
-                                // expected-note@#or1 {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+                                // expected-note@#or1 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 
 static_assert(Or2<S>() == 2);
 static_assert(Or2<int, S>() == 2);
@@ -224,14 +252,18 @@ static_assert(Or2<S, int>() == 2);
 static_assert(Or2<S, S>() == 2);
 static_assert(Or2<int>() == 2); // expected-error {{no matching function for 
call to 'Or2'}}
                                 // expected-note@#or2 {{candidate template 
ignored: constraints not satisfied [with T = int, U = <>]}}
-                                // expected-note@#or2 {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+                                // expected-note@#or2 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 static_assert(Or3<S>() == 3);
 static_assert(Or3<int, S>() == 3);
 static_assert(Or3<S, int>() == 3);
 static_assert(Or3<S, S>() == 3);
 static_assert(Or3<int>() == 3); // expected-error {{no matching function for 
call to 'Or3'}}
                                 // expected-note@#or3 {{candidate template 
ignored: constraints not satisfied}}
-                                // expected-note@#or3 {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
+                                // expected-note@#or3 {{because 'typename 
T::type' does not satisfy 'C'}}
+                                // expected-note@#C {{because 'T' does not 
satisfy 'A'}}
+                                // expected-note@#C {{because substituted 
constraint expression is ill-formed: type 'int' cannot be used prior to '::' 
because it has no members}}
 }
 
 namespace bool_conversion_break {
@@ -655,6 +687,7 @@ void g() {
   f<char, int, short>();
   // expected-error@-1 {{no matching function}}
   // expected-note@#GH218548_f {{constraints not satisfied}}
+  // expected-note@#GH218548_f {{does not satisfy 'same_as_impl'}}
   // expected-note@#GH218548_f {{invalid index}}
 }
 
diff --git a/clang/test/SemaTemplate/concepts.cpp 
b/clang/test/SemaTemplate/concepts.cpp
index b37e856fe84d0..7b88489307d98 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1824,6 +1824,7 @@ namespace instantiation_dependent {
   template <class V> requires C<X<V&>> struct Y {};
   Y<void> y;
   // expected-error@-1 {{constraints not satisfied for class template 'Y' 
[with V = void]}}
+  // expected-note@-3  {{because 'X<V &>' (aka 'int') does not satisfy 'C'}} \
   // expected-note@-3  {{because substituted constraint expression is 
ill-formed: cannot form a reference to 'void'}}
 } // namespace instantiation_dependent
 
@@ -2069,6 +2070,9 @@ struct quantity {};
 
 auto x = quantity<reference<int>{}, int>{};
 // expected-error@-1 {{constraints not satisfied for class template 'quantity' 
[with V = reference<int>{}, $1 = int]}}
+// expected-note@-5 {{because 'representation_of<type-parameter-0-1, 
get_spec(V)>' evaluated to false}}
+// expected-note@-7 {{because 'decltype(V)' does not satisfy 'repr_impl'}}
+// expected-note@-7 {{because substituted constraint expression is ill-formed: 
non-type template argument is not a constant expression}}
 
 } // namespace CannotResolve1
 
diff --git a/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp 
b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
index 5809ef684bbf3..a2e0881e6c17e 100644
--- a/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
+++ b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
@@ -29,6 +29,7 @@ namespace constant_evaluated {
   // expected-note@-1{{in instantiation of}} expected-note@-1{{while 
substituting}}
   using s = S<int>;
   // expected-note@-1 {{while checking}}
+  // expected-error@-2 {{constraints not satisfied}}
   template<typename T> void foo() requires f<int[1]> { };
   // expected-note@-1{{in instantiation}} expected-note@-1{{while 
substituting}} \
      expected-note@-1{{candidate template ignored}}
diff --git a/clang/test/SemaTemplate/instantiate-requires-expr.cpp 
b/clang/test/SemaTemplate/instantiate-requires-expr.cpp
index a5a18acd069f3..979cc4dd1a7b9 100644
--- a/clang/test/SemaTemplate/instantiate-requires-expr.cpp
+++ b/clang/test/SemaTemplate/instantiate-requires-expr.cpp
@@ -235,6 +235,7 @@ template <class T> requires(T{})
 constexpr bool e_v = true;
 
 static_assert(e_v<bool>);
+// expected-error@-1 {{constraints not satisfied for variable template 'e_v'}}
 
 } // namespace GH73885
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to