[gcc r16-7997] libstdc++: Use __builtin_constexpr_diag instead of __asm__("") in <meta> if possible

Jakub Jelinek jakub@gcc.gnu.org
Wed Mar 11 06:58:24 GMT 2026


https://gcc.gnu.org/g:5b09326f7b82ca2481a4b8df1f80475d6a792a04

commit r16-7997-g5b09326f7b82ca2481a4b8df1f80475d6a792a04
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Mar 11 07:55:58 2026 +0100

    libstdc++: Use __builtin_constexpr_diag instead of __asm__("") in <meta> if possible
    
    Your asm -> __asm__ patch made me think that these are perfect
    candidates for __builtin_constexpr_diag, the asms were there just
    to make it provably non-constant expression (guess *(char*)nullptr = 0;
    would do as well).  But with __builtin_constexpr_diag we can tell
    the user the details.
    
    Additionally, when testing it I've found that the
    https://eel.is/c++draft/meta.reflection#access.context-13
    Throws: meta::exception unless cls is either the null reflection
    or a reflection of a complete class type.
    part of via's description was implemented wierdly, it did throw
    an exception, but not by telling user that via has been called with
    something that is not a null reflection nor reflection of a complete
    class type, but that is_class_type has been called on a reflection
    of something other than a type.
    
    2026-03-11  Jakub Jelinek  <jakub@redhat.com>
    
            * include/std/meta (std::meta::exception::what()): Use
            __builtin_constexpr_diag instead of __asm__("") if supported.
            (std::meta::access_context::via(info)): Don't call is_class_type
            if __cls is not a type.  Use __builtin_constexpr_diag instead of
            __asm__("") if supported for -fno-exceptions.
    
            * g++.dg/reflect/eh8.C: Expect different diagnostics.
            * g++.dg/reflect/no-exceptions2.C: New test.
    
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>

Diff:
---
 gcc/testsuite/g++.dg/reflect/eh8.C            |  2 +-
 gcc/testsuite/g++.dg/reflect/no-exceptions2.C | 15 +++++++++++++++
 libstdc++-v3/include/std/meta                 | 17 ++++++++++++++++-
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/g++.dg/reflect/eh8.C b/gcc/testsuite/g++.dg/reflect/eh8.C
index ac4afa4b053e..183715f33f04 100644
--- a/gcc/testsuite/g++.dg/reflect/eh8.C
+++ b/gcc/testsuite/g++.dg/reflect/eh8.C
@@ -24,7 +24,7 @@ bar ()
 {
   exception a (u8"\N{GRINNING FACE}\N{GRINNING FACE WITH SMILING EYES}\N{LEFT SPEECH BUBBLE}", ^^foo);
   const char *b = a.what ();	// { dg-message "in 'constexpr' expansion of 'a.std::meta::exception::what\\\(\\\)" }
-  return true;			// { dg-error "inline assembly is not a constant expression" "" { target *-*-* } 0 }
+  return true;			// { dg-error "constexpr message: std::meta::exception message could not be successfully transcoded from UTF-8 to ordinary literal encoding" "" { target *-*-* } 0 }
 }
 
 static_assert (foo ());
diff --git a/gcc/testsuite/g++.dg/reflect/no-exceptions2.C b/gcc/testsuite/g++.dg/reflect/no-exceptions2.C
new file mode 100644
index 000000000000..b9431e316144
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/no-exceptions2.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection -fno-exceptions" }
+
+#include <meta>
+
+consteval bool
+foo ()
+{
+  auto ctx = std::meta::access_context::unchecked ();
+  auto ctx2 = ctx.via (^^::);	// { dg-message "in 'constexpr' expansion of 'ctx.std::meta::access_context::via\\\(\\\^\\\^::\\\)'" }
+  return true;
+}
+
+auto b = foo ();		// { dg-message "in 'constexpr' expansion of 'foo\\\(\\\)'" }
+// { dg-error "constexpr message: std::meta::access_context::via argument other than null or complete class type reflection" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/include/std/meta b/libstdc++-v3/include/std/meta
index 2ed7708dcbf6..d72c73894f2b 100644
--- a/libstdc++-v3/include/std/meta
+++ b/libstdc++-v3/include/std/meta
@@ -120,7 +120,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	// from UTF-8 to ordinary literal encoding failed.
 	// In that case what() should be non-constant.
 	if (_M_what.size() == 0 && _M_u8what.size() != 0)
+#if __has_builtin(__builtin_constexpr_diag)
+	  __builtin_constexpr_diag (2, "",
+				    "std::meta::exception message could not "
+				    "be successfully transcoded from UTF-8 to "
+				    "ordinary literal encoding");
+#else
 	  __asm__("");
+#endif
 	return _M_what.c_str();
       }
       consteval u8string_view u8what() const noexcept { return _M_u8what; }
@@ -591,15 +598,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     access_context::via(info __cls) const
     {
       if (__cls != info {}
-	  && (!std::meta::is_class_type(__cls)
+	  && (!std::meta::is_type(__cls)
+	      || !std::meta::is_class_type(__cls)
 	      || !std::meta::is_complete_type(__cls)))
 	{
 #if __cpp_exceptions
 	  throw std::meta::exception(u8"via argument other than null "
 				       "or complete class type reflection",
 				     ^^access_context::via);
+#else
+#if __has_builtin(__builtin_constexpr_diag)
+	  __builtin_constexpr_diag (2, "",
+				    "std::meta::access_context::via argument "
+				    "other than null or complete class type "
+				    "reflection");
 #else
 	  __asm__("");
+#endif
 	  return *this;
 #endif
 	}


More information about the Libstdc++-cvs mailing list