Skip to content

Commit b9a77b5

Browse files
author
Erich Keane
committed
[Concepts] Fix an assert when trying to form a recovery expr on a
concept When we failed the lookup of the function, we tried to form a RecoveryExpr that caused us to recursively re-check the same constraint, which caused us to try to double-insert the satisfaction into the cache. This patch makes us just return the inner-cached version instead. We DO end up double-evaluating thanks to the recovery-expr, but there isn't a good way around that.
1 parent 69b2b72 commit b9a77b5

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ Bug Fixes
260260
- Fix template arguments of pointer and reference not taking the type as
261261
part of their identity.
262262
`Issue 47136 <https://github.com/llvm/llvm-project/issues/47136>`_
263+
- Fix a crash when trying to form a recovery expression on a call inside a
264+
constraint, which re-evaluated the same constraint.
265+
`Issue 53213 <https://github.com/llvm/llvm-project/issues/53213>`_
266+
`Issue 45736 <https://github.com/llvm/llvm-project/issues/45736>`_
263267

264268
Improvements to Clang's diagnostics
265269
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaConcept.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,29 @@ bool Sema::CheckConstraintSatisfaction(
408408
OutSatisfaction = *Cached;
409409
return false;
410410
}
411+
411412
auto Satisfaction =
412413
std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
413414
if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
414415
ConvertedConstraints, TemplateArgsLists,
415416
TemplateIDRange, *Satisfaction)) {
416417
return true;
417418
}
419+
420+
if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
421+
// The evaluation of this constraint resulted in us trying to re-evaluate it
422+
// recursively. This isn't really possible, except we try to form a
423+
// RecoveryExpr as a part of the evaluation. If this is the case, just
424+
// return the 'cached' version (which will have the same result), and save
425+
// ourselves the extra-insert. If it ever becomes possible to legitimately
426+
// recursively check a constraint, we should skip checking the 'inner' one
427+
// above, and replace the cached version with this one, as it would be more
428+
// specific.
429+
OutSatisfaction = *Cached;
430+
return false;
431+
}
432+
433+
// Else we can simply add this satisfaction to the list.
418434
OutSatisfaction = *Satisfaction;
419435
// We cannot use InsertPos here because CheckConstraintSatisfaction might have
420436
// invalidated it.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify %s
2+
namespace GH53213 {
3+
template<typename T>
4+
concept c = requires(T t) { f(t); }; // #CDEF
5+
6+
auto f(c auto); // #FDEF
7+
8+
void g() {
9+
f(0);
10+
// expected-error@-1{{no matching function for call to 'f'}}
11+
// expected-note@#FDEF{{constraints not satisfied}}
12+
// expected-note@#FDEF{{because 'int' does not satisfy 'c'}}
13+
// expected-note@#CDEF{{because 'f(t)' would be invalid: no matching function for call to 'f'}}
14+
}
15+
} // namespace GH53213
16+
17+
namespace GH45736 {
18+
struct constrained;
19+
20+
template<typename T>
21+
struct type {
22+
};
23+
template<typename T>
24+
constexpr bool f(type<T>) {
25+
return true;
26+
}
27+
28+
template<typename T>
29+
concept matches = f(type<T>());
30+
31+
32+
struct constrained {
33+
template<typename U> requires matches<U>
34+
explicit constrained(U value) {
35+
}
36+
};
37+
38+
bool f(constrained const &) {
39+
return true;
40+
}
41+
42+
struct outer {
43+
constrained state;
44+
};
45+
46+
bool f(outer const & x) {
47+
return f(x.state);
48+
}
49+
} // namespace GH45736

0 commit comments

Comments
 (0)