On Tue, 10 Mar 2026 at 09:18, Jakub Jelinek <[email protected]> wrote:
>
> Hi!
>
> 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.

Oh of course! Very nice.

>
> 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 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.
>
> Tested on x86_64-linux, ok for trunk?
>
> 2026-03-10  Jakub Jelinek  <[email protected]>
>
>         * 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.
>
> --- libstdc++-v3/include/std/meta.jj    2026-03-10 08:14:28.100322627 +0100
> +++ libstdc++-v3/include/std/meta       2026-03-10 10:03:33.295442677 +0100
> @@ -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,7 +598,8 @@ _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
> @@ -599,7 +607,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>                                        "or complete class type reflection",
>                                      ^^access_context::via);
>  #else
> +#if __has_builtin(__builtin_constexpr_diag)
> +         __builtin_constexpr_diag (2, "",
> +                                   "std::meta::exception::via argument "

s/exception/access_context/

> +                                   "other than null or complete class type "
> +                                   "reflection and exceptions disabled");

I think the "and exceptions disabled" part is a bit confusing, it
reads like it's part of the "argument other than ..." clause.

You could put it in parens "... (and exceptions disabled)" or maybe
just leave that part off completely? Users probably know when they're
compiling with -fno-exceptions and so shouldn't be surprised they
don't get an exception here.


> +#else
>           __asm__("");
> +#endif
>           return *this;
>  #endif
>         }
> --- gcc/testsuite/g++.dg/reflect/eh8.C.jj       2026-01-15 16:33:47.007097959 
> +0100
> +++ gcc/testsuite/g++.dg/reflect/eh8.C  2026-03-10 09:57:15.887817046 +0100
> @@ -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 ());
> --- gcc/testsuite/g++.dg/reflect/no-exceptions2.C.jj    2026-03-10 
> 09:49:10.810013159 +0100
> +++ gcc/testsuite/g++.dg/reflect/no-exceptions2.C       2026-03-10 
> 10:07:44.471200349 +0100
> @@ -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::exception::via argument other 
> than null or complete class type reflection and exceptions disabled" "" { 
> target *-*-* } 0 }
>
>         Jakub
>

Reply via email to