Skip to content

Commit d0a6de5

Browse files
committed
[clang] Instantiate concepts with sugared template arguments
Since we don't unique specializations for concepts, we can just instantiate them with the sugared template arguments, at negligible cost. If we don't track their specializations, we can't resugar them later anyway, and that would be more expensive than just instantiating them sugared in the first place since it would require an additional pass. Signed-off-by: Matheus Izvekov <[email protected]> Differential Revision: https://reviews.llvm.org/D136566
1 parent 4c44c91 commit d0a6de5

File tree

15 files changed

+160
-144
lines changed

15 files changed

+160
-144
lines changed

clang/lib/Sema/SemaConcept.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
10771077
TemplateArgumentList TAL{TemplateArgumentList::OnStack,
10781078
CSE->getTemplateArguments()};
10791079
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
1080-
CSE->getNamedConcept(), /*Final=*/false, &TAL,
1080+
CSE->getNamedConcept(), /*Final=*/true, &TAL,
10811081
/*RelativeToPrimary=*/true,
10821082
/*Pattern=*/nullptr,
10831083
/*ForConstraintInstantiation=*/true);

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 105 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,53 +1475,57 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
14751475
// C++2b:
14761476
// Otherwise, if the type contains a placeholder type, it is replaced by the
14771477
// type determined by placeholder type deduction.
1478-
DeducedType *Deduced = Ty->getContainedDeducedType();
1479-
if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) {
1480-
Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity,
1481-
Kind, Exprs);
1482-
if (Ty.isNull())
1483-
return ExprError();
1484-
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
1485-
} else if (Deduced) {
1486-
MultiExprArg Inits = Exprs;
1487-
if (ListInitialization) {
1488-
auto *ILE = cast<InitListExpr>(Exprs[0]);
1489-
Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits());
1490-
}
1478+
if (const DeducedType *Deduced = Ty->getContainedDeducedType();
1479+
Deduced && !Deduced->isDeduced()) {
1480+
if (isa<DeducedTemplateSpecializationType>(Deduced)) {
1481+
Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity, Kind,
1482+
Exprs);
1483+
if (Ty.isNull())
1484+
return ExprError();
1485+
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
1486+
} else {
1487+
assert(isa<AutoType>(Deduced));
1488+
MultiExprArg Inits = Exprs;
1489+
if (ListInitialization) {
1490+
auto *ILE = cast<InitListExpr>(Exprs[0]);
1491+
Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits());
1492+
}
14911493

1492-
if (Inits.empty())
1493-
return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_init_no_expression)
1494-
<< Ty << FullRange);
1495-
if (Inits.size() > 1) {
1496-
Expr *FirstBad = Inits[1];
1497-
return ExprError(Diag(FirstBad->getBeginLoc(),
1498-
diag::err_auto_expr_init_multiple_expressions)
1499-
<< Ty << FullRange);
1500-
}
1501-
if (getLangOpts().CPlusPlus2b) {
1502-
if (Ty->getAs<AutoType>())
1503-
Diag(TyBeginLoc, diag::warn_cxx20_compat_auto_expr) << FullRange;
1504-
}
1505-
Expr *Deduce = Inits[0];
1506-
if (isa<InitListExpr>(Deduce))
1507-
return ExprError(
1508-
Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces)
1509-
<< ListInitialization << Ty << FullRange);
1510-
QualType DeducedType;
1511-
TemplateDeductionInfo Info(Deduce->getExprLoc());
1512-
TemplateDeductionResult Result =
1513-
DeduceAutoType(TInfo->getTypeLoc(), Deduce, DeducedType, Info);
1514-
if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed)
1515-
return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_deduction_failure)
1516-
<< Ty << Deduce->getType() << FullRange
1517-
<< Deduce->getSourceRange());
1518-
if (DeducedType.isNull()) {
1519-
assert(Result == TDK_AlreadyDiagnosed);
1520-
return ExprError();
1521-
}
1494+
if (Inits.empty())
1495+
return ExprError(
1496+
Diag(TyBeginLoc, diag::err_auto_expr_init_no_expression)
1497+
<< Ty << FullRange);
1498+
if (Inits.size() > 1) {
1499+
Expr *FirstBad = Inits[1];
1500+
return ExprError(Diag(FirstBad->getBeginLoc(),
1501+
diag::err_auto_expr_init_multiple_expressions)
1502+
<< Ty << FullRange);
1503+
}
1504+
if (getLangOpts().CPlusPlus2b) {
1505+
if (Ty->getAs<AutoType>())
1506+
Diag(TyBeginLoc, diag::warn_cxx20_compat_auto_expr) << FullRange;
1507+
}
1508+
Expr *Deduce = Inits[0];
1509+
if (isa<InitListExpr>(Deduce))
1510+
return ExprError(
1511+
Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces)
1512+
<< ListInitialization << Ty << FullRange);
1513+
QualType DeducedType;
1514+
TemplateDeductionInfo Info(Deduce->getExprLoc());
1515+
TemplateDeductionResult Result =
1516+
DeduceAutoType(TInfo->getTypeLoc(), Deduce, DeducedType, Info);
1517+
if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed)
1518+
return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_deduction_failure)
1519+
<< Ty << Deduce->getType() << FullRange
1520+
<< Deduce->getSourceRange());
1521+
if (DeducedType.isNull()) {
1522+
assert(Result == TDK_AlreadyDiagnosed);
1523+
return ExprError();
1524+
}
15221525

