public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Patrick Palka <ppalka@redhat.com>
To: Jonathan Wakely <jwakely.gcc@gmail.com>
Cc: Patrick Palka <ppalka@redhat.com>,
	Jonathan Wakely <jwakely@redhat.com>,
	 libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]
Date: Sat, 16 Dec 2023 11:26:43 -0500 (EST)	[thread overview]
Message-ID: <a0920a62-93b4-b2f6-63ac-001e76011fa4@idea> (raw)
In-Reply-To: <CAH6eHdTKVtTYYPZiY2=LOaP_Pc3gwC_UThb6n00ryKbiEcPPwQ@mail.gmail.com>

On Sat, 16 Dec 2023, Jonathan Wakely wrote:

> On Sat, 16 Dec 2023 at 09:14, Jonathan Wakely wrote:
> >
> > On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote:
> > >
> > > On Wed, 6 Dec 2023, Jonathan Wakely wrote:
> > >
> > > > Any comments on this approach?
> > > >
> > > > -- >8 --
> > > >
> > > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe
> > > > iterator instrumentation and checking is disabled during constant
> > > > evaluation, because it requires mutex locks and calls to non-inline
> > > > functions defined in libstdc++.so. It should be OK to disable the safety
> > > > checks, because most UB should be detected during constant evaluation
> > > > anyway.
> > > >
> > > > We could try to enable the full checking in constexpr, but it would mean
> > > > wrapping all the non-inline functions like _M_attach with an inline
> > > > _M_constexpr_attach that does the iterator housekeeping inline without
> > > > mutex locks when calling for constant evaluation, and calls the
> > > > non-inline function at runtime. That could be done in future if we find
> > > > that we've lost safety or useful checking by disabling the safe
> > > > iterators.
> > > >
> > > > There are a few test failures in C++20 mode, which I'm unable to
> > > > explain. The _Safe_iterator::operator++() member gives errors for using
> > > > non-constexpr functions during constant evaluation, even though those
> > > > functions are guarded by std::is_constant_evaluated() checks. The same
> > > > code works fine for C++23 and up.
> > >
> > > AFAICT these C++20 test failures are really due to the variable
> > > definition of non-literal type
> > >
> > > 381    __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> > >
> > > which were prohibited in a constexpr function (even if that code was
> > > never executed) until C++23's P2242R3.
> >
> > Ah, I figured it was a core change but I couldn't recall which one. Thanks.

Yeah the diagnostic blaming the non-constexpr call to _M_incrementable
was outright wrong and misleading, I filed PR113041 about that.

> >
> > > We can use an immediately invoked lambda to work around this:
> > >
> > > 381    [this] {
> > > 382      __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> > > 383      ++base();
> > > 384    }();
> > > 385    return *this;
> >
> > We'd need some #if as this code has to work for C++98. But that's doable.
> 
> The attached patch seems simpler, I'm testing it now.

Would the operator+=, operator-= and the copy assign operator= also need
adjustment?

We could somewhat cleanly encapsulate the lambda workaround with a pair
of macros surrounding the problematic variable, something like:

diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index 26f008982f8..df3b4d33f04 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -360,6 +360,14 @@ namespace __gnu_debug
 	return base().operator->();
       }
 
+#if __cplusplus >= 202002L && __cpp_constexpr < 202110L
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN [&] { do
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false); }()
+#else
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN do
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false)
+#endif
+
       // ------ Input iterator requirements ------
       /**
        *  @brief Iterator preincrement
@@ -378,8 +386,10 @@ namespace __gnu_debug
 	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
 			      _M_message(__msg_bad_inc)
 			      ._M_iterator(*this, "this"));
-	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-	++base();
+	_GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
+	  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+	  ++base();
+	} _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END;
 	return *this;
       }
 


  reply	other threads:[~2023-12-16 16:27 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-06 14:18 Jonathan Wakely
2023-12-14 16:34 ` Jonathan Wakely
2023-12-16  0:26 ` Patrick Palka
2023-12-16  9:14   ` Jonathan Wakely
2023-12-16  9:37     ` Jonathan Wakely
2023-12-16 16:26       ` Patrick Palka [this message]
2023-12-16 16:30         ` Jonathan Wakely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a0920a62-93b4-b2f6-63ac-001e76011fa4@idea \
    --to=ppalka@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jwakely.gcc@gmail.com \
    --cc=jwakely@redhat.com \
    --cc=libstdc++@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).