From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 953533990E8C; Thu, 6 Jun 2024 22:03:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 953533990E8C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1717711408; bh=OOzqLuKvSA0UkZqUXGEYwU8zLQoPbcy2foq8e6DtTg4=; h=From:To:Subject:Date:From; b=Q4FvaCmbslJxx+Vtn3a9aB29+nIADLrvD1Aa7UoFl/WMMqqb/27XtH0DEyZRJVTAZ tY7883WAfh5lydtEE+3odzh62S7VYPq7JPPImntSRgT6AypvSjHswfB2kD7jkmdAil n7w0K7YwFc/GpoVxDv8gYp9YlsioN8LFinJZ93wU= From: "eric.niebler at gmail dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/115378] New: [ice-on-valid] code using friend injection is crashing gcc since 14 Date: Thu, 06 Jun 2024 22:03:28 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 15.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: eric.niebler at gmail dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D115378 Bug ID: 115378 Summary: [ice-on-valid] code using friend injection is crashing gcc since 14 Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: eric.niebler at gmail dot com Target Milestone: --- the following valid code crashes gcc-14 and gcc-trunk. clang accepts it, as does gcc-13. see https://godbolt.org/z/s9frvq3Pv #include #include #include #include #include #include #include #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wunknown-warning-option" #pragma GCC diagnostic ignored "-Wnon-template-friend" #endif namespace std::execution { template concept __has_query =3D requires (const Env& __env, Args&&... __args) { __env.query(Query(), std::forward(__args)...); }; // specialization for key/value pairs template struct prop { [[no_unique_address]] Query __query; [[no_unique_address]] Value __value; [[nodiscard]] constexpr const Value & query(Query) const noexcept { return __value; } }; template prop(Query, Value) -> prop>; template struct __ref; template struct __ref { Env& __env; constexpr __ref(reference_wrapper __r) noexcept : __env(__r) {} template requires __has_query constexpr decltype(auto) query(Query __q, Args&&... args) const noexcept(noexcept(__env.query(__q, std::forward(args)...))) { return __env.query(__q, std::forward(args)...); } }; template struct __reader { friend auto __counted_flag(__reader); }; template struct __writer { friend auto __counted_flag(__reader) {} static constexpr size_t __n =3D N; }; template consteval auto __counter_impl() { constexpr bool __counted_past_value =3D requires(__reader __r) { __counted_flag(__r); }; if constexpr (__counted_past_value) { return __counter_impl(); } else { return __writer().__n; } } template()> constexpr auto __counter =3D Val; template struct __list; template struct __ignore { constexpr __ignore(auto&&) {} auto query(auto) const =3D delete; }; template using __wrap =3D conditional_t, __ref, Env>; template using _as_base_ =3D conditional_t, __igno= re>; template >> using _as_base =3D _as_base_; // utility for joining multiple environments template struct env : _as_base, Envs>... { template constexpr decltype(auto) __get_1st() const noexcept { constexpr bool __flags[] =3D {__has_query...}; constexpr size_t __idx =3D ranges::find(__flags, true) - __flags; auto __tup =3D tie(static_cast&>(*this)...); return get<__idx>(__tup); } template requires (__has_query ||...) constexpr decltype(auto) query(Query __q, Args&&... args) const noexcept(noexcept(__get_1st().query(__q, std::forward(args)...))) { return __get_1st().query(__q, std::forward(args)...); } }; template env(Envs...) -> env...>; } // std::execution // Test code: template struct get_value_t { auto operator()(const auto& env) const noexcept -> decltype(env.query(*th= is)) { static_assert(noexcept(env.query(*this))); return env.query(*this); } }; template inline constexpr get_value_t get_value{}; int main() { using namespace std::execution; // can create an environment out of a query and a value auto env1 =3D prop(get_value<0>, 42); auto val =3D get_value<0>(env1); assert(val =3D=3D 42); // can store a value by reference: int i =3D 42; auto env2 =3D prop(get_value<0>, std::ref(i)); int& j =3D get_value<0>(env2); ++j; assert(i =3D=3D 43); // Can create an env from several envs with duplicates. // Queries are resolved by asking the nested envs first to last. auto env3 =3D env(prop(get_value<0>, 42), prop(get_value<1>, 43), prop(get_value<1>, 44), prop(get_value<0>, 45), prop(get_value<0>, 46)); assert(get_value<0>(env3) =3D=3D 42); assert(get_value<1>(env3) =3D=3D 43); // nested envs can be held by reference also: auto env4 =3D env(prop(get_value<1>, 42), std::cref(env2)); assert(get_value<0>(env4) =3D=3D 43); assert(get_value<1>(env4) =3D=3D 42); }=