1523-
Ty = DeducedType;
1524-
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
1526+
Ty = DeducedType;
1527+
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
1528+
}
15251529
}
15261530

15271531
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
@@ -2011,59 +2015,62 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
20112015
DirectInitRange.getEnd());
20122016

20132017
// C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
2014-
auto *Deduced = AllocType->getContainedDeducedType();
2015-
if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) {
2016-
if (ArraySize)
2017-
return ExprError(
2018-
Diag(*ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(),
2019-
diag::err_deduced_class_template_compound_type)
2020-
<< /*array*/ 2
2021-
<< (*ArraySize ? (*ArraySize)->getSourceRange() : TypeRange));
2018+
if (const DeducedType *Deduced = AllocType->getContainedDeducedType();
2019+
Deduced && !Deduced->isDeduced()) {
2020+
if (isa<DeducedTemplateSpecializationType>(Deduced)) {
2021+
if (ArraySize)
2022+
return ExprError(
2023+
Diag(*ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(),
2024+
diag::err_deduced_class_template_compound_type)
2025+
<< /*array*/ 2
2026+
<< (*ArraySize ? (*ArraySize)->getSourceRange() : TypeRange));
2027+
2028+
InitializedEntity Entity =
2029+
InitializedEntity::InitializeNew(StartLoc, AllocType);
2030+
AllocType = DeduceTemplateSpecializationFromInitializer(
2031+
AllocTypeInfo, Entity, Kind, Exprs);
2032+
if (AllocType.isNull())
2033+
return ExprError();
2034+
} else {
2035+
assert(isa<AutoType>(Deduced));
2036+
MultiExprArg Inits = Exprs;
2037+
bool Braced = (initStyle == CXXNewExpr::ListInit);
2038+
if (Braced) {
2039+
auto *ILE = cast<InitListExpr>(Exprs[0]);
2040+
Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits());
2041+
}
20222042

2023-
InitializedEntity Entity
2024-
= InitializedEntity::InitializeNew(StartLoc, AllocType);
2025-
AllocType = DeduceTemplateSpecializationFromInitializer(
2026-
AllocTypeInfo, Entity, Kind, Exprs);
2027-
if (AllocType.isNull())
2028-
return ExprError();
2029-
} else if (Deduced) {
2030-
MultiExprArg Inits = Exprs;
2031-
bool Braced = (initStyle == CXXNewExpr::ListInit);
2032-
if (Braced) {
2033-
auto *ILE = cast<InitListExpr>(Exprs[0]);
2034-
Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits());
2035-
}
2036-
2037-
if (initStyle == CXXNewExpr::NoInit || Inits.empty())
2038-
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
2039-
<< AllocType << TypeRange);
2040-
if (Inits.size() > 1) {
2041-
Expr *FirstBad = Inits[1];
2042-
return ExprError(Diag(FirstBad->getBeginLoc(),
2043-
diag::err_auto_new_ctor_multiple_expressions)
2044-
<< AllocType << TypeRange);
2045-
}
2046-
if (Braced && !getLangOpts().CPlusPlus17)
2047-
Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init)
2048-
<< AllocType << TypeRange;
2049-
Expr *Deduce = Inits[0];
2050-
if (isa<InitListExpr>(Deduce))
2051-
return ExprError(
2052-
Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces)
2053-
<< Braced << AllocType << TypeRange);
2054-
QualType DeducedType;
2055-
TemplateDeductionInfo Info(Deduce->getExprLoc());
2056-
TemplateDeductionResult Result =
2057-
DeduceAutoType(AllocTypeInfo->getTypeLoc(), Deduce, DeducedType, Info);
2058-
if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed)
2059-
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
2060-
<< AllocType << Deduce->getType() << TypeRange
2061-
<< Deduce->getSourceRange());
2062-
if (DeducedType.isNull()) {
2063-
assert(Result == TDK_AlreadyDiagnosed);
2064-
return ExprError();
2043+
if (initStyle == CXXNewExpr::NoInit || Inits.empty())
2044+
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
2045+
<< AllocType << TypeRange);
2046+
if (Inits.size() > 1) {
2047+
Expr *FirstBad = Inits[1];
2048+
return ExprError(Diag(FirstBad->getBeginLoc(),
2049+
diag::err_auto_new_ctor_multiple_expressions)
2050+
<< AllocType << TypeRange);
2051+
}
2052+
if (Braced && !getLangOpts().CPlusPlus17)
2053+
Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init)
2054+
<< AllocType << TypeRange;
2055+
Expr *Deduce = Inits[0];
2056+
if (isa<InitListExpr>(Deduce))
2057+
return ExprError(
2058+
Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces)
2059+
<< Braced << AllocType << TypeRange);
2060+
QualType DeducedType;
2061+
TemplateDeductionInfo Info(Deduce->getExprLoc());
2062+
TemplateDeductionResult Result = DeduceAutoType(
2063+
AllocTypeInfo->getTypeLoc(), Deduce, DeducedType, Info);
2064+
if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed)
2065+
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
2066+
<< AllocType << Deduce->getType() << TypeRange
2067+
<< Deduce->getSourceRange());
2068+
if (DeducedType.isNull()) {
2069+
assert(Result == TDK_AlreadyDiagnosed);
2070+
return ExprError();
2071+
}
2072+
AllocType = DeducedType;
20652073
}
2066-
AllocType = DeducedType;
20672074
}
20682075

