From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id E0AD53858D35; Tue, 31 Oct 2023 09:39:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E0AD53858D35 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1698745156; bh=cCH3cgE8TlZENEwV8mCxn2XMdTDHlsvv/VvPzav12pE=; h=From:To:Subject:Date:From; b=CKLhgDnXZ/M+tuo7LThh2NBHmxwC3eKpoWte5Kx/t2sl6bdWFMJ35YtQKmmw9MDsp 1fqnGzeDMsLZEeMpKAuo+DfWuD5mw15B0dkNxOIETDVwMvFW1Pn1KXBipG8UfuLE2G Esg0ROrwsuuTRH1+AKQzD1b3xH7vOOaqo3QKP3l0= From: "raffael at casagrande dot ch" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/112307] New: Segmentation fault with -O1 -fcode-hoisting Date: Tue, 31 Oct 2023 09:39:15 +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: 14.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: raffael at casagrande dot ch 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=3D112307 Bug ID: 112307 Summary: Segmentation fault with -O1 -fcode-hoisting Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: raffael at casagrande dot ch Target Milestone: --- *Affected Versions*: 10.0 - current (14.0.0 20231031). Earlier versions can= not compile the code because it uses c++20. *System*: Linux *Command Line*: g++ main.cc -std=3Dc++20 -O1 -fcode-hoisting *Compiler Output*: :48:87: warning: friend declaration 'bool operator=3D=3D(const EnumeratorRange::Sentinel&, const EnumeratorRange::Iterator&)' declares a non-template function [-Wnon-template-friend] 48 | friend auto operator=3D=3D(const Sentinel& /*unused*/, const It= erator& i) noexcept -> bool; |=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 ^~~~ :48:87: note: (if this is not what you intended, make sure the func= tion template has already been declared and add '<>' after the function name her= e) *Runtime Output*: Segmentation fault, "boundary" is printed many times. *Source File*: #include #include #include #include template class EnumeratorRange { public: struct Sentinel { Sentinel() noexcept =3D default; Sentinel(const Sentinel&) noexcept =3D default; Sentinel(Sentinel&&) noexcept =3D default; auto operator=3D(const Sentinel&) noexcept -> Sentinel& =3D default; auto operator=3D(Sentinel&&) noexcept -> Sentinel& =3D default; ~Sentinel() noexcept =3D default; }; class Iterator { public: using value_type =3D typename ENUMERATOR::value_type; using difference_type =3D std::ptrdiff_t; explicit Iterator(EnumeratorRange* range) : range_(range) {} Iterator() noexcept =3D default; Iterator(const Iterator&) =3D delete; Iterator(Iterator&&) noexcept =3D default; ~Iterator() noexcept =3D default; auto operator=3D(const Iterator&) =3D delete; auto operator=3D(Iterator&&) noexcept -> Iterator& =3D default; auto operator*() const noexcept { assert(!range_->end_reached_); return *range_->enumerator_; } auto operator++() noexcept -> Iterator& { assert(!range_->end_reached_); range_->end_reached_ =3D !range_->enumerator_.Next(); return *this; } auto operator++(int) noexcept -> void { ++*this; } private: EnumeratorRange* range_; friend auto operator=3D=3D(const Sentinel& /*unused*/, const Iterator& = i) noexcept -> bool; }; explicit EnumeratorRange(ENUMERATOR&& e) : enumerator_(std::move(e)), end_reached_(!enumerator_.Next()) {} auto begin() const noexcept { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) return Iterator(const_cast(this)); } auto end() const noexcept { return Sentinel(); } private: ENUMERATOR enumerator_; bool end_reached_; friend auto operator=3D=3D(const Sentinel&, const Iterator& i) noexcept -= > bool { return i.range_->end_reached_; } friend auto operator=3D=3D(const Iterator& i, const Sentinel& s) noexcept= -> bool { return s =3D=3D i; } friend auto operator!=3D(const Sentinel& s, const Iterator& i) noexcept -= > bool { return !(s =3D=3D i); } friend auto operator!=3D(const Iterator& i, const Sentinel& s) noexcept -= > bool { return !(s =3D=3D i); } }; class Intersection { public: auto Boundary() const noexcept -> bool { return is_boundary_; } private: bool is_boundary_ =3D true; }; class CompositeMesh { public: auto Intersections() const noexcept -> std::ranges::input_range auto; }; auto CompositeMesh::Intersections() const noexcept -> std::ranges::input_ra= nge auto { class Enumerator { public: using wrapped_range_t =3D decltype(std::views::single(Intersection())); explicit Enumerator(wrapped_range_t&& range) : range_(std::move(range)), begin_{} {} using value_type =3D Intersection; auto operator*() const noexcept -> value_type { return *begin_.value();= } auto Next() noexcept -> bool { if (!begin_.has_value()) { auto b =3D range_.begin(); bool result =3D (b !=3D range_.end()); begin_ =3D std::move(b); return result; } else { auto& b =3D *begin_; if ((*b).Boundary()) { std::cout << "boundary" << std::endl; } ++b; return b !=3D range_.end(); } } private: wrapped_range_t range_; std::optional> begin_; }; return EnumeratorRange(Enumerator(std::views::single(Intersection()))); } int main() { auto mesh =3D CompositeMesh(); decltype(auto) intersections =3D mesh.Intersections(); for (auto intersection : intersections) { } } *Additional Notes* - It works if we use `-O2` (which includes -fcode-hoisting) - Godbolt: https://godbolt.org/z/1PqTKz33Y - One can disable the following compiler options from `-O1` and still repro= duce the bug: -fno-auto-inc-dec -fno-branch-count-reg -fno-combine-stack-adjustm= ents -fno-compare-elim -fno-cprop-registers -fno-dce -fno-defer-pop -fno-delayed-branch -fno-dse -fno-forward-propagate -fno-if-conversion -fno-if-conversion2 -fno-inline-functions-called-once -fno-ipa-modref -fno-ipa-profile -fno-ipa-pure-const -fno-ipa-reference -fno-ipa-reference-addressable -fno-merge-constants -fno-move-loop-invarian= ts -fno-move-loop-stores -fno-omit-frame-pointer -fno-reorder-blocks -fno-shrink-wrap -fno-shrink-wrap-separate -fno-split-wide-types -fno-ssa-backprop -fno-ssa-phiopt -fno-tree-bit-ccp -fno-tree-ccp -fno-tree= -ch -fno-tree-coalesce-vars -fno-tree-copy-prop -fno-tree-dce -fno-tree-dominator-opts -fno-tree-phiprop -fno-tree-scev-cprop -fno-tree-s= ink -fno-tree-slsr -fno-tree-sra -fno-tree-ter -fno-unit-at-a-time=