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.
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 " + "other than null or complete class type " + "reflection and exceptions disabled"); +#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