20692076
// Per C++0x [expr.new]p5, the type being constructed may be a
@@ -8956,16 +8963,15 @@ Sema::BuildExprRequirement(
89568963
// be satisfied.
89578964
TemplateParameterList *TPL =
89588965
ReturnTypeRequirement.getTypeConstraintTemplateParameterList();
8959-
QualType MatchedType =
8960-
Context.getReferenceQualifiedType(E).getCanonicalType();
8966+
QualType MatchedType = Context.getReferenceQualifiedType(E);
89618967
llvm::SmallVector<TemplateArgument, 1> Args;
89628968
Args.push_back(TemplateArgument(MatchedType));
89638969

89648970
auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
89658971

89668972
TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args);
89678973
MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray(),
8968-
/*Final=*/false);
8974+
/*Final=*/true);
89698975
MLTAL.addOuterRetainedLevels(TPL->getDepth());
89708976
Expr *IDC = Param->getTypeConstraint()->getImmediatelyDeclaredConstraint();
89718977
ExprResult Constraint = SubstExpr(IDC, MLTAL);

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4861,13 +4861,13 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
48614861

48624862
auto *CSD = ImplicitConceptSpecializationDecl::Create(
48634863
Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
4864-
CanonicalConverted);
4864+
SugaredConverted);
48654865
ConstraintSatisfaction Satisfaction;
48664866
bool AreArgsDependent =
48674867
TemplateSpecializationType::anyDependentTemplateArguments(
4868-
*TemplateArgs, CanonicalConverted);
4869-
MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
4870-
/*Final=*/false);
4868+
*TemplateArgs, SugaredConverted);
4869+
MultiLevelTemplateArgumentList MLTAL(NamedConcept, SugaredConverted,
4870+
/*Final=*/true);
48714871
LocalInstantiationScope Scope(*this);
48724872

48734873
EnterExpressionEvaluationContext EECtx{
@@ -6098,7 +6098,7 @@ bool Sema::CheckTemplateArgumentList(
60986098

60996099
if (!PartialTemplateArgs) {
61006100
TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack,
6101-
CanonicalConverted);
6101+
SugaredConverted);
61026102
// Setup the context/ThisScope for the case where we are needing to
61036103
// re-instantiate constraints outside of normal instantiation.
61046104
DeclContext *NewContext = Template->getDeclContext();
@@ -6118,7 +6118,7 @@ bool Sema::CheckTemplateArgumentList(
61186118
CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr);
61196119

61206120
MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
6121-
Template, /*Final=*/false, &StackTemplateArgs,
6121+
Template, /*Final=*/true, &StackTemplateArgs,
61226122
/*RelativeToPrimary=*/true,
61236123
/*Pattern=*/nullptr,
61246124
/*ForConceptInstantiation=*/true);

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2886,10 +2886,10 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
28862886

28872887
bool NeedsReplacement = DeducedArgsNeedReplacement(Template);
28882888
TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack,
2889-
CanonicalDeducedArgs};
2889+
SugaredDeducedArgs};
28902890

28912891
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
2892-
Template, /*Final=*/false,
2892+
Template, /*Final=*/true,
28932893
/*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL,
28942894
/*RelativeToPrimary=*/true, /*Pattern=*/
28952895
nullptr, /*ForConstraintInstantiation=*/true);
@@ -2899,7 +2899,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
28992899
// not class-scope explicit specialization, so replace with Deduced Args
29002900
// instead of adding to inner-most.
29012901
if (NeedsReplacement)
2902-
MLTAL.replaceInnermostTemplateArguments(CanonicalDeducedArgs);
2902+
MLTAL.replaceInnermostTemplateArguments(SugaredDeducedArgs);
29032903

