diff mbox series

[pushed] c++: ICE with concept, local class, and lambda [PR115561]

Message ID 20240727202600.3933837-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: ICE with concept, local class, and lambda [PR115561] | expand

Commit Message

Jason Merrill July 27, 2024, 8:25 p.m. UTC
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

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.
---
 gcc/cp/semantics.cc                           |  2 +-
 .../g++.dg/cpp2a/concepts-lambda21.C          | 69 +++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C


base-commit: 928116e94a5a8a995dffd926af58abfa7286e78e
diff mbox series

Patch

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 0f122b839c5..a9abf32e01f 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2968,7 +2968,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)
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C
new file mode 100644
index 00000000000..8d701cd4bbc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C
@@ -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; });
+}