Skip to content

Commit 87aa318

Browse files
committed
[clang] fix concepts crash on substitution failure during normalization
When substitution failed on the first constrained template argument (but only the first), we would assert / crash. Checking for failure was only being performed from the second constraint on. This changes it so the checking is performed in that case, and the code is also now simplified a little bit to hopefully avoid this confusion. Signed-off-by: Matheus Izvekov <[email protected]> Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D106907
1 parent 0c7cd4a commit 87aa318

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

clang/lib/Sema/SemaConcept.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -742,22 +742,15 @@ Optional<NormalizedConstraint>
742742
NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
743743
ArrayRef<const Expr *> E) {
744744
assert(E.size() != 0);
745-
auto First = fromConstraintExpr(S, D, E[0]);
746-
if (E.size() == 1)
747-
return First;
748-
auto Second = fromConstraintExpr(S, D, E[1]);
749-
if (!Second)
745+
auto Conjunction = fromConstraintExpr(S, D, E[0]);
746+
if (!Conjunction)
750747
return None;
751-
llvm::Optional<NormalizedConstraint> Conjunction;
752-
Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
753-
CCK_Conjunction);
754-
for (unsigned I = 2; I < E.size(); ++I) {
748+
for (unsigned I = 1; I < E.size(); ++I) {
755749
auto Next = fromConstraintExpr(S, D, E[I]);
756750
if (!Next)
757-
return llvm::Optional<NormalizedConstraint>{};
758-
NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
751+
return None;
752+
*Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
759753
std::move(*Next), CCK_Conjunction);
760-
*Conjunction = std::move(NewConjunction);
761754
}
762755
return Conjunction;
763756
}

clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,18 @@ namespace non_type_pack {
6767

6868
static_assert((foo<1>(), true));
6969
}
70+
71+
namespace PR47174 {
72+
// This checks that we don't crash with a failed substitution on the first constrained argument when
73+
// performing normalization.
74+
template <Bar2 T, True U>
75+
requires true struct S3; // expected-note {{template is declared here}}
76+
template <True T, True U>
77+
requires true struct S3<T, U>; // expected-error {{class template partial specialization is not more specialized than the primary template}}
78+
79+
// Same as above, for the second position (but this was already working).
80+
template <True T, Bar2 U>
81+
requires true struct S4; // expected-note {{template is declared here}}
82+
template <True T, True U>
83+
requires true struct S4<T, U>; // expected-error {{class template partial specialization is not more specialized than the primary template}}
84+
} // namespace PR47174

0 commit comments

Comments
 (0)