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. (cherry picked from commit 3129a2ed6a764c0687efaca9eba53dcf12d1d8a0)
This commit is contained in:
parent
98baaa1756
commit
f30caf1bda
2 changed files with 70 additions and 1 deletions
|
@ -2951,7 +2951,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
|
|||
-Wredundant-move warning. */
|
||||
suppress_warning (result, OPT_Wpessimizing_move);
|
||||
|
||||
if (cfun)
|
||||
if (cfun && cp_function_chain && !cp_unevaluated_operand)
|
||||
{
|
||||
bool abnormal = true;
|
||||
for (lkp_iterator iter (maybe_get_fns (fn)); iter; ++iter)
|
||||
|
|
69
gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C
Normal file
69
gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C
Normal file
|
@ -0,0 +1,69 @@
|
|||
// PR c++/115561
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
template<typename _Tp>
|
||||
auto declval() noexcept -> _Tp&&;
|
||||
|
||||
template<bool, typename _Tp = void>
|
||||
struct enable_if
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
struct enable_if<true, _Tp>
|
||||
{ using type = _Tp; };
|
||||
|
||||
template<bool _Cond, typename _Tp = void>
|
||||
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
|
||||
|
||||
template<typename _Tp>
|
||||
struct is_void
|
||||
{ static constexpr bool value = false; };
|
||||
|
||||
template<typename Fun, typename... Args>
|
||||
using invoke_result_t =
|
||||
decltype(declval<Fun>()(declval<Args>()...));
|
||||
|
||||
template<typename R>
|
||||
using iter_reference_t = decltype(*declval<R &>());
|
||||
|
||||
struct iter_move_fn
|
||||
{
|
||||
template<typename I>
|
||||
constexpr
|
||||
auto operator() (I &&i) -> void;
|
||||
} iter_move;
|
||||
|
||||
template<typename I>
|
||||
using iter_rvalue_reference_t = decltype(iter_move(declval<I &>()));
|
||||
|
||||
template<class, class>
|
||||
concept same_as = true;
|
||||
|
||||
template<typename I>
|
||||
concept readable_concept_ =
|
||||
same_as<iter_rvalue_reference_t<I const>, iter_rvalue_reference_t<I>>;
|
||||
|
||||
template<typename I>
|
||||
concept indirectly_readable =
|
||||
readable_concept_<enable_if_t<true, I>>;
|
||||
|
||||
template<typename Fun, typename I>
|
||||
using indirect_result_t =
|
||||
enable_if_t<indirectly_readable<I>,
|
||||
invoke_result_t<Fun, iter_reference_t<I>>>;
|
||||
|
||||
template<typename I, typename Fun>
|
||||
concept transformable =
|
||||
(!is_void<indirect_result_t<Fun &, I>>::value);
|
||||
|
||||
template<typename I, typename Fun >
|
||||
requires transformable<I, Fun>
|
||||
constexpr void transform(I, Fun)
|
||||
{
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
struct B {};
|
||||
(void) transform((B*)nullptr, [](B) {return 0; });
|
||||
}
|
Loading…
Add table
Reference in a new issue