[{"id":3679267,"web_url":"http://patchwork.ozlabs.org/comment/3679267/","msgid":"<CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>","list_archive_url":null,"date":"2026-04-20T07:25:50","subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","submitter":{"id":90409,"url":"http://patchwork.ozlabs.org/api/people/90409/","name":"Tomasz Kamiński","email":"tkaminsk@redhat.com"},"content":"On Sun, Apr 19, 2026 at 1:28 AM Patrick Palka <ppalka@redhat.com> wrote:\n\n> Changes in v2:\n>   - Added code comment\n>   - Clarified commit message, removed red herring about trivial\n>     destructibility.\n>   - Extended test with 'x6' direct-initialization that avoids invoking\n>     optional's move constructor.  This testcase, when instantiated with\n> T=B,\n>     demonstrates that non-trivially-copyable optional is also affected\n>     and we must set _M_empty even in that case.\n>\n> -- >8 --\n>\n> When an optional that contains a value is cleared, _M_destroy invokes the\n> destructor of the contained value _Storage::_M_value, leaving the union\n> _Storage without an active member.  While this is benign at runtime, a\n> union suboject with no active member violates core constant expression\n> requirements and in turn an optional in this state can't be used as a\n> constant initializer, which Clang and recent GCC (since r16-3022) correctly\n> diagnose.\n>\nI am not aware of this limitation, and I do not see how if fails out of the\nwording,\nThe constituent values explicitly exclude inactive union members:\nhttps://eel.is/c++draft/intro.object#12.2, so empty union simply has none.\n\nCould you please update the commit description, to reflect actual problem\nas described by Jason here:\nhttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=124910#c13\n\n\n\n>\n> To fix this, this patch makes _M_destroy activate the dummy union member\n> _M_empty after destroying _M_value to ensure that the union always has\n> an active member throughout its lifetime.  We use std::construct_at\n> instead of simple assignment to work around a front end bug (comment #3\n> in the PR).  Doing so means we don't activate the member in C++17 mode,\n> which should be fine; I don't think it's possible to disengage an engaged\n> optional using only the C++17 constexpr optional operations.\n>\n>         PR c++/124910\n>\n> libstdc++-v3/ChangeLog:\n>\n>         * include/std/optional (_Optional_payload_base::_M_destroy)\n>         [__cpp_lib_optional >= 202106L]: During constant evaluation,\n>         after invoking destructor of _M_value, use construct_at to\n>         activate _M_empty.\n>         * testsuite/20_util/optional/constexpr/124910.cc: New test.\n>\n> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>\n> ---\n>  libstdc++-v3/include/std/optional             |  6 ++\n>  .../20_util/optional/constexpr/124910.cc      | 74 +++++++++++++++++++\n>  2 files changed, 80 insertions(+)\n>  create mode 100644\n> libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>\n> diff --git a/libstdc++-v3/include/std/optional\n> b/libstdc++-v3/include/std/optional\n> index 0f4cf0bd1ef6..49ba7b6b45dd 100644\n> --- a/libstdc++-v3/include/std/optional\n> +++ b/libstdc++-v3/include/std/optional\n> @@ -321,6 +321,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>        {\n>         _M_engaged = false;\n>         _M_payload._M_value.~_Stored_type();\n> +#if __cpp_lib_optional >= 202106L // full constexpr support\n> +       if (std::is_constant_evaluated())\n> +         // Ensure union _M_payload always has an active member, for sake\n> +         // of the core constant expression requirements.\n> +         std::construct_at(std::__addressof(_M_payload._M_empty));\n> +#endif\n>        }\n>\n>  #if __cplusplus >= 202002L\n> diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> new file mode 100644\n> index 000000000000..2f61f7e4e775\n> --- /dev/null\n> +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> @@ -0,0 +1,74 @@\n> +// { dg-do compile { target c++20 } }\n> +\n> +// PR124910 - bogus 'std::optional{...}' is not a constant expression\n> error\n> +// after resetting it via '= nullopt'\n> +\n> +#include <optional>\n> +\n> +struct A\n> +{\n> +  constexpr A(int m) : m(m) { }\n> +  int m;\n> +};\n> +\n> +struct B\n> +{\n> +  constexpr B(int m) : m(m) { }\n> +  constexpr ~B() { }\n> +  int m;\n> +};\n> +\n> +static_assert(   std::is_trivially_destructible_v<int> );\n> +static_assert(   std::is_trivially_destructible_v<A> );\n> +static_assert( ! std::is_trivially_destructible_v<B> );\n> +\n> +template<class T>\n> +void\n> +do_test()\n> +{\n> +  constexpr std::optional<T> x1 = [] {\n> +    std::optional<T> o = 1;\n> +    o = std::nullopt;\n> +    return o;\n> +  }();\n> +\n> +  constexpr std::optional<T> x2 = [] {\n> +    std::optional<T> o = 1;\n> +    o.reset();\n> +    return o;\n> +  }();\n> +\n> +  constexpr std::optional<T> x3 = [] {\n> +    std::optional<T> o1 = 1;\n> +    std::optional<long> o2;\n> +    o1 = o2;\n> +    return o1;\n> +  }();\n> +\n> +  constexpr std::optional<T> x4 = [] {\n> +    std::optional<T> o1 = 1;\n> +    std::optional<long> o2;\n> +    o1 = std::move(o2);\n> +    return o1;\n> +  }();\n> +\n> +  constexpr std::optional<T> x5 = [] {\n> +    std::optional<T> o1 = 1;\n> +    std::optional<T> o2;\n> +    std::swap(o1, o2);\n> +    return o1;\n> +  }();\n> +\n> +  struct C : std::optional<T> {\n> +    constexpr C() : std::optional<T>(1) { this->reset(); }\n> +  };\n> +  constexpr C x6;\n> +}\n> +\n> +int\n> +main()\n> +{\n> +  do_test<int>();\n> +  do_test<A>();\n> +  do_test<B>();\n> +}\n> --\n> 2.54.0.rc1.54.g60f07c4f5c\n>\n>","headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=afMOjT+B;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=afMOjT+B","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzcW95VW9z1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 17:27:00 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 6ACC64A98F03\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 07:26:58 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 260994BA23FE\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 07:26:05 +0000 (GMT)","from mail-yw1-f198.google.com (mail-yw1-f198.google.com\n [209.85.128.198]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-286-8rNFLVfhNiiQ7L7tsJSDsw-1; Mon, 20 Apr 2026 03:26:02 -0400","by mail-yw1-f198.google.com with SMTP id\n 00721157ae682-7b6fea89dd7so55455997b3.1\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 00:26:02 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 6ACC64A98F03","OpenDKIM Filter v2.11.0 sourceware.org 260994BA23FE"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 260994BA23FE","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 260994BA23FE","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776669965; cv=none;\n b=n9shFxAUgwpLvzDEFpI42wWG5DDmZdiYzV5YMl/z9Xvv8MMgvc1YO/KteBjrthx6/rGgNoBRJTJvtPLQM6oMwB/ZLXm2io8pgWoYC+OZ+8037kexbX0yd02f85+mqpHmDLrc7tu7NNqPXy+cmJnstsYiYvB9tH78zlNxF7Dti/E=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776669965; c=relaxed/simple;\n bh=QaH1An831D7EaJaqD8KDMSFGvl/Pb3VoiOh3RQRdIIU=;\n h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To;\n b=eAWGB5IfxlXRDbUQo/3QCStiQOr4Oax8VwRgSsMA9NC+IC5yLwdqN5xfHVrIbfzrH1uTDWoj1IATiH8s9+GxBoF8HXY7AJQhJ++E0cni9D/KKfeDyfzkmok8TpsWzBpK+v+bVSakXANgBQvuU6vH5hUjyE8TT0O/La49DFFEzOA=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776669964;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=mYlM8V9duUMIx8CmT9WkAHTmFCFx3TFNRM7Qe3BxNig=;\n b=afMOjT+BRGc2DM8zTvVStvuu6FTSAQ3r7nxcqh4UGydKHMIQr4CGxrvhKApV2hK5GnGJqd\n kEdGxlXClxi1O1MFelqxhaYC8/4mCI3yE9XWhsNMSPP06+A7Wda0HFqB+3XaFwORc4bX9Y\n hgQlfqD2FNy9FEkPL1AZSyPNER67ztw=","X-MC-Unique":"8rNFLVfhNiiQ7L7tsJSDsw-1","X-Mimecast-MFC-AGG-ID":"8rNFLVfhNiiQ7L7tsJSDsw_1776669962","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776669962; x=1777274762;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=mYlM8V9duUMIx8CmT9WkAHTmFCFx3TFNRM7Qe3BxNig=;\n b=CYDdAstq5jUH3f50MFxzPtKnUbRcyu5ofJwLWHMRdiU2K42qrqFd6WwnFAqu55Lpew\n guK67kWs2cL6nDU9CZYMIYn8bR/bc/r5kOnpjB69CjhEvjzus9Xzqfzqwh8Cg0FhsH1Z\n u+2YqoPFlUCUF/b5YAU9eukGmEYskKLJt2+OBCk3hmzEJCwlLlVrPssRXgsDgeHptDMW\n /NCmtTWFm2zCE44MYTNkkX3jCeGGS5riaQx2GY/jf9HNOK5xKfxs7sOgz2hHlnMa43BS\n X0FRT4LxI2/nYxTpzF30aN2ldwIO4wRApo85bHn8O5Qt8hxj6Nqcnj1I+XY0RvAVAjZy\n p/+w==","X-Gm-Message-State":"AOJu0Yzy6UMJEOI8s3AY2E/QngndGVzOrcQ1Glv+d7jhEgfIdJdgY6/r\n EmyQ21jktDRLG5W10vkeLH6f8E5keDp8N2cKImAoClD9T9qp0kFFrn6B4ePS/hhxwF/K+xMIPD2\n +mQr7A5mkZ6qeWzpbOqTF/EcAW8ZZpKT636fi/W0a7zDp3A3RIbGySQl6n6DZLizRyijhE74XCO\n 23zVm8q6rpOgdrAkHNcy/NM6pkvruev8SSlQ==","X-Gm-Gg":"AeBDiesDIuSHNeseB/o001I//e4uZvVOkNTg8lAt4paGI0rXKTBgtMuqwpkkgHlaw34\n wgZETZZNFzjBAK8+Bm+6RmeO4T8uNWofOFFmctA3F+PC0D1oxdzYrr6ZrOhS1f2VExNTVMU6mo7\n RinTkI+QNVyKlp9ang0YZH1++wBEF7cHndMN37ltV2V7ykyp95OtQUkKniOqa15ZW/jfgzQlQtm\n ivgL3HNSLZnqEAnaDXq9WDxkchnkoTThOjVFlw/eMUcHzTHzk1Po+aG+6j3NDlCC7hBtWDBUK4k\n XQ==","X-Received":["by 2002:a05:690c:6605:b0:7ba:f1a2:a472 with SMTP id\n 00721157ae682-7baf1a2a7aemr16882377b3.38.1776669962079;\n Mon, 20 Apr 2026 00:26:02 -0700 (PDT)","by 2002:a05:690c:6605:b0:7ba:f1a2:a472 with SMTP id\n 00721157ae682-7baf1a2a7aemr16882217b3.38.1776669961551; Mon, 20 Apr 2026\n 00:26:01 -0700 (PDT)"],"MIME-Version":"1.0","References":"<20260418232807.3364700-1-ppalka@redhat.com>","In-Reply-To":"<20260418232807.3364700-1-ppalka@redhat.com>","From":"Tomasz Kaminski <tkaminsk@redhat.com>","Date":"Mon, 20 Apr 2026 09:25:50 +0200","X-Gm-Features":"AQROBzB8IDRQIuD4rBPgs2mPD84XNmrTGtsSHrNy2ueVT0SjRGDNwxbRmQ9XAhE","Message-ID":"\n <CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>","Subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","To":"Patrick Palka <ppalka@redhat.com>","Cc":"gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org, jason@redhat.com,\n Jonathan Wakely <jwakely@redhat.com>","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"BJiORNlFTp-GMW1puJKsbCkKZbHq7-AApeFwsbfzlF8_1776669962","X-Mimecast-Originator":"redhat.com","Content-Type":"multipart/alternative; boundary=\"000000000000f1af4d064fdf3559\"","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}},{"id":3679268,"web_url":"http://patchwork.ozlabs.org/comment/3679268/","msgid":"<CAKvuMXBwX7xp2-y_KP8+a9J-3VNTzEvjuK+kKxya3t-H_mZhfQ@mail.gmail.com>","list_archive_url":null,"date":"2026-04-20T07:26:55","subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","submitter":{"id":90409,"url":"http://patchwork.ozlabs.org/api/people/90409/","name":"Tomasz Kamiński","email":"tkaminsk@redhat.com"},"content":"On Mon, Apr 20, 2026 at 9:25 AM Tomasz Kaminski <tkaminsk@redhat.com> wrote:\n\n>\n>\n> On Sun, Apr 19, 2026 at 1:28 AM Patrick Palka <ppalka@redhat.com> wrote:\n>\n>> Changes in v2:\n>>   - Added code comment\n>>   - Clarified commit message, removed red herring about trivial\n>>     destructibility.\n>>   - Extended test with 'x6' direct-initialization that avoids invoking\n>>     optional's move constructor.  This testcase, when instantiated with\n>> T=B,\n>>     demonstrates that non-trivially-copyable optional is also affected\n>>     and we must set _M_empty even in that case.\n>>\n>> -- >8 --\n>>\n>> When an optional that contains a value is cleared, _M_destroy invokes the\n>> destructor of the contained value _Storage::_M_value, leaving the union\n>> _Storage without an active member.  While this is benign at runtime, a\n>> union suboject with no active member violates core constant expression\n>> requirements and in turn an optional in this state can't be used as a\n>> constant initializer, which Clang and recent GCC (since r16-3022)\n>> correctly\n>> diagnose.\n>>\n> I am not aware of this limitation, and I do not see how if fails out of\n> the wording,\n> The constituent values explicitly exclude inactive union members:\n> https://eel.is/c++draft/intro.object#12.2, so empty union simply has none.\n>\n> Could you please update the commit description, to reflect actual problem\n> as described by Jason here:\n> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124910#c13\n>\nAh sorry, I haven't noticed that the patch is already committed.\n\n>\n>\n>\n>>\n>> To fix this, this patch makes _M_destroy activate the dummy union member\n>> _M_empty after destroying _M_value to ensure that the union always has\n>> an active member throughout its lifetime.  We use std::construct_at\n>> instead of simple assignment to work around a front end bug (comment #3\n>> in the PR).  Doing so means we don't activate the member in C++17 mode,\n>> which should be fine; I don't think it's possible to disengage an engaged\n>> optional using only the C++17 constexpr optional operations.\n>>\n>>         PR c++/124910\n>>\n>> libstdc++-v3/ChangeLog:\n>>\n>>         * include/std/optional (_Optional_payload_base::_M_destroy)\n>>         [__cpp_lib_optional >= 202106L]: During constant evaluation,\n>>         after invoking destructor of _M_value, use construct_at to\n>>         activate _M_empty.\n>>         * testsuite/20_util/optional/constexpr/124910.cc: New test.\n>>\n>> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>\n>> ---\n>>  libstdc++-v3/include/std/optional             |  6 ++\n>>  .../20_util/optional/constexpr/124910.cc      | 74 +++++++++++++++++++\n>>  2 files changed, 80 insertions(+)\n>>  create mode 100644\n>> libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>>\n>> diff --git a/libstdc++-v3/include/std/optional\n>> b/libstdc++-v3/include/std/optional\n>> index 0f4cf0bd1ef6..49ba7b6b45dd 100644\n>> --- a/libstdc++-v3/include/std/optional\n>> +++ b/libstdc++-v3/include/std/optional\n>> @@ -321,6 +321,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>>        {\n>>         _M_engaged = false;\n>>         _M_payload._M_value.~_Stored_type();\n>> +#if __cpp_lib_optional >= 202106L // full constexpr support\n>> +       if (std::is_constant_evaluated())\n>> +         // Ensure union _M_payload always has an active member, for sake\n>> +         // of the core constant expression requirements.\n>> +         std::construct_at(std::__addressof(_M_payload._M_empty));\n>> +#endif\n>>        }\n>>\n>>  #if __cplusplus >= 202002L\n>> diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>> b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>> new file mode 100644\n>> index 000000000000..2f61f7e4e775\n>> --- /dev/null\n>> +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>> @@ -0,0 +1,74 @@\n>> +// { dg-do compile { target c++20 } }\n>> +\n>> +// PR124910 - bogus 'std::optional{...}' is not a constant expression\n>> error\n>> +// after resetting it via '= nullopt'\n>> +\n>> +#include <optional>\n>> +\n>> +struct A\n>> +{\n>> +  constexpr A(int m) : m(m) { }\n>> +  int m;\n>> +};\n>> +\n>> +struct B\n>> +{\n>> +  constexpr B(int m) : m(m) { }\n>> +  constexpr ~B() { }\n>> +  int m;\n>> +};\n>> +\n>> +static_assert(   std::is_trivially_destructible_v<int> );\n>> +static_assert(   std::is_trivially_destructible_v<A> );\n>> +static_assert( ! std::is_trivially_destructible_v<B> );\n>> +\n>> +template<class T>\n>> +void\n>> +do_test()\n>> +{\n>> +  constexpr std::optional<T> x1 = [] {\n>> +    std::optional<T> o = 1;\n>> +    o = std::nullopt;\n>> +    return o;\n>> +  }();\n>> +\n>> +  constexpr std::optional<T> x2 = [] {\n>> +    std::optional<T> o = 1;\n>> +    o.reset();\n>> +    return o;\n>> +  }();\n>> +\n>> +  constexpr std::optional<T> x3 = [] {\n>> +    std::optional<T> o1 = 1;\n>> +    std::optional<long> o2;\n>> +    o1 = o2;\n>> +    return o1;\n>> +  }();\n>> +\n>> +  constexpr std::optional<T> x4 = [] {\n>> +    std::optional<T> o1 = 1;\n>> +    std::optional<long> o2;\n>> +    o1 = std::move(o2);\n>> +    return o1;\n>> +  }();\n>> +\n>> +  constexpr std::optional<T> x5 = [] {\n>> +    std::optional<T> o1 = 1;\n>> +    std::optional<T> o2;\n>> +    std::swap(o1, o2);\n>> +    return o1;\n>> +  }();\n>> +\n>> +  struct C : std::optional<T> {\n>> +    constexpr C() : std::optional<T>(1) { this->reset(); }\n>> +  };\n>> +  constexpr C x6;\n>> +}\n>> +\n>> +int\n>> +main()\n>> +{\n>> +  do_test<int>();\n>> +  do_test<A>();\n>> +  do_test<B>();\n>> +}\n>> --\n>> 2.54.0.rc1.54.g60f07c4f5c\n>>\n>>","headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=KQZkb9Oo;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=KQZkb9Oo","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzcXK2JHcz1yGs\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 17:28:01 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 8E6B64CCCA31\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 07:27:57 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 166664A98F03\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 07:27:10 +0000 (GMT)","from mail-yw1-f200.google.com (mail-yw1-f200.google.com\n [209.85.128.200]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-50-5U1PYxXiN7eyPR3Y9_5AKA-1; Mon, 20 Apr 2026 03:27:07 -0400","by mail-yw1-f200.google.com with SMTP id\n 00721157ae682-79064868702so54725877b3.3\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 00:27:07 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 8E6B64CCCA31","OpenDKIM Filter v2.11.0 sourceware.org 166664A98F03"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 166664A98F03","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 166664A98F03","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776670030; cv=none;\n b=wm+89ADe3bTKCrDuW0lEnQAj0WgyTmOXxlrJkoMjLscYeqWW5p7896mdGMBV7t3UNSzANl1vytim+lYONUoZr8CFre7AtnpIrSiKWPafSBUkBRbBMFhU9aGmuA8m2QtPbQH3uOouxJKOOGdirh3a0qsgN1pWQMgZD5FRnNBHcOc=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776670030; c=relaxed/simple;\n bh=jq0xZFagW2wJ44pMbHC6GXtnMiGrTOqscdYEfRcTJNI=;\n h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To;\n b=jB4j3xPtQx2yvYMriUfRwufq22adu/2zGWaU+XNoqc5A+WEzJCH7RGwYdVCjtpg9bWhxQqvJpim6d4oLqdqpzc2sAvdq0ikN31nzbOEJEZiN8I6QHoEEinbnYVKbFcoCZaoVIq/Kbop20LSbRacshxj5NTDOZEdZWsU0hkkNjj0=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776670029;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=79sMMg1HQVANGLTB07STXkMwMYK3Pi2bGBe5TRWwf+g=;\n b=KQZkb9Ook5QCsae9hTp31MwF1dD9iHQ3dnxPtDIYYv3iMTbQVX2cB0Rc5w3yFTG/xwSkYi\n Q8ofepB+yJYGzkDIwJNIN3Kk6FhdvIDdUYvy6SfP9apc7Oycse4l6Ez7riP+N2aOP+j3qJ\n cOBt1r7w817RcqnGm8JrR/Hqvfq4xUE=","X-MC-Unique":"5U1PYxXiN7eyPR3Y9_5AKA-1","X-Mimecast-MFC-AGG-ID":"5U1PYxXiN7eyPR3Y9_5AKA_1776670027","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776670027; x=1777274827;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=79sMMg1HQVANGLTB07STXkMwMYK3Pi2bGBe5TRWwf+g=;\n b=tLYfDniV1lIlJedHv11G8n4HJwX/nrhGteQOc8ZuAgCU+WR5UCR+0hmQEmOgEo8WGh\n /fvEHnIdTeMcgFl6/7r4QTIKdqgHDF3H7uYs52SSDqMVZQpFcpqw37YlJrgOyDe5wLiL\n +8G3iqFYrPeX4fBz7FFC7PCiJG8aoIWRrDzGPKOyEyWb+JYqTD0nQBYaAcNX/OWurXbB\n RmkdcZNYb+3yy7YlW5dnQ9Fn4SvrndUDnLW21Q9aEiZhp47lQE5tdPRv/AZhadd32xea\n RNwlxihCZP166DHaqKztuaH2htVQxE3H+VePlb9VH6I5mfu9zoAD45AF4/9HfozYY2bk\n RJrw==","X-Gm-Message-State":"AOJu0YxaXjWO89FdprBTauwILDpdOG6kZWBPp28ORNKwsQrhU43fQf7l\n FpBi3Jp+Ss+kfVBYtkVbNHMnr9hx1wNN71s8iF87YsCRPmIOayTnWgmXZCjJtsCv2eRZVjvMP4a\n 3TRUtASRuIjiPfD5b/YWhX+48bmyBtCFSCaZCSp8T8cNlWp/FIaZiZsg6lHXBAfnwYuyQnEADub\n BvmF7Fm7CJibMSkPpVB02UQoBtFfWni7iIZA==","X-Gm-Gg":"AeBDietx3HHspVX29ZcDQ3Q9qJTWKw12vjrdGltyu3d7f58BVjiWvVVFD6RrxEM1pkM\n Mya6pWFrCkSXnYD9FmxYnhe228wiwGPM9bb1EEtXjxrp0zpo/XTC+WMsIqo2T6yCXHpV1Ey9nV0\n MMyEry9YAozLSJ2j+LfdVK6deaqyjWbk354pSkC7wch4oBaEPodElf+3WQya0ktbrYbNHNFqZXB\n siboH9TlbgMj3+gwqLA9tM5FkRetROex2LnQfQ0hYfm4mfcs4s5kDqi4Pr6WRUStffqUNeV05Qo\n fw==","X-Received":["by 2002:a05:690c:6c0d:b0:7b4:378c:f732 with SMTP id\n 00721157ae682-7b9ed0477e1mr123782417b3.46.1776670027180;\n Mon, 20 Apr 2026 00:27:07 -0700 (PDT)","by 2002:a05:690c:6c0d:b0:7b4:378c:f732 with SMTP id\n 00721157ae682-7b9ed0477e1mr123782267b3.46.1776670026610; Mon, 20 Apr 2026\n 00:27:06 -0700 (PDT)"],"MIME-Version":"1.0","References":"<20260418232807.3364700-1-ppalka@redhat.com>\n <CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>","In-Reply-To":"\n <CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>","From":"Tomasz Kaminski <tkaminsk@redhat.com>","Date":"Mon, 20 Apr 2026 09:26:55 +0200","X-Gm-Features":"AQROBzBx9ih15f5_PMYqmC5QFARqgLS6NFHRa741ICJf1eZyF5T_ervjNkzL2nw","Message-ID":"\n <CAKvuMXBwX7xp2-y_KP8+a9J-3VNTzEvjuK+kKxya3t-H_mZhfQ@mail.gmail.com>","Subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","To":"Patrick Palka <ppalka@redhat.com>","Cc":"gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org, jason@redhat.com,\n Jonathan Wakely <jwakely@redhat.com>","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"o74nk3wTWRVnVBTebDM-McJkB0_wEv0Rm1VAG6B-obo_1776670027","X-Mimecast-Originator":"redhat.com","Content-Type":"multipart/alternative; boundary=\"000000000000d27d7d064fdf3928\"","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}},{"id":3679393,"web_url":"http://patchwork.ozlabs.org/comment/3679393/","msgid":"<d5572fc1-d066-2b6b-b008-7a5e29ee9b14@idea>","list_archive_url":null,"date":"2026-04-20T12:44:19","subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","submitter":{"id":78319,"url":"http://patchwork.ozlabs.org/api/people/78319/","name":"Patrick Palka","email":"ppalka@redhat.com"},"content":"On Mon, 20 Apr 2026, Tomasz Kaminski wrote:\n\n> \n> \n> On Sun, Apr 19, 2026 at 1:28 AM Patrick Palka <ppalka@redhat.com> wrote:\n>       Changes in v2:\n>         - Added code comment\n>         - Clarified commit message, removed red herring about trivial\n>           destructibility.\n>         - Extended test with 'x6' direct-initialization that avoids invoking\n>           optional's move constructor.  This testcase, when instantiated with T=B,\n>           demonstrates that non-trivially-copyable optional is also affected\n>           and we must set _M_empty even in that case.\n> \n>       -- >8 --\n> \n>       When an optional that contains a value is cleared, _M_destroy invokes the\n>       destructor of the contained value _Storage::_M_value, leaving the union\n>       _Storage without an active member.  While this is benign at runtime, a\n>       union suboject with no active member violates core constant expression\n>       requirements and in turn an optional in this state can't be used as a\n>       constant initializer, which Clang and recent GCC (since r16-3022) correctly\n>       diagnose.\n> \n> I am not aware of this limitation, and I do not see how if fails out of the wording,\n> The constituent values explicitly exclude inactive union members:\n> https://eel.is/c++draft/intro.object#12.2, so empty union simply has none.\n\nThat term \"constituent values\" seems to have been introduced in C++26 by\nP2668R5 and so it's not clear to what extent that wording applies to C++20 :/\n\n> \n> Could you please update the commit description, to reflect actual problem\n> as described by Jason here:\n> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124910#c13\n\n[class.union.general]/2 says: In a union, a non-static data member is\nactive if its name refers to an object whose lifetime has begun and has\nnot ended.  How does destroying an active member not make it inactive?\n\n \n> \n>  \n> \n>       To fix this, this patch makes _M_destroy activate the dummy union member\n>       _M_empty after destroying _M_value to ensure that the union always has\n>       an active member throughout its lifetime.  We use std::construct_at\n>       instead of simple assignment to work around a front end bug (comment #3\n>       in the PR).  Doing so means we don't activate the member in C++17 mode,\n>       which should be fine; I don't think it's possible to disengage an engaged\n>       optional using only the C++17 constexpr optional operations.\n> \n>               PR c++/124910\n> \n>       libstdc++-v3/ChangeLog:\n> \n>               * include/std/optional (_Optional_payload_base::_M_destroy)\n>               [__cpp_lib_optional >= 202106L]: During constant evaluation,\n>               after invoking destructor of _M_value, use construct_at to\n>               activate _M_empty.\n>               * testsuite/20_util/optional/constexpr/124910.cc: New test.\n> \n>       Reviewed-by: Jonathan Wakely <jwakely@redhat.com>\n>       ---\n>        libstdc++-v3/include/std/optional             |  6 ++\n>        .../20_util/optional/constexpr/124910.cc      | 74 +++++++++++++++++++\n>        2 files changed, 80 insertions(+)\n>        create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> \n>       diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional\n>       index 0f4cf0bd1ef6..49ba7b6b45dd 100644\n>       --- a/libstdc++-v3/include/std/optional\n>       +++ b/libstdc++-v3/include/std/optional\n>       @@ -321,6 +321,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>              {\n>               _M_engaged = false;\n>               _M_payload._M_value.~_Stored_type();\n>       +#if __cpp_lib_optional >= 202106L // full constexpr support\n>       +       if (std::is_constant_evaluated())\n>       +         // Ensure union _M_payload always has an active member, for sake\n>       +         // of the core constant expression requirements.\n>       +         std::construct_at(std::__addressof(_M_payload._M_empty));\n>       +#endif\n>              }\n> \n>        #if __cplusplus >= 202002L\n>       diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>       new file mode 100644\n>       index 000000000000..2f61f7e4e775\n>       --- /dev/null\n>       +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>       @@ -0,0 +1,74 @@\n>       +// { dg-do compile { target c++20 } }\n>       +\n>       +// PR124910 - bogus 'std::optional{...}' is not a constant expression error\n>       +// after resetting it via '= nullopt'\n>       +\n>       +#include <optional>\n>       +\n>       +struct A\n>       +{\n>       +  constexpr A(int m) : m(m) { }\n>       +  int m;\n>       +};\n>       +\n>       +struct B\n>       +{\n>       +  constexpr B(int m) : m(m) { }\n>       +  constexpr ~B() { }\n>       +  int m;\n>       +};\n>       +\n>       +static_assert(   std::is_trivially_destructible_v<int> );\n>       +static_assert(   std::is_trivially_destructible_v<A> );\n>       +static_assert( ! std::is_trivially_destructible_v<B> );\n>       +\n>       +template<class T>\n>       +void\n>       +do_test()\n>       +{\n>       +  constexpr std::optional<T> x1 = [] {\n>       +    std::optional<T> o = 1;\n>       +    o = std::nullopt;\n>       +    return o;\n>       +  }();\n>       +\n>       +  constexpr std::optional<T> x2 = [] {\n>       +    std::optional<T> o = 1;\n>       +    o.reset();\n>       +    return o;\n>       +  }();\n>       +\n>       +  constexpr std::optional<T> x3 = [] {\n>       +    std::optional<T> o1 = 1;\n>       +    std::optional<long> o2;\n>       +    o1 = o2;\n>       +    return o1;\n>       +  }();\n>       +\n>       +  constexpr std::optional<T> x4 = [] {\n>       +    std::optional<T> o1 = 1;\n>       +    std::optional<long> o2;\n>       +    o1 = std::move(o2);\n>       +    return o1;\n>       +  }();\n>       +\n>       +  constexpr std::optional<T> x5 = [] {\n>       +    std::optional<T> o1 = 1;\n>       +    std::optional<T> o2;\n>       +    std::swap(o1, o2);\n>       +    return o1;\n>       +  }();\n>       +\n>       +  struct C : std::optional<T> {\n>       +    constexpr C() : std::optional<T>(1) { this->reset(); }\n>       +  };\n>       +  constexpr C x6;\n>       +}\n>       +\n>       +int\n>       +main()\n>       +{\n>       +  do_test<int>();\n>       +  do_test<A>();\n>       +  do_test<B>();\n>       +}\n>       --\n>       2.54.0.rc1.54.g60f07c4f5c\n> \n> \n>","headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=bedqex4x;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=bedqex4x","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.129.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzlZK17Ptz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 22:45:10 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 8254B4D108E4\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 12:45:08 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id 3164C4C91769\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 12:44:24 +0000 (GMT)","from mail-qt1-f200.google.com (mail-qt1-f200.google.com\n [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-605-0AUaQQasNv-JEUDfAlsfGg-1; Mon, 20 Apr 2026 08:44:22 -0400","by mail-qt1-f200.google.com with SMTP id\n d75a77b69052e-50d840206c3so5829501cf.3\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 05:44:22 -0700 (PDT)","from [2600:4040:aa66:bf00:9e8e:99ff:fed1:71f]\n ([2600:4040:aa66:bf00:9e8e:99ff:fed1:71f])\n by smtp.gmail.com with ESMTPSA id\n d75a77b69052e-50e3bf260fbsm94909761cf.10.2026.04.20.05.44.19\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 20 Apr 2026 05:44:20 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 8254B4D108E4","OpenDKIM Filter v2.11.0 sourceware.org 3164C4C91769"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 3164C4C91769","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 3164C4C91769","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776689064; cv=none;\n b=UrQ8AfNhhT5FMSRj6Jm2OSj/xLnnw0ofoy1PusNnOxbbR00XGrShR8ZuBQZvFf2cE4AGCtA1vFy3zYDF7swoPHMQwcDfttjwID0eH/gfsvJcpl+7vkgIrxTT0yCkGj0gB1wYiCLynbsDaPVHYo9gyiP32UrvJDsT7nHjZSk4cKQ=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776689064; c=relaxed/simple;\n bh=g0BdkFErLr6kwsX1+sjUbiGSU8xAgn39VsZ9GqxyZ1c=;\n h=DKIM-Signature:From:Date:To:Subject:Message-ID:MIME-Version;\n b=GzSluXrj9rKN8cci3QougtgizXq04vBxMcTgdSpiQUpccHqpwCJHAESWc/gLjq4EjyGURZQtBd4wwaMi2I/XqObXLl7Sm2Up5srKKxH8Ux9FpJGTGzR5sL5e82oDPNjY21ejQdXqdALTsCWktJ9zFWXXPswPNiPwcgmg8H9bfaw=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776689063;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=dMN9LnOYsrB5TQDEpQ3jQ/pgWyExwSrRvBfwAOgQ7Bo=;\n b=bedqex4xzI0K3/IxZTOG1qT6rWKF9scPcc/O8JKSR5Lrbe5cH0JxCCq7GX8OOq/oTLes9G\n lIOvxtJksv/ut3cB0/0EJCJAE5zOgANUQ33xtbIjh3/kDVsqLDyl1A+Ko87mVbCT4Jw9Ry\n 2OjXtWvySVqv0/nWI3JsCObdsOgslVw=","X-MC-Unique":"0AUaQQasNv-JEUDfAlsfGg-1","X-Mimecast-MFC-AGG-ID":"0AUaQQasNv-JEUDfAlsfGg_1776689062","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776689062; x=1777293862;\n h=mime-version:references:message-id:in-reply-to:subject:cc:to:date\n :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=Egmm9beDcoRp8o+I1hXIrfE703bsq70AgDJFL5vAHKA=;\n b=EdUET/Ad5gjUJ3p3V20L29UCzvlTL9gwDHNs2goM4pV2iqHXWoEcQgSclONxzHImu9\n 6Paq9l8mJOFTetdVCfs8l3IfHBWo9HFyHLw+Uc9/fVFHMlxFRgHlg71GvY8aP8Vk6GhX\n RzzhFmZnxDP51iUOpaMLE3tw6rrIZ1eNrJqy0QFskwt41R70l7kuAW0F/+Hf2gfbEUIc\n 87qn85ogbX2mn+fxorEPWWDDtR/wNodZw8Q0o07tLDuDWj3wOJV1ElWQ2VHrzcIi5IRZ\n XQxCF3pD1tLzRnUgtMi8XMcsUjHGhe3RweW2f2hksN2gNHQl1JAmQQbO+YWzo5KnnD5G\n HIJQ==","X-Forwarded-Encrypted":"i=1;\n AFNElJ9X7MI092E3Lflf3uc9ldOENPFmkRbE1BEARrN1jXuHeiMetN1bDGRSZDUNBF72f77jby6Ec4QaPWnBIA==@gcc.gnu.org","X-Gm-Message-State":"AOJu0YwMgNZgKB3rTYjtE89NsodWR4Yi0MaR9oZ6ROO0MDgV8v0/ow0F\n nDsywrLdc7x+oKowgyFeBSqplqEbGuNn5jMiSRCa1nby2I/iryZZV0GtwJgg1ulG36x2rh47/8m\n BJvzu9cv/NFJmrWQQYKKLRaYlXbHy1WveofACMIVkJEvmgbG1uJBYPEwR6G4=","X-Gm-Gg":"AeBDies0kFPk5BYSUbB0i24o2wpDYVf7DzV/vKM9kTS4lAulAv62hqRppNmP6a7mCsi\n dq7A1Ot+e48DSaK4Iehbw+psrfH1Jn6MbKfZ0G0qJJoRMGtEewTis7DJJ90qojV21mINFrKwyt0\n 4sHlktIo4Dn8iAdyli024xaQK6vNlAOBC+fzYTgCFY0XZlj9QWGljyjCfOY5JrcInbOO/5FEaRa\n TV5Y0JP9/dpZZiL+o91cf+UocmF7nobR6+y05eZTCutg4Fmq7BmKMG6tc1jOObvO4+Fkr6/1JKn\n 0dtScwrG2ETS9WpuDY35uyrKOcvYY8HeWHP3r9RR17+gBoTJR4oT5NfV23FkOfeUs5udA5wYEiO\n RKRx6wbfpGCLXvPVKbzlIN6e0/Wno/ApmDbOU/PXvdOPV51rFx94+qnyl4e529xBG","X-Received":["by 2002:a05:622a:2587:b0:50e:a1ab:67e6 with SMTP id\n d75a77b69052e-50ea1ab6a40mr15420341cf.4.1776689061778;\n Mon, 20 Apr 2026 05:44:21 -0700 (PDT)","by 2002:a05:622a:2587:b0:50e:a1ab:67e6 with SMTP id\n d75a77b69052e-50ea1ab6a40mr15419971cf.4.1776689061230;\n Mon, 20 Apr 2026 05:44:21 -0700 (PDT)"],"From":"Patrick Palka <ppalka@redhat.com>","X-Google-Original-From":"Patrick Palka <patrick@idea>","Date":"Mon, 20 Apr 2026 08:44:19 -0400 (EDT)","To":"Tomasz Kaminski <tkaminsk@redhat.com>","cc":"Patrick Palka <ppalka@redhat.com>, gcc-patches@gcc.gnu.org,\n libstdc++@gcc.gnu.org, jason@redhat.com,\n Jonathan Wakely <jwakely@redhat.com>","Subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","In-Reply-To":"\n <CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>","Message-ID":"<d5572fc1-d066-2b6b-b008-7a5e29ee9b14@idea>","References":"<20260418232807.3364700-1-ppalka@redhat.com>\n <CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"CoCDMNXmj-81H2IjAzgsnt8zSAEHALi1no0J8gMNEUc_1776689062","X-Mimecast-Originator":"redhat.com","Content-Type":"multipart/mixed; boundary=\"8323329-699540677-1776689060=:113381\"","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}},{"id":3679411,"web_url":"http://patchwork.ozlabs.org/comment/3679411/","msgid":"<CAKvuMXB64JLtF3Y3_L3dxQ7jw3MAVQbiOj2ii90_Bd6JEyrSSg@mail.gmail.com>","list_archive_url":null,"date":"2026-04-20T13:39:45","subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","submitter":{"id":90409,"url":"http://patchwork.ozlabs.org/api/people/90409/","name":"Tomasz Kamiński","email":"tkaminsk@redhat.com"},"content":"On Mon, Apr 20, 2026 at 2:44 PM Patrick Palka <ppalka@redhat.com> wrote:\n\n> On Mon, 20 Apr 2026, Tomasz Kaminski wrote:\n>\n> >\n> >\n> > On Sun, Apr 19, 2026 at 1:28 AM Patrick Palka <ppalka@redhat.com> wrote:\n> >       Changes in v2:\n> >         - Added code comment\n> >         - Clarified commit message, removed red herring about trivial\n> >           destructibility.\n> >         - Extended test with 'x6' direct-initialization that avoids\n> invoking\n> >           optional's move constructor.  This testcase, when instantiated\n> with T=B,\n> >           demonstrates that non-trivially-copyable optional is also\n> affected\n> >           and we must set _M_empty even in that case.\n> >\n> >       -- >8 --\n> >\n> >       When an optional that contains a value is cleared, _M_destroy\n> invokes the\n> >       destructor of the contained value _Storage::_M_value, leaving the\n> union\n> >       _Storage without an active member.  While this is benign at\n> runtime, a\n> >       union suboject with no active member violates core constant\n> expression\n> >       requirements and in turn an optional in this state can't be used\n> as a\n> >       constant initializer, which Clang and recent GCC (since r16-3022)\n> correctly\n> >       diagnose.\n> >\n> > I am not aware of this limitation, and I do not see how if fails out of\n> the wording,\n> > The constituent values explicitly exclude inactive union members:\n> >\n> https://eel.is/c++draft/intro.objehttps://docs.google.com/https://docs.google.com/ct#12.2\n> <https://eel.is/c++draft/intro.object#12.2>, so empty union simply has\n> none.\n>\n> That term \"constituent values\" seems to have been introduced in C++26 by\n> P2668R5 and so it's not clear to what extent that wording applies to C++20\n> :/\n>\nFor C++20 we have:\nhttps://timsong-cpp.github.io/cppwp/n4861/dcl.constexpr#10\nAnd there seem be no limitation of union without active members here:\nhttps://timsong-cpp.github.io/cppwp/n4861/expr.const#5\n\n>\n> >\n> > Could you please update the commit description, to reflect actual problem\n> > as described by Jason here:\n> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124910#c13\n>\n> [class.union.general]/2 says: In a union, a non-static data member is\n> active if its name refers to an object whose lifetime has begun and has\n> not ended.  How does destroying an active member not make it inactive?\n>\nI think the point of comment, is that this change is a workaround for GCC\nbug\n(the _M_value member is still considered active member, but it shouldn't).\n\n>\n>\n> >\n> >\n> >\n> >       To fix this, this patch makes _M_destroy activate the dummy union\n> member\n> >       _M_empty after destroying _M_value to ensure that the union always\n> has\n> >       an active member throughout its lifetime.  We use std::construct_at\n> >       instead of simple assignment to work around a front end bug\n> (comment #3\n> >       in the PR).  Doing so means we don't activate the member in C++17\n> mode,\n> >       which should be fine; I don't think it's possible to disengage an\n> engaged\n> >       optional using only the C++17 constexpr optional operations.\n> >\n> >               PR c++/124910\n> >\n> >       libstdc++-v3/ChangeLog:\n> >\n> >               * include/std/optional (_Optional_payload_base::_M_destroy)\n> >               [__cpp_lib_optional >= 202106L]: During constant\n> evaluation,\n> >               after invoking destructor of _M_value, use construct_at to\n> >               activate _M_empty.\n> >               * testsuite/20_util/optional/constexpr/124910.cc: New test.\n> >\n> >       Reviewed-by: Jonathan Wakely <jwakely@redhat.com>\n> >       ---\n> >        libstdc++-v3/include/std/optional             |  6 ++\n> >        .../20_util/optional/constexpr/124910.cc      | 74\n> +++++++++++++++++++\n> >        2 files changed, 80 insertions(+)\n> >        create mode 100644\n> libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> >\n> >       diff --git a/libstdc++-v3/include/std/optional\n> b/libstdc++-v3/include/std/optional\n> >       index 0f4cf0bd1ef6..49ba7b6b45dd 100644\n> >       --- a/libstdc++-v3/include/std/optional\n> >       +++ b/libstdc++-v3/include/std/optional\n> >       @@ -321,6 +321,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n> >              {\n> >               _M_engaged = false;\n> >               _M_payload._M_value.~_Stored_type();\n> >       +#if __cpp_lib_optional >= 202106L // full constexpr support\n> >       +       if (std::is_constant_evaluated())\n> >       +         // Ensure union _M_payload always has an active member,\n> for sake\n> >       +         // of the core constant expression requirements.\n> >       +         std::construct_at(std::__addressof(_M_payload._M_empty));\n> >       +#endif\n> >              }\n> >\n> >        #if __cplusplus >= 202002L\n> >       diff --git\n> a/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> >       new file mode 100644\n> >       index 000000000000..2f61f7e4e775\n> >       --- /dev/null\n> >       +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n> >       @@ -0,0 +1,74 @@\n> >       +// { dg-do compile { target c++20 } }\n> >       +\n> >       +// PR124910 - bogus 'std::optional{...}' is not a constant\n> expression error\n> >       +// after resetting it via '= nullopt'\n> >       +\n> >       +#include <optional>\n> >       +\n> >       +struct A\n> >       +{\n> >       +  constexpr A(int m) : m(m) { }\n> >       +  int m;\n> >       +};\n> >       +\n> >       +struct B\n> >       +{\n> >       +  constexpr B(int m) : m(m) { }\n> >       +  constexpr ~B() { }\n> >       +  int m;\n> >       +};\n> >       +\n> >       +static_assert(   std::is_trivially_destructible_v<int> );\n> >       +static_assert(   std::is_trivially_destructible_v<A> );\n> >       +static_assert( ! std::is_trivially_destructible_v<B> );\n> >       +\n> >       +template<class T>\n> >       +void\n> >       +do_test()\n> >       +{\n> >       +  constexpr std::optional<T> x1 = [] {\n> >       +    std::optional<T> o = 1;\n> >       +    o = std::nullopt;\n> >       +    return o;\n> >       +  }();\n> >       +\n> >       +  constexpr std::optional<T> x2 = [] {\n> >       +    std::optional<T> o = 1;\n> >       +    o.reset();\n> >       +    return o;\n> >       +  }();\n> >       +\n> >       +  constexpr std::optional<T> x3 = [] {\n> >       +    std::optional<T> o1 = 1;\n> >       +    std::optional<long> o2;\n> >       +    o1 = o2;\n> >       +    return o1;\n> >       +  }();\n> >       +\n> >       +  constexpr std::optional<T> x4 = [] {\n> >       +    std::optional<T> o1 = 1;\n> >       +    std::optional<long> o2;\n> >       +    o1 = std::move(o2);\n> >       +    return o1;\n> >       +  }();\n> >       +\n> >       +  constexpr std::optional<T> x5 = [] {\n> >       +    std::optional<T> o1 = 1;\n> >       +    std::optional<T> o2;\n> >       +    std::swap(o1, o2);\n> >       +    return o1;\n> >       +  }();\n> >       +\n> >       +  struct C : std::optional<T> {\n> >       +    constexpr C() : std::optional<T>(1) { this->reset(); }\n> >       +  };\n> >       +  constexpr C x6;\n> >       +}\n> >       +\n> >       +int\n> >       +main()\n> >       +{\n> >       +  do_test<int>();\n> >       +  do_test<A>();\n> >       +  do_test<B>();\n> >       +}\n> >       --\n> >       2.54.0.rc1.54.g60f07c4f5c\n> >\n> >\n> >\n>","headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=jQ75YF+x;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=jQ75YF+x","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.129.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzmpV0vrqz1yD4\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 23:40:48 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id B22744B35881\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 13:40:46 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id DD2134BA23C2\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 13:40:00 +0000 (GMT)","from mail-yw1-f197.google.com (mail-yw1-f197.google.com\n [209.85.128.197]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-561-IzrApEOaMbG9HytMx3FLFA-1; Mon, 20 Apr 2026 09:39:59 -0400","by mail-yw1-f197.google.com with SMTP id\n 00721157ae682-794c39ea759so20359437b3.1\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 06:39:58 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org B22744B35881","OpenDKIM Filter v2.11.0 sourceware.org DD2134BA23C2"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org DD2134BA23C2","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org DD2134BA23C2","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776692401; cv=none;\n b=dzCqM58ES390TT0vTPLviR1AS5Q1d8b+Fir/Awpc4EzHh9iGb0R44RWAuy5lIgy3429/F/8WldKkEUU/faOFQuRr96PFQ3+hDj0OlDCXQzCVy/BXwyT3hSLUK+dcMzdLdErHUuMuBCY62+y4OHN1ylMRPyOfdN+Yzl1aXvzFunE=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776692401; c=relaxed/simple;\n bh=PwSPAOD5+zlD+RyVMPK8FPNCufZ7mskpnm2vu8Ofwnk=;\n h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To;\n b=Zeed/8MLayQ5QAnhrqExEblfpFpFaEj/uD2hU+ml5Sm7gMIBWy6ZUOODx8+w2KxuF3zGaN6PYeWSPH4GKBDy1X5jdEc3iCC4Z/QIr6RsIlU9psf2idZtE/NGu53k8dGxSH7LBrTKYB63fw28FKJ1FP5jwNqq8O8V+I4L/+/rN/g=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776692400;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=i0x9BnkrYOlgjkBQXWDWBlkHd2OUhoGcRTX+TZvAhIU=;\n b=jQ75YF+xCBofK0qj62EJDIeW29W7ogREFJPaM3kVf6cNbkjdfzqPwPESUZdJub5O7G2JsS\n amVGkgcuJ4ZBTj8GVoPY4O1ya2rymfFa4ushK81qTnR3nqOZkBNjiMbUfGJBPF69AahvqB\n Sqyh4kGv8Nff8tIwNtEx1tjYUIJDXZc=","X-MC-Unique":"IzrApEOaMbG9HytMx3FLFA-1","X-Mimecast-MFC-AGG-ID":"IzrApEOaMbG9HytMx3FLFA_1776692398","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776692398; x=1777297198;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=i0x9BnkrYOlgjkBQXWDWBlkHd2OUhoGcRTX+TZvAhIU=;\n b=tKCG3oYqzpnf3IUR8QeLBjrbqzY84IHpgL6O6ExnTRW+/sCWdHFdIGfOEgU3JehRDU\n YB5lkIQzDxVuhAOX+bxJNUBVSZ5p8KZUx2hmIKkZjaxSgB3LEl2lnmj43Hen8bkyugog\n 4PFPwoN+CSW3Ms2McE4lgvk9nMoHGLMbtRP5ekopSVcTAFT4wt/VWoXNEZt0JB/GvIx6\n 7TJGba6RUf+wC8iTYQ9JsJI+HPOXaUu6QM0wD49pD3X8sE7xewNUwAWNs0Cz6799nmp+\n oaY+IXA/t7gmLuYYUFTXAetz1ButH3i1PfC7rDDar4xYfx0uc7t264k0zYg/tWre/OnF\n kxjQ==","X-Gm-Message-State":"AOJu0YzEBIV1t7koZ26EVizommjmrABJhYk1D2E7LUo72QJ+MdTEQzSI\n HVzUY9COehdWxIW+/RStMu+3UoQoEu5u/Wx0/NZ+NHp/prvy73mUC1aznrgOn4WzzgWFciXuB0X\n hsA4HWtj56Rq4aaEIeV7frD775AxVaxB93TfSHn7S+gXzDAiYW6SSokfpQxLh4RmBkJVlm805eq\n sio7H6wJwGG53Hx+MseJleOlx2amFxHA8cwQ==","X-Gm-Gg":"AeBDiesq/jWtVsCx3yS82CF/4fdkwM/VeJjNP8oX0DusUyvmLA4jKJGtgl3Q2OKEhMV\n SNBnhKqKtULHFEcrES5UU1nIbv7phoYnqzh1gH5JG9OyLP1e6RgtfBE0LH1n6tFVDyNt6qxfG9Z\n UAUsBUvONtr7O6jPkvh7BZvtJJO5vbGvAN9zoRvNNar7BnsaaqTMoC0n5bQEzBaJ2z2m43+enDQ\n gu75+gFU6QPGYhjAH7yQ255R4n6rlfMrg8Cw0cJQeUK38RqdBxvCu6GRl5Ux3HhCnxj8pbfGhnZ\n CA==","X-Received":["by 2002:a05:690c:9510:b0:7ba:ef98:9717 with SMTP id\n 00721157ae682-7baef98a74bmr31317457b3.14.1776692398286;\n Mon, 20 Apr 2026 06:39:58 -0700 (PDT)","by 2002:a05:690c:9510:b0:7ba:ef98:9717 with SMTP id\n 00721157ae682-7baef98a74bmr31316587b3.14.1776692396918; Mon, 20 Apr 2026\n 06:39:56 -0700 (PDT)"],"MIME-Version":"1.0","References":"<20260418232807.3364700-1-ppalka@redhat.com>\n <CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>\n <d5572fc1-d066-2b6b-b008-7a5e29ee9b14@idea>","In-Reply-To":"<d5572fc1-d066-2b6b-b008-7a5e29ee9b14@idea>","From":"Tomasz Kaminski <tkaminsk@redhat.com>","Date":"Mon, 20 Apr 2026 15:39:45 +0200","X-Gm-Features":"AQROBzB6Lvhntxa3Y9w61LJYaPtm4Iz_FVULnaO-UQfq0e3EWbe2bYJBE1Z-RZs","Message-ID":"\n <CAKvuMXB64JLtF3Y3_L3dxQ7jw3MAVQbiOj2ii90_Bd6JEyrSSg@mail.gmail.com>","Subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","To":"Patrick Palka <ppalka@redhat.com>","Cc":"gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org, jason@redhat.com,\n Jonathan Wakely <jwakely@redhat.com>","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"erqNPaEhKuvtIGaBAX_B9AYNc2fHFuwx61AOWEuick8_1776692398","X-Mimecast-Originator":"redhat.com","Content-Type":"multipart/alternative; boundary=\"00000000000031ab13064fe46fa8\"","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}},{"id":3679602,"web_url":"http://patchwork.ozlabs.org/comment/3679602/","msgid":"<441e2856-ae25-e423-1789-9a8c08cdaea7@idea>","list_archive_url":null,"date":"2026-04-20T21:06:49","subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","submitter":{"id":78319,"url":"http://patchwork.ozlabs.org/api/people/78319/","name":"Patrick Palka","email":"ppalka@redhat.com"},"content":"On Mon, 20 Apr 2026, Tomasz Kaminski wrote:\n\n> \n> \n> On Mon, Apr 20, 2026 at 2:44 PM Patrick Palka <ppalka@redhat.com> wrote:\n>       On Mon, 20 Apr 2026, Tomasz Kaminski wrote:\n> \n>       >\n>       >\n>       > On Sun, Apr 19, 2026 at 1:28 AM Patrick Palka <ppalka@redhat.com> wrote:\n>       >       Changes in v2:\n>       >         - Added code comment\n>       >         - Clarified commit message, removed red herring about trivial\n>       >           destructibility.\n>       >         - Extended test with 'x6' direct-initialization that avoids invoking\n>       >           optional's move constructor.  This testcase, when instantiated with T=B,\n>       >           demonstrates that non-trivially-copyable optional is also affected\n>       >           and we must set _M_empty even in that case.\n>       >\n>       >       -- >8 --\n>       >\n>       >       When an optional that contains a value is cleared, _M_destroy invokes the\n>       >       destructor of the contained value _Storage::_M_value, leaving the union\n>       >       _Storage without an active member.  While this is benign at runtime, a\n>       >       union suboject with no active member violates core constant expression\n>       >       requirements and in turn an optional in this state can't be used as a\n>       >       constant initializer, which Clang and recent GCC (since r16-3022) correctly\n>       >       diagnose.\n>       >\n>       > I am not aware of this limitation, and I do not see how if fails out of the wording,\n>       > The constituent values explicitly exclude inactive union members:\n>       > https://eel.is/c++draft/intro.objehttps://docs.google.com/https://docs.google.com/ct#12.2, so empty union simply has none.\n> \n>       That term \"constituent values\" seems to have been introduced in C++26 by\n>       P2668R5 and so it's not clear to what extent that wording applies to C++20 :/\n> \n> For C++20 we have: https://timsong-cpp.github.io/cppwp/n4861/dcl.constexpr#10\n> And there seem be no limitation of union without active members here: \n> https://timsong-cpp.github.io/cppwp/n4861/expr.const#5\n> \n>       >\n>       > Could you please update the commit description, to reflect actual problem\n>       > as described by Jason here:\n>       > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124910#c13\n> \n>       [class.union.general]/2 says: In a union, a non-static data member is\n>       active if its name refers to an object whose lifetime has begun and has\n>       not ended.  How does destroying an active member not make it inactive?\n> \n> I think the point of comment, is that this change is a workaround for GCC bug\n> (the _M_value member is still considered active member, but it shouldn't).\n\nI see, that makes sense.  So Clang and GCC happened to have (more or less)\nthe same bug!  With Jason's fix r16-8767 from today it appears my\n<optional> change is no longer necessary for GCC, but I suppose we still\nwant it for Clang?\n\n> \n> \n>       >\n>       >  \n>       >\n>       >       To fix this, this patch makes _M_destroy activate the dummy union member\n>       >       _M_empty after destroying _M_value to ensure that the union always has\n>       >       an active member throughout its lifetime.  We use std::construct_at\n>       >       instead of simple assignment to work around a front end bug (comment #3\n>       >       in the PR).  Doing so means we don't activate the member in C++17 mode,\n>       >       which should be fine; I don't think it's possible to disengage an engaged\n>       >       optional using only the C++17 constexpr optional operations.\n>       >\n>       >               PR c++/124910\n>       >\n>       >       libstdc++-v3/ChangeLog:\n>       >\n>       >               * include/std/optional (_Optional_payload_base::_M_destroy)\n>       >               [__cpp_lib_optional >= 202106L]: During constant evaluation,\n>       >               after invoking destructor of _M_value, use construct_at to\n>       >               activate _M_empty.\n>       >               * testsuite/20_util/optional/constexpr/124910.cc: New test.\n>       >\n>       >       Reviewed-by: Jonathan Wakely <jwakely@redhat.com>\n>       >       ---\n>       >        libstdc++-v3/include/std/optional             |  6 ++\n>       >        .../20_util/optional/constexpr/124910.cc      | 74 +++++++++++++++++++\n>       >        2 files changed, 80 insertions(+)\n>       >        create mode 100644 libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>       >\n>       >       diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional\n>       >       index 0f4cf0bd1ef6..49ba7b6b45dd 100644\n>       >       --- a/libstdc++-v3/include/std/optional\n>       >       +++ b/libstdc++-v3/include/std/optional\n>       >       @@ -321,6 +321,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>       >              {\n>       >               _M_engaged = false;\n>       >               _M_payload._M_value.~_Stored_type();\n>       >       +#if __cpp_lib_optional >= 202106L // full constexpr support\n>       >       +       if (std::is_constant_evaluated())\n>       >       +         // Ensure union _M_payload always has an active member, for sake\n>       >       +         // of the core constant expression requirements.\n>       >       +         std::construct_at(std::__addressof(_M_payload._M_empty));\n>       >       +#endif\n>       >              }\n>       >\n>       >        #if __cplusplus >= 202002L\n>       >       diff --git a/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>       >       new file mode 100644\n>       >       index 000000000000..2f61f7e4e775\n>       >       --- /dev/null\n>       >       +++ b/libstdc++-v3/testsuite/20_util/optional/constexpr/124910.cc\n>       >       @@ -0,0 +1,74 @@\n>       >       +// { dg-do compile { target c++20 } }\n>       >       +\n>       >       +// PR124910 - bogus 'std::optional{...}' is not a constant expression error\n>       >       +// after resetting it via '= nullopt'\n>       >       +\n>       >       +#include <optional>\n>       >       +\n>       >       +struct A\n>       >       +{\n>       >       +  constexpr A(int m) : m(m) { }\n>       >       +  int m;\n>       >       +};\n>       >       +\n>       >       +struct B\n>       >       +{\n>       >       +  constexpr B(int m) : m(m) { }\n>       >       +  constexpr ~B() { }\n>       >       +  int m;\n>       >       +};\n>       >       +\n>       >       +static_assert(   std::is_trivially_destructible_v<int> );\n>       >       +static_assert(   std::is_trivially_destructible_v<A> );\n>       >       +static_assert( ! std::is_trivially_destructible_v<B> );\n>       >       +\n>       >       +template<class T>\n>       >       +void\n>       >       +do_test()\n>       >       +{\n>       >       +  constexpr std::optional<T> x1 = [] {\n>       >       +    std::optional<T> o = 1;\n>       >       +    o = std::nullopt;\n>       >       +    return o;\n>       >       +  }();\n>       >       +\n>       >       +  constexpr std::optional<T> x2 = [] {\n>       >       +    std::optional<T> o = 1;\n>       >       +    o.reset();\n>       >       +    return o;\n>       >       +  }();\n>       >       +\n>       >       +  constexpr std::optional<T> x3 = [] {\n>       >       +    std::optional<T> o1 = 1;\n>       >       +    std::optional<long> o2;\n>       >       +    o1 = o2;\n>       >       +    return o1;\n>       >       +  }();\n>       >       +\n>       >       +  constexpr std::optional<T> x4 = [] {\n>       >       +    std::optional<T> o1 = 1;\n>       >       +    std::optional<long> o2;\n>       >       +    o1 = std::move(o2);\n>       >       +    return o1;\n>       >       +  }();\n>       >       +\n>       >       +  constexpr std::optional<T> x5 = [] {\n>       >       +    std::optional<T> o1 = 1;\n>       >       +    std::optional<T> o2;\n>       >       +    std::swap(o1, o2);\n>       >       +    return o1;\n>       >       +  }();\n>       >       +\n>       >       +  struct C : std::optional<T> {\n>       >       +    constexpr C() : std::optional<T>(1) { this->reset(); }\n>       >       +  };\n>       >       +  constexpr C x6;\n>       >       +}\n>       >       +\n>       >       +int\n>       >       +main()\n>       >       +{\n>       >       +  do_test<int>();\n>       >       +  do_test<A>();\n>       >       +  do_test<B>();\n>       >       +}\n>       >       --\n>       >       2.54.0.rc1.54.g60f07c4f5c\n>       >\n>       >\n>       >\n> \n> \n>","headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=RET7T4o0;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=RET7T4o0","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.129.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzyjx3lMzz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 21 Apr 2026 07:07:32 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 05E0D4B3589F\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 21:07:30 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by sourceware.org (Postfix) with ESMTP id 8B0E94B7A1C3\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 21:06:53 +0000 (GMT)","from mail-qk1-f200.google.com (mail-qk1-f200.google.com\n [209.85.222.200]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-117-7XfbzTJSPWODmGZXnDP9NA-1; Mon, 20 Apr 2026 17:06:51 -0400","by mail-qk1-f200.google.com with SMTP id\n af79cd13be357-8eab2831ba2so37517985a.3\n for <gcc-patches@gcc.gnu.org>; Mon, 20 Apr 2026 14:06:51 -0700 (PDT)","from [2600:4040:aa66:bf00:9e8e:99ff:fed1:71f]\n ([2600:4040:aa66:bf00:9e8e:99ff:fed1:71f])\n by smtp.gmail.com with ESMTPSA id\n af79cd13be357-8eb61bc0d3dsm304621485a.26.2026.04.20.14.06.49\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 20 Apr 2026 14:06:49 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 05E0D4B3589F","OpenDKIM Filter v2.11.0 sourceware.org 8B0E94B7A1C3"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 8B0E94B7A1C3","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 8B0E94B7A1C3","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776719213; cv=none;\n b=prOXJlcpWURMtLDSFrXM9vZzCuzAC+MNdg0KVxBxymPByiFrY0zxF4rybYtwu6zldXrI4xvgY6X88AGSXoQ/u2cXJPlOvXuWbZMugYzjTMe1zQUw+0PKCjw594A7RWyMMJ6kpw1f1fu9kb8AmWqmUDrs+1f+i2c07c6VLlixyJI=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776719213; c=relaxed/simple;\n bh=zy3D2qp2Wzl9rYiXwkoDugJmcWUNxOVqaaDKCI635Zg=;\n h=DKIM-Signature:From:Date:To:Subject:Message-ID:MIME-Version;\n b=ZNCmg+ZxoO5Xh17pP9i7iSdCe/xdTjSlnMnqOALmYmdV60zpdHEwGGcYcrLcsbvz+hVOVfORhXuuzY9xmYcAf0CUjkzB25gG07FZd+JJZ+GKG/oGLbhvceG3h2gLVWDKV+xxMLCjM3If/17bWc93766UO16Z3NVwcGgmcf4itsE=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776719213;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=maReRmCzCvlAw1JNbwyyUgKoElOLYUyBVyF3308htsg=;\n b=RET7T4o05xUs240EErj4/JLg8+IPE/O0Jk521IRDjOE/1BRxfvpcweN7ysZi2aeSePaac+\n rDy2J4KZepeXzbc8kW7aidluFyKmqi9YXDhxQ8ahRO1GAPvkPZjqNs2E68GTcmszdTLY6N\n RAyaKiX0vbZOccePg2ysn4oSK+UeB8E=","X-MC-Unique":"7XfbzTJSPWODmGZXnDP9NA-1","X-Mimecast-MFC-AGG-ID":"7XfbzTJSPWODmGZXnDP9NA_1776719211","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776719211; x=1777324011;\n h=mime-version:references:message-id:in-reply-to:subject:cc:to:date\n :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=jPFFJ8QCwF0x9QIZ8IilVmHzyb1X4YvN/mnXsKEiYaU=;\n b=OS6dbV297pgNOvVid/4bwAwxp31M8ZjgFl1SHAoz/D563iDFEvXtZlBrGQe6HxtBoX\n C9jY3/fgLodKQj3GdUSWdc/HONsJVA4nO9VWNwlcR9ZEhJBbbZMhjV9355xM4WAu3tAX\n Ap5uWmLtCPt713ulG4dI37sLlk4p6gN+gHxpfZHR5MprHoLnmobMLU4aTbLJuvN7farg\n J5G859nrpQ7f6YgYMUVJW0CXxlufv6fTYcnfG9xogDbYi0KJxCvhHQK18ITKnPMLmwGY\n xBFGDVRNLVIhkzK9t6XB8XBlWayO5Ij0/PiG0MUdDsJOi2kjZh0dVVX1A2p8Mc9KQLAL\n bM6A==","X-Forwarded-Encrypted":"i=1;\n AFNElJ/OesAo9iKV4pWG9C8rHeKCmz8R6VA/82Ve1OkRYghf3eCqTpkodDY3I8o6Yq+ry4GdmyXG4R0QRUNgVQ==@gcc.gnu.org","X-Gm-Message-State":"AOJu0YwxZbaZKrxJHuO2DvhwUchGCng78TKNZLPtcwaYd6Wt0oI8wcCt\n EWVfeDSDX9Kv1bSlaUZ8y3VI7hq3wuNzBE3WImxc6PjPmjwBIAIIDoBHx19k73OZW8oA062JpL7\n kaYYp57+MuSoecgS6eqwbthN0ScQtDI5OomceqC8nLQKhki3eGtQCNN2CxHM=","X-Gm-Gg":"AeBDietvCPnA3rDoWXvpWPs+I04j0y3dYIcQQsddzf0a5hs9ny1Q2x8AJVhKaLMfxpe\n xZ5kPJ4+q+491FJjokX+MsKqbd/x5/8b3MUIA010FNWb12zyqSfrO98BfGgMZv41IODGfpzr6To\n f5xPOgUS750eOv/u2Rp0Crx1oSIK2761kX9+zqPH18Cb0RNi4C2UP2lYSYVl3pl1bF6/FnmWslJ\n VN/veLNZN9aAi3a2/6s/dvo/PuxHMoaJRUvbHeTqm3Wp7wJ2tmjuTrs7v81KrtAVa5pxp5xOcj8\n u0bFvzr6wPpoRhS/3zvFHaqBnxgjjgwV5OvKKzwi9te0BW3A/VlnG3vepE1t5PsfDX5C8G45Yw9\n sr93731gOUfg7Cj21MPyTZJUiKp1/wJ8jVKoHokJ0Ukjh4NySyQRY2REQHqizXyl5","X-Received":["by 2002:a05:620a:29c3:b0:8cd:86a2:340c with SMTP id\n af79cd13be357-8e78f059175mr1315453985a.1.1776719211064;\n Mon, 20 Apr 2026 14:06:51 -0700 (PDT)","by 2002:a05:620a:29c3:b0:8cd:86a2:340c with SMTP id\n af79cd13be357-8e78f059175mr1315450485a.1.1776719210505;\n Mon, 20 Apr 2026 14:06:50 -0700 (PDT)"],"From":"Patrick Palka <ppalka@redhat.com>","X-Google-Original-From":"Patrick Palka <patrick@idea>","Date":"Mon, 20 Apr 2026 17:06:49 -0400 (EDT)","To":"Tomasz Kaminski <tkaminsk@redhat.com>","cc":"Patrick Palka <ppalka@redhat.com>, gcc-patches@gcc.gnu.org,\n libstdc++@gcc.gnu.org, jason@redhat.com,\n Jonathan Wakely <jwakely@redhat.com>","Subject":"Re: [committed v2] libstdc++: Fix constantness of engaged ->\n disengaged std::optional [PR124910]","In-Reply-To":"\n <CAKvuMXB64JLtF3Y3_L3dxQ7jw3MAVQbiOj2ii90_Bd6JEyrSSg@mail.gmail.com>","Message-ID":"<441e2856-ae25-e423-1789-9a8c08cdaea7@idea>","References":"<20260418232807.3364700-1-ppalka@redhat.com>\n <CAKvuMXBMyE45px+S0z+mZFOtF4VPRCfBCR_NTssTR6XgXrZ4zA@mail.gmail.com>\n <d5572fc1-d066-2b6b-b008-7a5e29ee9b14@idea>\n <CAKvuMXB64JLtF3Y3_L3dxQ7jw3MAVQbiOj2ii90_Bd6JEyrSSg@mail.gmail.com>","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"f_HPS6AjT8I2F6KVvcEBaS8UnavMnbY9qXXxyfwCy5Y_1776719211","X-Mimecast-Originator":"redhat.com","Content-Type":"multipart/mixed; boundary=\"8323329-486741551-1776719209=:113381\"","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}}]