From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id uR/7Igku4mpxpj4AWB0awg (envelope-from ) for ; Wed, 28 Oct 2026 13:16:57 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=EVMopc/O; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 853951E007; Wed, 28 Oct 2026 13:16:57 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id E55601E007 for ; Wed, 28 Oct 2026 13:16:55 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7FCA04BA23CE for ; Wed, 28 Oct 2026 17:16:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7FCA04BA23CE Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=EVMopc/O Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id C1A0A4BA2E07 for ; Wed, 28 Oct 2026 17:16:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C1A0A4BA2E07 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C1A0A4BA2E07 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793207785; cv=none; b=USm2i/l3YBS6bP+BInNZ0iEytAwjiZmUEnQiJvUANQn61wvG45yPYFg5SYnW/Z3RV1Udz/II7Wr5y0addb2A1ggbQS3MPfQyfnBZRSuMBAN3Skmo4Edqjxgwi97eC1IlNoPM/NEDDXro2XhXx3edZx2zfX3TrCCOQd8z5MiykJU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793207785; c=relaxed/simple; bh=pL47xcGR9Qa5vRIXGW79QUoO0FFFgqJHR6EYS3bXdJQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=SWMuQEemCpTfCIN68IxVqOX/L2DnlguwqnJAESHZOefwGEwWKk1OACu2vk1npphR/+OM5XEX+4OmGl3BWCFpgjc251ZQZbwWdpiE/B2BQjqKXjHF+tUwZJryug/Ylk2oC1g2SmMkpABzNizKAq/uDB1yRqw3c6MUMMcRxmGoHhc= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=EVMopc/O DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C1A0A4BA2E07 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1793207785; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9rONaWrYWcRTokzD53X7lpJxmOVIpWjYidXnws1TF28=; b=EVMopc/O16tZ5BHEhxuGNgJy+AdaSZ80Z3J/twgll5R2cUptvQLmVlyqAiaJLm76PxDUbc O2dCJOFRtQYBow5PlzFS0gkVFe2i4Vha4lmIqKhnkwc0EYiYiaJZT2NTw3C3oTCL/xtum0 mR7cdhjR5+M7IRN/iiE9zGoBr2W0ajo= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-252-Jspfxp_2NU-KbaOq1S8Epg-1; Wed, 28 Oct 2026 13:16:22 -0400 X-MC-Unique: Jspfxp_2NU-KbaOq1S8Epg-1 X-Mimecast-MFC-AGG-ID: Jspfxp_2NU-KbaOq1S8Epg_1793207781 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-48b027578a4so953719f8f.3 for ; Wed, 28 Oct 2026 10:16:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793207781; x=1793812581; h=content-transfer-encoding:content-type:mime-version:message-id:date :references:in-reply-to:subject:to:from:x-gm-gg:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to:content-type; bh=U8/ihgSIrzKNwu7ydiUGEj/uZRjy5wgsfcjLvWhsFjA=; b=XSvuX9ZzYWKn+f89BbKQAZlpEbcnFApafBZsq3dww4ofH4MKGibR1TwGa2owuUik92 ASqcvsGEh8Ilc5XlvaRlc7JZsZB3/Pcdvr1UlXpfoUIDRrAlpQohpMxQpbfqWNpzxodV MGPtXWH7ja0x0lHG2x8dMs7RS3gcH/bSvOM1JF1aDsAUBbB5FA66IjLH98++JpASHwMT e9PxqHIq0E58mCNE8AdmEBLR3AxrDbGGBlumx9AEftdoAZo9j5oN8OElp1wipBaJJrph 5BDPFNVpLiHxfu6GMsmJRvgENytm0fNsOpq/9I9EHnAcEgwD9cwkHPoQhPT9j300XK3s 37GQ== X-Forwarded-Encrypted: i=1; AKwUvBxr7yhjoYTHHi4jx8hOW25p4tfm1sN1zbHmSWY5P4ZMLfsnBveAVkYQQ0lEzzpeP6ULtFwHyfvWOQdFHw==@sourceware.org X-Gm-Message-State: AFq9FYKYkYnHe/sgGRx72I8nKulpdmV2JFXYTPAVXrS5K9Nr/DEMZxL8 twtEXunlMJ8fjSZo6ZGA99LLGp8uwWNY/go/MpQnQTh08rxEB6q8lejBOMhiTtpG2N3JPne3Daf P2rbdOcLyO1X+bmQTt5zXkOV8kzJpyF1nwm4Tw2+DSI2pxCGYMVh1G3g+67djDxKO4Tiz6vE= X-Gm-Gg: AYBFou2o33bnPXPI7wod1WFUDGEs6BXfILYPPcSBiCSgGRw7JdrCHZ2+zSjNNcVMBvA dBoJqG7eL7qC+EEI31qF4j8BKdv0uw/Zwsy1zQQio91NC97DUU9nAkLej/mn2oHX/qplvnXKnmv CMIdSMjob/gbe/rotiFrTbpNP9JRivrpt/f4t59NlW57IdIl0gl6KscVD7N/03jte/uRt+4ldn0 UPiqPhQ0Udsd3bI0ILEhwSMbxSER5jnHA+IlsbrCBuP0jsNfnYqwWA2c8dTbtjez6GtrPjqOL8o ++mFTGMNvIVDNB7PCLAq/OW7wjbz7ywKpPOYDWciyoQpfXUKhVpNFuKXJ7r0mAeGZvlW48oTaSO D3nCEXzFB/72Mxp4Oo+s+e76LdNpiqbmSguQj3m//SpqeAXo= X-Received: by 2002:a05:600c:83c5:b0:4a8:c6a0:c08f with SMTP id 5b1f17b1804b1-4a967e8c05emr78280165e9.35.1793207781084; Wed, 28 Oct 2026 10:16:21 -0700 (PDT) X-Received: by 2002:a05:600c:83c5:b0:4a8:c6a0:c08f with SMTP id 5b1f17b1804b1-4a967e8c05emr78279185e9.35.1793207780463; Wed, 28 Oct 2026 10:16:20 -0700 (PDT) Received: from localhost ([2a00:23c6:e11d:fb01:6748:4fce:3e30:6e23]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48e3ebc3dd7sm29707130f8f.15.2026.10.28.10.16.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2026 10:16:19 -0700 (PDT) From: Andrew Burgess To: Tom de Vries , gdb-patches@sourceware.org Subject: Re: [PATCH] [gdb/build] Fix Wmaybe-uninitialized false positive for ui_out_emit_type In-Reply-To: <20261026163904.156660-1-tdevries@suse.de> References: <20261026163904.156660-1-tdevries@suse.de> Date: Wed, 28 Oct 2026 17:16:18 +0000 Message-ID: <87se1p7nkt.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 7Hjmjs65MTnq_XTHwxRjFmnkcgeHjXK6o4X4snJfAm4_1793207781 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Tom de Vries writes: > With an aarch64-linux -O2 build with gcc 16.2.1, I run into: > ... > In file included from gdb/exceptions.h:23, > from gdb/symtab.c:21: > In destructor =E2=80=98ui_out_emit_type::~ui_out_emit_type() [with = ui_out_type Type =3D ui_out_type_tuple]=E2=80=99, > inlined from =E2=80=98constexpr void std::_Optional_payload_base<_Tp>= ::_M_destroy() [with _Tp =3D ui_out_emit_type]=E2=80=99 = at /usr/include/c++/16/optional:325:35, > inlined from =E2=80=98constexpr void std::_Optional_payload_base<_Tp>= ::_M_reset() [with _Tp =3D ui_out_emit_type]=E2=80=99 at= /usr/include/c++/16/optional:361:14, > inlined from =E2=80=98constexpr void std::_Optional_payload_base<_Tp>= ::_M_reset() [with _Tp =3D ui_out_emit_type]=E2=80=99 at= /usr/include/c++/16/optional:358:7, > inlined from =E2=80=98std::_Optional_payload<_Tp, false, _Copy, _Move= >::~_Optional_payload() [with _Tp =3D ui_out_emit_type; = bool _Copy =3D false; bool _Move =3D false]=E2=80=99 at /usr/include/c++/16= /optional:484:65, > inlined from =E2=80=98std::_Optional_base, false, false>::~_Optional_base()=E2=80=99 at /usr/include/c++/16/= optional:508:12, > inlined from =E2=80=98std::optional >::~optional()=E2=80=99 at /usr/include/c++/16/optional:812:11, > inlined from =E2=80=98void info_sources_worker(ui_out*, bool, const i= nfo_sources_filter&)=E2=80=99 at gdb/symtab.c:4544:1: > gdb/ui-out.h:428:18: warning: =E2=80=98*(ui_out_emit_type*)((char*)&output_tuple + offsetof(std::optional >,std::optional >::.std::_Optional_base, false, false>::= _M_payload.std::_Optional_payload, fals= e, false, false>::.std::_Optional_payload, true, false, false>::.std::_Optional_payload_base >::_M_payload)).ui_out_emit_type::m_uiout=E2=80=99 may be used uninitialized [-Wmaybe-uninitialize= d] > 428 | m_uiout->end (Type); > | ~~~~~~~~~~~~~^~~~~~ > gdb/symtab.c: In function =E2=80=98void info_sources_worker(ui_out*, bool= , const info_sources_filter&)=E2=80=99: > gdb/symtab.c:4477:36: note: =E2=80=98*(ui_out_emit_type*)((char*)&output_tuple + offsetof(std::optional >,std::optional >::= .std::_Optional_base, false, false>::_M= _payload.std::_Optional_payload, false,= false, false>::.std::_Optional_payload, true, false, false>::.std::_Optional_payload_base >::_M_payload)).ui_out_emit_type::m_uiout=E2=80=99 was declared here > 4477 | std::optional output_tuple; > | ^~~~~~~~~~~~ > ... > > The code pattern triggering this is: > ... > std::optional output_tuple; > for (objfile &objfile : current_program_space->objfiles ()) > { > if (group_by_objfile) > =09output_tuple.emplace (uiout, nullptr); > ... > if (group_by_objfile) > output_tuple.reset (); > } > ... > > This is a false positive. > > We can get rid of the warning by making changes to the function: > - making the reset unconditional, or > - moving the output_tuple declaration into the loop. > > But instead, consider that the class ui_out_emit_type wraps a pointer. > > An std::optional has three possible states: !has_value, nullptr o= r > non-nullptr. If we don't use the nullptr state, using std::optional > is overkill, and we can use nullptr instead of !has_value. > > Rewrite ui_out_emit_type to provide some of the std::optional interface: > - default constructor > - reset > - emplace > - has_value > with protected access, and derive an opt_ui_out_emit_type which inherits = those > with public access. > > As a side effect, we get rid of the warning. > > Tested on aarch64-linux. > > Tested on x86_64-linux with gcc 7.5.0, where all the Wmaybe-uninitialized > reported in PR31150 are now fixed. > > Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D31150 > --- > gdb/breakpoint.c | 11 +++---- > gdb/disasm.c | 8 ++--- > gdb/mi/mi-cmd-stack.c | 2 +- > gdb/mi/mi-main.c | 2 +- > gdb/python/py-framefilter.c | 6 ++-- > gdb/record-btrace.c | 8 ++--- > gdb/symtab.c | 4 +-- > gdb/thread.c | 2 +- > gdb/ui-out.h | 63 ++++++++++++++++++++++++++++++++++--- > 9 files changed, 80 insertions(+), 26 deletions(-) > > diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c > index 0f5360c4ce5..9995c6ab21b 100644 > --- a/gdb/breakpoint.c > +++ b/gdb/breakpoint.c > @@ -7150,8 +7150,8 @@ print_one_breakpoint_location (struct breakpoint *b= , > =09(uiout->test_flags (fix_breakpoint_script_output) > =09 || fix_breakpoint_script_output_globally); > =20 > - std::optional tuple_emitter; > - std::optional list_emitter; > + opt_ui_out_emit_tuple tuple_emitter; > + opt_ui_out_emit_list list_emitter; > =20 > if (use_fixed_output) > =09list_emitter.emplace (uiout, "script"); > @@ -7224,8 +7224,7 @@ print_one_breakpoint (breakpoint *b, const bp_locat= ion **last_loc, int allflag) > =3D (uiout->test_flags (fix_multi_location_breakpoint_output) > || fix_multi_location_breakpoint_output_globally); > =20 > - std::optional bkpt_tuple_emitter (std::in_place, ui= out, > -=09=09=09=09=09=09 "bkpt"); > + opt_ui_out_emit_tuple bkpt_tuple_emitter (uiout, "bkpt"); > bool printed =3D print_one_breakpoint_location (b, NULL, 0, last_loc, > =09=09=09=09=09=09allflag, false); > =20 > @@ -7260,7 +7259,7 @@ print_one_breakpoint (breakpoint *b, const bp_locat= ion **last_loc, int allflag) > =09=09 || !b->first_loc ().enabled > =09=09 || b->first_loc ().disabled_by_cond)))) > =09{ > -=09 std::optional locations_list; > +=09 opt_ui_out_emit_list locations_list; > =20 > =09 /* For MI version <=3D 2, keep the behavior where GDB outputs an in= valid > =09 MI record. For later versions, place breakpoint locations in a > @@ -10278,7 +10277,7 @@ watchpoint::print_it (const bpstat *bs) const > =20 > string_file stb; > =20 > - std::optional tuple_emitter; > + opt_ui_out_emit_tuple tuple_emitter; > switch (this->type) > { > case bp_watchpoint: > diff --git a/gdb/disasm.c b/gdb/disasm.c > index 01361fe4323..67f56faaecd 100644 > --- a/gdb/disasm.c > +++ b/gdb/disasm.c > @@ -610,8 +610,8 @@ do_mixed_source_and_assembly_deprecated > =20 > ui_out_emit_list asm_insns_list (uiout, "asm_insns"); > =20 > - std::optional outer_tuple_emitter; > - std::optional inner_list_emitter; > + opt_ui_out_emit_tuple outer_tuple_emitter; > + opt_ui_out_emit_list inner_list_emitter; > =20 > for (i =3D 0; i < newlines; i++) > { > @@ -767,8 +767,8 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch= , > =20 > ui_out_emit_list asm_insns_emitter (uiout, "asm_insns"); > =20 > - std::optional tuple_emitter; > - std::optional list_emitter; > + opt_ui_out_emit_tuple tuple_emitter; > + opt_ui_out_emit_list list_emitter; > =20 > last_symtab =3D NULL; > last_line =3D 0; > diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c > index a3b577032ce..335f7e1fbef 100644 > --- a/gdb/mi/mi-cmd-stack.c > +++ b/gdb/mi/mi-cmd-stack.c > @@ -533,7 +533,7 @@ list_arg_or_local (const struct frame_arg *arg, enum = what_to_list what, > =3D=3D lang_vars_shadowing::HIDE && shadowed && already_printed) > return; > =20 > - std::optional tuple_emitter; > + opt_ui_out_emit_tuple tuple_emitter; > if (values !=3D PRINT_NO_VALUES || what =3D=3D all) > tuple_emitter.emplace (uiout, nullptr); > =20 > diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c > index d39b8eeab87..dcf76db39a3 100644 > --- a/gdb/mi/mi-main.c > +++ b/gdb/mi/mi-main.c > @@ -2455,7 +2455,7 @@ print_variable_or_computed (const char *expression,= enum print_values values) > else > val =3D expr->evaluate (); > =20 > - std::optional tuple_emitter; > + opt_ui_out_emit_tuple tuple_emitter; > if (values !=3D PRINT_NO_VALUES) > tuple_emitter.emplace (uiout, nullptr); > uiout->field_string ("name", expression); > diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c > index b67431cf8c9..9899470cc0f 100644 > --- a/gdb/python/py-framefilter.c > +++ b/gdb/python/py-framefilter.c > @@ -321,7 +321,7 @@ py_print_single_arg (struct ui_out *out, > else > val =3D fv; > =20 > - std::optional maybe_tuple; > + opt_ui_out_emit_tuple maybe_tuple; > =20 > /* MI has varying rules for tuples, but generally if there is only > one element in each item in the list, do not start a tuple. The > @@ -557,7 +557,7 @@ enumerate_locals (PyObject *iter, > struct symbol *sym; > const struct block *sym_block; > int local_indent =3D 8 + (8 * indent); > - std::optional tuple; > + opt_ui_out_emit_tuple tuple; > =20 > gdbpy_ref<> item (PyIter_Next (iter)); > if (item =3D=3D NULL) > @@ -814,7 +814,7 @@ py_print_frame (PyObject *filter, frame_filter_flags = flags, > return EXT_LANG_BT_OK; > } > =20 > - std::optional tuple; > + opt_ui_out_emit_tuple tuple; > =20 > /* -stack-list-locals does not require a > wrapping frame attribute. */ > diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c > index dae243ee2db..5c1bb606130 100644 > --- a/gdb/record-btrace.c > +++ b/gdb/record-btrace.c > @@ -763,8 +763,8 @@ btrace_find_line_range (CORE_ADDR pc) > =20 > static void > btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout= , > -=09=09 std::optional *src_and_asm_tuple, > -=09=09 std::optional *asm_list, > +=09=09 opt_ui_out_emit_tuple *src_and_asm_tuple, > +=09=09 opt_ui_out_emit_list *asm_list, > =09=09 gdb_disassembly_flags flags) > { > print_source_lines_flags psl_flags; > @@ -803,8 +803,8 @@ btrace_insn_history (struct ui_out *uiout, > =20 > ui_out_emit_list list_emitter (uiout, "asm_insns"); > =20 > - std::optional src_and_asm_tuple; > - std::optional asm_list; > + opt_ui_out_emit_tuple src_and_asm_tuple; > + opt_ui_out_emit_list asm_list; > =20 > gdb_pretty_print_disassembler disasm (gdbarch, uiout); > =20 > diff --git a/gdb/symtab.c b/gdb/symtab.c > index b082a488b88..18fdc66d1f7 100644 > --- a/gdb/symtab.c > +++ b/gdb/symtab.c > @@ -4474,8 +4474,8 @@ info_sources_worker (struct ui_out *uiout, > output_source_filename_data data (uiout, filter); > =20 > ui_out_emit_list results_emitter (uiout, "files"); > - std::optional output_tuple; > - std::optional sources_list; > + opt_ui_out_emit_tuple output_tuple; > + opt_ui_out_emit_list sources_list; > =20 > gdb_assert (group_by_objfile || uiout->is_mi_like_p ()); > =20 > diff --git a/gdb/thread.c b/gdb/thread.c > index e14254619e3..5fa2bb6915c 100644 > --- a/gdb/thread.c > +++ b/gdb/thread.c > @@ -1296,7 +1296,7 @@ print_thread_info_1 (struct ui_out *uiout, const ch= ar *requested_threads, > /* For backward compatibility, we make a list for MI. A table is > preferable for the CLI, though, because it shows table > headers. */ > - std::optional list_emitter; > + opt_ui_out_emit_list list_emitter; > std::optional table_emitter; > =20 > /* We'll be switching threads temporarily below. */ > diff --git a/gdb/ui-out.h b/gdb/ui-out.h > index 26d4a6b7d0e..8717d93539d 100644 > --- a/gdb/ui-out.h > +++ b/gdb/ui-out.h > @@ -418,25 +418,80 @@ class ui_out_emit_type > public: > =20 > ui_out_emit_type (struct ui_out *uiout, const char *id =3D nullptr) > - : m_uiout (uiout) > { > - uiout->begin (Type, id); > + emplace (uiout, id); > } > =20 > ~ui_out_emit_type () > { > - m_uiout->end (Type); > + reset (); > } > =20 > DISABLE_COPY_AND_ASSIGN (ui_out_emit_type); > =20 > +protected: > + > + ui_out_emit_type () =3D default; > + > + /* Support the std::optional interface, see opt_ui_out_emit_type. */ > + ui_out_emit_type &emplace (struct ui_out *uiout, const char *id =3D nu= llptr) > + { > + reset (); > + uiout->begin (Type, id); > + m_uiout =3D uiout; > + return *this; > + } > + > + /* Support the std::optional interface, see opt_ui_out_emit_type. */ > + void reset () noexcept > + { > + if (!has_value ()) > + return; > + > + m_uiout->end (Type); > + m_uiout =3D nullptr; > + } > + > + /* Support the std::optional interface, see opt_ui_out_emit_type. */ > + bool has_value () const noexcept > + { > + return m_uiout !=3D nullptr; > + } > + > private: > + struct ui_out *m_uiout =3D nullptr; > +}; > =20 > - struct ui_out *m_uiout; > +/* Stand-in for std::optional>. > + Support (as needed) some of the std::optional interface, allowing it = to be > + used as if it were std::optional>. There are = 2 > + reasons why we don't want to use the std::optional form: > + - Wmaybe-uninitialized false positives, and > + - it's overkill. With std::optional, we can have three states: > + - !has_value () > + - has_value () && m_uiout =3D=3D nullptr > + - has_value () && m_uiout !=3D nullptr > + and we don't use the middle one. */ > +template > +class opt_ui_out_emit_type : ui_out_emit_type > +{ > + using base =3D ui_out_emit_type; > + > +public: > + opt_ui_out_emit_type () =3D default; > + > + using base::base; > + using base::emplace; > + using base::reset; > + using base::has_value; > + > + DISABLE_COPY_AND_ASSIGN (opt_ui_out_emit_type); > }; > =20 > using ui_out_emit_tuple =3D ui_out_emit_type; > +using opt_ui_out_emit_tuple =3D opt_ui_out_emit_type; > using ui_out_emit_list =3D ui_out_emit_type; > +using opt_ui_out_emit_list =3D opt_ui_out_emit_type; > =20 Did you consider adding something like this: namespace std { template<> class [[deprecated ("std::optional is disabled; opt_ui_out_e= mit_tuple instead")]] optional { public: /* Delete all constructors to prevent object creation. */ optional() =3D delete; optional(const optional&) =3D delete; optional(optional&&) =3D delete; template optional(Args&&...) =3D delete; }; } This should be valid(ish) since C++14. I say "ish" because I think overriding things in std:: without providing an API compatible replacement is I think itself bad. But given we want this to not compile I suspect this would be good enough. You'd want to add something similar for ui_out_emit_list too. The goal here is to enforce the use of your new std::optional replacements. thoughts? Thanks, Andrew