From: Jonathan Wakely <jwakely@redhat.com>
To: Marc Glisse <marc.glisse@inria.fr>
Cc: "libstdc++" <libstdc++@gcc.gnu.org>,
Matthias Kretz <m.kretz@gsi.de>,
gcc Patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] libstdc++: Implement std::unreachable() for C++23 (P0627R6)
Date: Fri, 1 Apr 2022 12:33:42 +0100 [thread overview]
Message-ID: <CACb0b4np4VYaSRf3A=VGZ8x7gLSGdf3MSdXRbwu6tc0TRTs30Q@mail.gmail.com> (raw)
In-Reply-To: <147e97d-41ab-98d-7721-a6cf2e0ddeb@hippo.saclay.inria.fr>
[-- Attachment #1: Type: text/plain, Size: 1645 bytes --]
On Thu, 31 Mar 2022 at 19:21, Marc Glisse wrote:
>
> On Thu, 31 Mar 2022, Jonathan Wakely wrote:
>
> > On Thu, 31 Mar 2022 at 17:03, Marc Glisse via Libstdc++
> > <libstdc++@gcc.gnu.org> wrote:
> >>
> >> On Thu, 31 Mar 2022, Matthias Kretz via Gcc-patches wrote:
> >>
> >>> I like it. But I'd like it even more if we could have
> >>>
> >>> #elif defined _UBSAN
> >>> __ubsan_invoke_ub("reached std::unreachable()");
> >>>
> >>> But to my knowledge UBSAN has no hooks for the library like this (yet).
> >>
> >> -fsanitize=undefined already replaces __builtin_unreachable with its own
> >> thing, so I was indeed going to ask if the assertion / trap provide a
> >> better debugging experience compared to plain __builtin_unreachable, with
> >> the possibility to get a stack trace (UBSAN_OPTIONS=print_stacktrace=1),
> >> etc? Detecting if (the right subset of) ubsan is enabled sounds like a
> >> good idea.
> >
> > Does UBsan define a macro that we can use to detect it?
>
> https://github.com/google/sanitizers/issues/765 seems to say no (it could
> be outdated though), but they were asking for use cases to motivate adding
> one. Apparently there is a macro for clang, although I don't think it is
> fine-grained.
>
> Adding one to cppbuiltin.cc testing SANITIZE_UNREACHABLE looks easy, maybe
> we can do just this one, we don't need to go overboard and define macros
> for all possible suboptions of ubsan right now.
Yes, we should only add what there's a use case for.
> I don't think any of that prevents from pushing your patch as is for
> gcc-12.
Matthias didn't like my Princess Bride easter egg :-)
Would the attached be better?
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 5072 bytes --]
commit e2b2cf6319406bc9cb9361962cf7c31b1848ebe8
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Apr 1 12:25:02 2022
libstdc++: Implement std::unreachable() for C++23 (P0627R6)
This defines std::unreachable as an assertion for debug mode, a trap
when _GLIBCXX_ASSERTIONS is defined, and __builtin_unreachable()
otherwise.
The reason for only using __builtin_trap() in the second case is to
avoid the overhead of setting up a call to __glibcxx_assert_fail that
should never happen.
UBsan can detect if __builtin_unreachable() is executed, so if a feature
test macro for that sanitizer is added, we could change just use
__builtin_unreachable() when the sanitizer is enabled.
While thinking about what the debug assertion failure should print, I
noticed that the __glibcxx_assert_fail function doesn't check for null
pointers. This adds a check so we don't try to print them if null.
libstdc++-v3/ChangeLog:
* include/std/utility (unreachable): Define for C++23.
* include/std/version (__cpp_lib_unreachable): Define.
* src/c++11/debug.cc (__glibcxx_assert_fail): Check for valid
arguments. Handle only the function being given.
* testsuite/20_util/unreachable/1.cc: New test.
* testsuite/20_util/unreachable/version.cc: New test.
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 0d7f8954c5a..ad5faa50f57 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -186,6 +186,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr underlying_type_t<_Tp>
to_underlying(_Tp __value) noexcept
{ return static_cast<underlying_type_t<_Tp>>(__value); }
+
+#define __cpp_lib_unreachable 202202L
+ /// Informs the compiler that program control flow never reaches this point.
+ /**
+ * Evaluating a call to this function results in undefined behaviour.
+ * This can be used as an assertion informing the compiler that certain
+ * conditions are impossible, for when the compiler is unable to determine
+ * that by itself.
+ *
+ * For example, it can be used to prevent warnings about reaching the
+ * end of a non-void function without returning.
+ *
+ * @since C++23
+ */
+ [[noreturn,__gnu__::__always_inline__]]
+ inline void
+ unreachable()
+ {
+#ifdef _GLIBCXX_DEBUG
+ std::__glibcxx_assert_fail(nullptr, 0, "std::unreachable()", nullptr);
+#elif defined _GLIBCXX_ASSERTIONS
+ __builtin_trap();
+#else
+ __builtin_unreachable();
+#endif
+ }
#endif // C++23
#endif // C++20
#endif // C++17
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index 44b8a9f88b5..51f2110b68e 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -326,6 +326,7 @@
# define __cpp_lib_string_resize_and_overwrite 202110L
#endif
#define __cpp_lib_to_underlying 202102L
+#define __cpp_lib_unreachable 202202L
#endif
#endif // C++2b
#endif // C++20
diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
index 98fe2dcc153..4706defedf1 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -52,8 +52,11 @@ namespace std
__glibcxx_assert_fail(const char* file, int line,
const char* function, const char* condition) noexcept
{
- fprintf(stderr, "%s:%d: %s: Assertion '%s' failed.\n",
- file, line, function, condition);
+ if (file && function && condition)
+ fprintf(stderr, "%s:%d: %s: Assertion '%s' failed.\n",
+ file, line, function, condition);
+ else if (function)
+ fprintf(stderr, "%s: Undefined behavior detected.\n", function);
abort();
}
}
diff --git a/libstdc++-v3/testsuite/20_util/unreachable/1.cc b/libstdc++-v3/testsuite/20_util/unreachable/1.cc
new file mode 100644
index 00000000000..0c463d52a48
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/unreachable/1.cc
@@ -0,0 +1,17 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <utility>
+
+#ifndef __cpp_lib_unreachable
+# error "Feature-test macro for unreachable missing in <utility>"
+#elif __cpp_lib_unreachable != 202202L
+# error "Feature-test macro for unreachable has wrong value in <utility>"
+#endif
+
+bool test01(int i)
+{
+ if (i == 4)
+ return true;
+ std::unreachable();
+} // { dg-bogus "control reaches end of non-void function" }
diff --git a/libstdc++-v3/testsuite/20_util/unreachable/version.cc b/libstdc++-v3/testsuite/20_util/unreachable/version.cc
new file mode 100644
index 00000000000..c7795900c30
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/unreachable/version.cc
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do preprocess { target c++23 } }
+
+#include <version>
+
+#ifndef __cpp_lib_unreachable
+# error "Feature-test macro for unreachable missing in <version>"
+#elif __cpp_lib_unreachable != 202202L
+# error "Feature-test macro for unreachable has wrong value in <version>"
+#endif
next prev parent reply other threads:[~2022-04-01 11:33 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-31 15:30 Jonathan Wakely
2022-03-31 15:50 ` Matthias Kretz
2022-03-31 15:59 ` Xi Ruoyao
2022-03-31 16:01 ` Marc Glisse
2022-03-31 16:05 ` Jonathan Wakely
2022-03-31 18:21 ` Marc Glisse
2022-04-01 11:33 ` Jonathan Wakely [this message]
2022-04-01 11:56 ` Matthias Kretz
2022-04-01 13:01 ` Jonathan Wakely
2022-03-31 16:02 ` 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='CACb0b4np4VYaSRf3A=VGZ8x7gLSGdf3MSdXRbwu6tc0TRTs30Q@mail.gmail.com' \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
--cc=m.kretz@gsi.de \
--cc=marc.glisse@inria.fr \
/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).