[libcxx-commits] [clang] [libcxx] Revert "[clang] Reland: Instantiate concepts with sugared template arguments (#101782)" (PR #102551)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 8 16:21:23 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
This reverts commit 748371183ae769bfb485f1e7466a864bf1db93d5.
Reverted due to both regression reported on PR and #<!-- -->102253
---
Patch is 30.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/102551.diff
19 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+2-3)
- (modified) clang/include/clang/Sema/Template.h (+3-3)
- (modified) clang/lib/Sema/SemaConcept.cpp (+4-7)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+3-2)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+5-5)
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+8-8)
- (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+1-1)
- (modified) clang/test/AST/ast-dump-concepts.cpp (+4-6)
- (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp (+5-5)
- (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp (+1-1)
- (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp (+2-2)
- (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp (+6-6)
- (modified) clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp (+1-1)
- (modified) clang/test/CXX/temp/temp.param/p10-2a.cpp (+2-2)
- (modified) clang/test/SemaTemplate/concepts-recursive-inst.cpp (+6-6)
- (modified) clang/test/SemaTemplate/concepts.cpp (+2-2)
- (modified) clang/test/SemaTemplate/instantiate-requires-expr.cpp (+3-13)
- (modified) clang/test/SemaTemplate/pr52970.cpp (+1-1)
- (modified) libcxx/test/libcxx/algorithms/cpp17_iterator_concepts.verify.cpp (+1-1)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cb0a1b25e51c2a..7beef7be0e6a53 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -75,8 +75,8 @@ sections with improvements to Clang's support for those languages.
C++ Language Changes
--------------------
-- Allow single element access of GCC vector/ext_vector_type object to be
- constant expression. Supports the `V.xyzw` syntax and other tidbits
+- Allow single element access of GCC vector/ext_vector_type object to be
+ constant expression. Supports the `V.xyzw` syntax and other tidbits
as seen in OpenCL. Selecting multiple elements is left as a future work.
C++17 Feature Support
@@ -166,7 +166,6 @@ Improvements to Clang's diagnostics
- Clang now diagnoses undefined behavior in constant expressions more consistently. This includes invalid shifts, and signed overflow in arithmetic.
- -Wdangling-assignment-gsl is enabled by default.
-- Clang now does a better job preserving the template arguments as written when specializing concepts.
- Clang now always preserves the template arguments as written used
to specialize template type aliases.
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index d616865afe807e..0340c23fd170d6 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -234,8 +234,7 @@ enum class TemplateSubstitutionKind : char {
/// Replaces the current 'innermost' level with the provided argument list.
/// This is useful for type deduction cases where we need to get the entire
/// list from the AST, but then add the deduced innermost list.
- void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args,
- bool Final = false) {
+ void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
"Replacing in an empty list?");
@@ -247,7 +246,8 @@ enum class TemplateSubstitutionKind : char {
TemplateArgumentLists[0].Args = Args;
} else {
--NumRetainedOuterLevels;
- TemplateArgumentLists.push_back({{AssociatedDecl, Final}, Args});
+ TemplateArgumentLists.push_back(
+ {{AssociatedDecl, /*Final=*/false}, Args});
}
}
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index d4c9d044985e34..d1e62fb5cee623 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -414,8 +414,7 @@ DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
E->Profile(ID, S.Context, /*Canonical=*/true);
for (const auto &List : MLTAL)
for (const auto &TemplateArg : List.Args)
- S.Context.getCanonicalTemplateArgument(TemplateArg)
- .Profile(ID, S.Context);
+ TemplateArg.Profile(ID, S.Context);
// Note that we have to do this with our own collection, because there are
// times where a constraint-expression check can cause us to need to evaluate
@@ -643,8 +642,8 @@ bool Sema::CheckConstraintSatisfaction(
// here.
llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
for (auto List : TemplateArgsLists)
- for (const TemplateArgument &Arg : List.Args)
- FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
+ FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
+ List.Args.end());
llvm::FoldingSetNodeID ID;
ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
@@ -828,8 +827,6 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
- if (TemplateArgs)
- MLTAL.replaceInnermostTemplateArguments(FD, *TemplateArgs, /*Final=*/true);
if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
return std::nullopt;
@@ -1483,7 +1480,7 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
const ConceptSpecializationExpr *CSE) {
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
- /*Final=*/true, CSE->getTemplateArguments(),
+ /*Final=*/false, CSE->getTemplateArguments(),
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 1b56b4cabd133e..124435330ca104 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -9330,13 +9330,14 @@ Sema::BuildExprRequirement(
// be satisfied.
TemplateParameterList *TPL =
ReturnTypeRequirement.getTypeConstraintTemplateParameterList();
- QualType MatchedType = Context.getReferenceQualifiedType(E);
+ 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=*/true);
+ MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false);
MLTAL.addOuterRetainedLevels(TPL->getDepth());
const TypeConstraint *TC = Param->getTypeConstraint();
assert(TC && "Type Constraint cannot be null here");
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index cd3ee31fcca610..29e7978ba5b1f8 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4358,13 +4358,13 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
auto *CSD = ImplicitConceptSpecializationDecl::Create(
Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
- SugaredConverted);
+ CanonicalConverted);
ConstraintSatisfaction Satisfaction;
bool AreArgsDependent =
TemplateSpecializationType::anyDependentTemplateArguments(
- *TemplateArgs, SugaredConverted);
- MultiLevelTemplateArgumentList MLTAL(NamedConcept, SugaredConverted,
- /*Final=*/true);
+ *TemplateArgs, CanonicalConverted);
+ MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
+ /*Final=*/false);
LocalInstantiationScope Scope(*this);
EnterExpressionEvaluationContext EECtx{
@@ -5583,7 +5583,7 @@ bool Sema::CheckTemplateArgumentList(
CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr);
MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
- Template, NewContext, /*Final=*/true, SugaredConverted,
+ Template, NewContext, /*Final=*/false, CanonicalConverted,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConceptInstantiation=*/true);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 978f1a9dc1a933..e9705ec43d86cc 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3078,7 +3078,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
// If we don't need to replace the deduced template arguments,
// we can add them immediately as the inner-most argument list.
if (!DeducedArgsNeedReplacement(Template))
- Innermost = SugaredDeducedArgs;
+ Innermost = CanonicalDeducedArgs;
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
Template, Template->getDeclContext(), /*Final=*/false, Innermost,
@@ -3090,7 +3090,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
// not class-scope explicit specialization, so replace with Deduced Args
// instead of adding to inner-most.
if (!Innermost)
- MLTAL.replaceInnermostTemplateArguments(Template, SugaredDeducedArgs);
+ MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
Info.getLocation(),
@@ -3913,13 +3913,13 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
(CanonicalBuilder.size() ==
FunctionTemplate->getTemplateParameters()->size())) {
if (CheckInstantiatedFunctionTemplateConstraints(
- Info.getLocation(), Specialization, SugaredBuilder,
+ Info.getLocation(), Specialization, CanonicalBuilder,
Info.AssociatedConstraintsSatisfaction))
return TemplateDeductionResult::MiscellaneousDeductionFailure;
if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
- Info.reset(TemplateArgumentList::CreateCopy(Context, SugaredBuilder),
- Info.takeCanonical());
+ Info.reset(Info.takeSugared(),
+ TemplateArgumentList::CreateCopy(Context, CanonicalBuilder));
return TemplateDeductionResult::ConstraintsNotSatisfied;
}
}
@@ -4993,8 +4993,8 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
/*PartialTemplateArgs=*/false,
SugaredConverted, CanonicalConverted))
return true;
- MultiLevelTemplateArgumentList MLTAL(Concept, SugaredConverted,
- /*Final=*/true);
+ MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted,
+ /*Final=*/false);
// Build up an EvaluationContext with an ImplicitConceptSpecializationDecl so
// that the template arguments of the constraint can be preserved. For
// example:
@@ -5008,7 +5008,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
S, Sema::ExpressionEvaluationContext::Unevaluated,
ImplicitConceptSpecializationDecl::Create(
S.getASTContext(), Concept->getDeclContext(), Concept->getLocation(),
- SugaredConverted));
+ CanonicalConverted));
if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
MLTAL, TypeLoc.getLocalSourceRange(),
Satisfaction))
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index fcf1579d86dda7..c118f3818467d9 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2391,7 +2391,7 @@ void ASTDeclReader::VisitImplicitConceptSpecializationDecl(
VisitDecl(D);
llvm::SmallVector<TemplateArgument, 4> Args;
for (unsigned I = 0; I < D->NumTemplateArgs; ++I)
- Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/false));
+ Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/true));
D->setTemplateArguments(Args);
}
diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp
index 4b8e9026b2916b..a5e0673c241ef4 100644
--- a/clang/test/AST/ast-dump-concepts.cpp
+++ b/clang/test/AST/ast-dump-concepts.cpp
@@ -20,9 +20,8 @@ struct Foo {
// CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'binary_concept'
// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:13, col:31> 'bool' Concept {{.*}} 'binary_concept'
// CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:13:9> col:9
- // CHECK-NEXT: | |-TemplateArgument type 'R'
- // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0
- // CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'R'
+ // CHECK-NEXT: | |-TemplateArgument type 'type-parameter-1-0'
+ // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent {{.*}}depth 1 index 0
// CHECK-NEXT: | `-TemplateArgument type 'int'
// CHECK-NEXT: | `-BuiltinType {{.*}} 'int'
// CHECK-NEXT: |-TemplateArgument {{.*}} type 'R'
@@ -36,9 +35,8 @@ struct Foo {
// CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'unary_concept'
// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:13> 'bool'
// CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:10:9> col:9
- // CHECK-NEXT: | `-TemplateArgument type 'R'
- // CHECK-NEXT: | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0
- // CHECK-NEXT: | `-TemplateTypeParm {{.*}} 'R'
+ // CHECK-NEXT: | `-TemplateArgument type 'type-parameter-1-0'
+ // CHECK-NEXT: | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent {{.*}}depth 1 index 0
template <unary_concept R>
Foo(R);
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp
index 3d6f0b11fa99c9..dc0e84280e0567 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp
@@ -35,14 +35,14 @@ using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class templ
using r2i3 = r2<D>;
using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}}
-template<typename T> requires requires { { sizeof(T) }; } // expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'class nonexistent'}}
+template<typename T> requires requires { { sizeof(T) }; } // expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}}
struct r3 {};
using r3i1 = r3<int>;
using r3i2 = r3<A>;
using r3i3 = r3<A &>;
using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}}
-using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = class nonexistent]}}
+using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}}
// Non-dependent expressions
@@ -149,7 +149,7 @@ namespace std_example {
template<typename T> constexpr bool is_same_v<T, T> = true;
template<typename T, typename U> concept same_as = is_same_v<T, U>;
- // expected-note at -1 {{because 'is_same_v<int, typename T2::inner>' evaluated to false}}
+ // expected-note at -1 {{because 'is_same_v<int, int *>' evaluated to false}}
static_assert(C1<int>);
static_assert(C1<int*>);
@@ -173,9 +173,9 @@ namespace std_example {
int operator *() { return 0; }
};
static_assert(C2<T1>);
- template<C2 T> struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'T2' does not satisfy 'C2'}}
+ template<C2 T> struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'std_example::T2' does not satisfy 'C2'}}
using c2c1 = C2_check<int>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = int]}}
- using c2c2 = C2_check<T2>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = T2]}}
+ using c2c2 = C2_check<T2>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::T2]}}
template<typename T>
void g(T t) noexcept(sizeof(T) == 1) {}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
index 00ac9d0422d67e..763d983d20f615 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
@@ -27,7 +27,7 @@ using r4i = X<void>::r4<int>; // expected-error{{constraints not satisfied for c
// C++ [expr.prim.req.nested] Examples
namespace std_example {
- template<typename U> concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(decltype(+t)) == 1' (4 == 1) evaluated to false}}
+ template<typename U> concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(int) == 1' (4 == 1) evaluated to false}}
template<typename T> concept D =
requires (T t) {
requires C1<decltype (+t)>; // expected-note{{because 'decltype(+t)' (aka 'int') does not satisfy 'C1'}}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
index abfadfa3488411..7515f5c62d5ea8 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
@@ -39,14 +39,14 @@ using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class
template<typename T> requires requires { sizeof(T); }
// expected-note at -1{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}}
-// expected-note at -2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'class nonexistent'}}
+// expected-note at -2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}}
struct r3 {};
using r3i1 = r3<int>;
using r3i2 = r3<A>;
using r3i3 = r3<A &>;
using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}}
-using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = class nonexistent]}}
+using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}}
template<typename T> requires requires (T t) { 0; "a"; (void)'a'; }
struct r4 {};
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
index 28dff336d053c6..5433cfb21955dd 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
@@ -182,14 +182,14 @@ namespace std_example {
static_assert(C1<has_inner_and_type> && C2<has_inner_and_type> && C3<has_inner_and_type>);
template<C1 T> struct C1_check {};
// expected-note at -1 {{because 'int' does not satisfy 'C1'}}
- // expected-note at -2 {{because 'has_type' does not satisfy 'C1'}}
+ // expected-note at -2 {{because 'std_example::has_type' does not satisfy 'C1'}}
template<C2 T> struct C2_check {};
- // expected-note at -1 {{because 'has_inner' does not satisfy 'C2'}}
+ // expected-note at -1 {{because 'std_example::has_inner' does not satisfy 'C2'}}
template<C3 T> struct C3_check {};
// expected-note at -1 {{because 'void' does not satisfy 'C3'}}
using c1 = C1_check<int>; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = int]}}
- using c2 = C1_check<has_type>; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = has_type]}}
- using c3 = C2_check<has_inner>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = has_inner]}}
+ using c2 = C1_check<has_type>; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = std_example::has_type]}}
+ using c3 = C2_check<has_inner>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}}
using c4 = C3_check<void>; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}}
}
@@ -199,10 +199,10 @@ template <typename T> concept C = requires { requires requires { T::a; }; };
// expected-note at -1 {{because 'T::a' would be invalid: no member named 'a' in 'PR48656::T1'}}
template <C...> struct A {};
-// expected-note at -1 {{because 'T1' does not satisfy 'C'}}
+// expected-note at -1 {{because 'PR48656::T1' does not satisfy 'C'}}
struct T1 {};
-template struct A<T1>; // expected-error {{constraints not satisfied for class template 'A' [with $0 = <T1>...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/102551
More information about the libcxx-commits
mailing list