Skip to content

Commit 3129a2e

Browse files
committed
c++: ICE with concept, local class, and lambda [PR115561]
Here when we want to synthesize methods for foo()::B maybe_push_to_top_level calls push_function_context, which sets cfun to a dummy value; later finish_call_expr tries to set something in cp_function_chain (i.e. cfun->language), which isn't set. Many places in the compiler check cfun && cp_function_chain to avoid this problem; here we also want to check !cp_unevaluated_operand, like set_flags_from_callee does. PR c++/115561 gcc/cp/ChangeLog: * semantics.cc (finish_call_expr): Check cp_unevaluated_operand. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-lambda21.C: New test.
1 parent dab0f35 commit 3129a2e

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

Diff for: gcc/cp/semantics.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2968,7 +2968,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
29682968
-Wredundant-move warning. */
29692969
suppress_warning (result, OPT_Wpessimizing_move);
29702970

2971-
if (cfun)
2971+
if (cfun && cp_function_chain && !cp_unevaluated_operand)
29722972
{
29732973
bool abnormal = true;
29742974
for (lkp_iterator iter (maybe_get_fns (fn)); iter; ++iter)

Diff for: gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// PR c++/115561
2+
// { dg-do compile { target c++20 } }
3+
4+
template<typename _Tp>
5+
auto declval() noexcept -> _Tp&&;
6+
7+
template<bool, typename _Tp = void>
8+
struct enable_if
9+
{ };
10+
11+
template<typename _Tp>
12+
struct enable_if<true, _Tp>
13+
{ using type = _Tp; };
14+
15+
template<bool _Cond, typename _Tp = void>
16+
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
17+
18+
template<typename _Tp>
19+
struct is_void
20+
{ static constexpr bool value = false; };
21+
22+
template<typename Fun, typename... Args>
23+
using invoke_result_t =
24+
decltype(declval<Fun>()(declval<Args>()...));
25+
26+
template<typename R>
27+
using iter_reference_t = decltype(*declval<R &>());
28+
29+
struct iter_move_fn
30+
{
31+
template<typename I>
32+
constexpr
33+
auto operator() (I &&i) -> void;
34+
} iter_move;
35+
36+
template<typename I>
37+
using iter_rvalue_reference_t = decltype(iter_move(declval<I &>()));
38+
39+
template<class, class>
40+
concept same_as = true;
41+
42+
template<typename I>
43+
concept readable_concept_ =
44+
same_as<iter_rvalue_reference_t<I const>, iter_rvalue_reference_t<I>>;
45+
46+
template<typename I>
47+
concept indirectly_readable =
48+
readable_concept_<enable_if_t<true, I>>;
49+
50+
template<typename Fun, typename I>
51+
using indirect_result_t =
52+
enable_if_t<indirectly_readable<I>,
53+
invoke_result_t<Fun, iter_reference_t<I>>>;
54+
55+
template<typename I, typename Fun>
56+
concept transformable =
57+
(!is_void<indirect_result_t<Fun &, I>>::value);
58+
59+
template<typename I, typename Fun >
60+
requires transformable<I, Fun>
61+
constexpr void transform(I, Fun)
62+
{
63+
}
64+
65+
void foo()
66+
{
67+
struct B {};
68+
(void) transform((B*)nullptr, [](B) {return 0; });
69+
}

0 commit comments

Comments
 (0)