29042904
if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
29052905
Info.getLocation(),
@@ -4672,8 +4672,8 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
46724672
/*PartialTemplateArgs=*/false,
46734673
SugaredConverted, CanonicalConverted))
46744674
return true;
4675-
MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted,
4676-
/*Final=*/false);
4675+
MultiLevelTemplateArgumentList MLTAL(Concept, SugaredConverted,
4676+
/*Final=*/true);
46774677
if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
46784678
MLTAL, TypeLoc.getLocalSourceRange(),
46794679
Satisfaction))

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,7 @@ void ASTDeclReader::VisitImplicitConceptSpecializationDecl(
22432243
VisitDecl(D);
22442244
llvm::SmallVector<TemplateArgument, 4> Args;
22452245
for (unsigned I = 0; I < D->NumTemplateArgs; ++I)
2246-
Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/true));
2246+
Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/false));
22472247
D->setTemplateArguments(Args);
22482248
}
22492249

clang/test/AST/ast-dump-concepts.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ struct Foo {
2020
// CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'binary_concept'
2121
// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:13, col:31> 'bool' Concept {{.*}} 'binary_concept'
2222
// CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:13:9> col:9
23-
// CHECK-NEXT: | |-TemplateArgument type 'type-parameter-1-0'
24-
// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent {{.*}}depth 1 index 0
23+
// CHECK-NEXT: | |-TemplateArgument type 'R'
24+
// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0
25+
// CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'R'
2526
// CHECK-NEXT: | `-TemplateArgument type 'int'
2627
// CHECK-NEXT: | `-BuiltinType {{.*}} 'int'
2728
// CHECK-NEXT: |-TemplateArgument {{.*}} type 'R'
@@ -35,8 +36,9 @@ struct Foo {
3536
// CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'unary_concept'
3637
// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:13> 'bool'
3738
// CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:10:9> col:9
38-
// CHECK-NEXT: | `-TemplateArgument type 'type-parameter-1-0'
39-
// CHECK-NEXT: | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent {{.*}}depth 1 index 0
39+
// CHECK-NEXT: | `-TemplateArgument type 'R'
40+
// CHECK-NEXT: | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0
41+
// CHECK-NEXT: | `-TemplateTypeParm {{.*}} 'R'
4042
template <unary_concept R>
4143
Foo(R);
4244

clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class templ
3535
using r2i3 = r2<D>;
3636
using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}}
3737

38-
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'}}
38+
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'}}
3939
struct r3 {};
4040

4141
using r3i1 = r3<int>;
4242
using r3i2 = r3<A>;
4343
using r3i3 = r3<A &>;
4444
using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}}
45-
using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}}
45+
using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = class nonexistent]}}
4646

4747
// Non-dependent expressions
4848

@@ -149,7 +149,7 @@ namespace std_example {
149149
template<typename T> constexpr bool is_same_v<T, T> = true;
150150

151151
template<typename T, typename U> concept same_as = is_same_v<T, U>;
152-
// expected-note@-1 {{because 'is_same_v<int, int *>' evaluated to false}}
152+
// expected-note@-1 {{because 'is_same_v<int, typename T2::inner>' evaluated to false}}
153153

154154
static_assert(C1<int>);
155155
static_assert(C1<int*>);
@@ -173,9 +173,9 @@ namespace std_example {
173173
int operator *() { return 0; }
174174
};
175175
static_assert(C2<T1>);
176-
template<C2 T> struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'std_example::T2' does not satisfy 'C2'}}
176+
template<C2 T> struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'T2' does not satisfy 'C2'}}
177177
using c2c1 = C2_check<int>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = int]}}
178-
using c2c2 = C2_check<T2>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::T2]}}
178+
using c2c2 = C2_check<T2>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = T2]}}
179179

180180
template<typename T>
181181
void g(T t) noexcept(sizeof(T) == 1) {}

clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ using r4i = X<void>::r4<int>; // expected-error{{constraints not satisfied for c
2727

2828
// C++ [expr.prim.req.nested] Examples
2929
namespace std_example {
30-
template<typename U> concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(int) == 1' (4 == 1) evaluated to false}}
30+
template<typename U> concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(decltype(+t)) == 1' (4 == 1) evaluated to false}}
3131
template<typename T> concept D =
3232
requires (T t) {
3333
requires C1<decltype (+t)>; // expected-note{{because 'decltype(+t)' (aka 'int') does not satisfy 'C1'}}

0 commit comments

Comments
 (0)