https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126088
--- Comment #3 from Max Orth <max.orth96 at gmail dot com> ---
(In reply to Jakub Jelinek from comment #2)
> #include <meta>
>
> constexpr char a[] = "str1";
> constexpr char const *b = "str2";
> struct A { char const *c = "str3"; };
> [[=A { "str4" }]] int d = 1;
> [[=A { a }]] int e = 2;
> [[=A { }]] int f = 3;
> [[=A { b }]] int g = 4;
>
> consteval std::meta::info
> foo (std::meta::info x)
> {
> std::vector<std::meta::info> h = std::meta::annotations_of (x);
> A i = std::meta::extract<A> (h[0]);
> std::string_view j (i.c, __builtin_strlen (i.c));
> return std::meta::reflect_constant_string (j);
> }
>
> int
> main ()
> {
> char const *k = [: foo (^^d) :];
> char const *l = [: foo (^^e) :];
> char const *m = [: foo (^^f) :];
> char const *n = [: foo (^^g) :];
> }
>
> Isn't this correct?
> This is
> #0 convert_reflect_constant_arg (type=<record_type 0x7fffe616bdc8 A>,
> expr=<constructor 0x7fffe61c67c8>) at ../../gcc/cp/pt.cc:34029
> #1 0x0000000000880983 in eval_reflect_constant (loc=4611686018427411086,
> ctx=0x7fffffff85c0, type=<record_type 0x7fffe616bdc8 A>, expr=<constructor
> 0x7fffe61c67c8>,
> non_constant_p=0x7fffffffaf5f, jump_target=0x7fffffffa6f0,
> fun=<function_decl 0x7fffe6172c00 extract>) at ../../gcc/cp/reflect.cc:4081
> #2 0x000000000087a4ce in eval_constant_of (loc=4611686018427411086,
> ctx=0x7fffffff85c0, r=<constructor 0x7fffe61c67c8>, kind=REFLECT_ANNOTATION,
> non_constant_p=0x7fffffffaf5f,
> overflow_p=0x7fffffffaf5e, jump_target=0x7fffffffa6f0,
> fun=<function_decl 0x7fffe6172c00 extract>) at ../../gcc/cp/reflect.cc:2874
>
> Now, if I call
> expr = convert_nontype_argument (type, expr, tf_warning_or_error);
> instead of
> expr = convert_nontype_argument (type, expr, tf_none);
> then it explains the reason:
> pr126088.C: In function ‘consteval std::meta::info foo(std::meta::info)’:
> pr126088.C:23:26: in ‘constexpr’ expansion of ‘foo(^^d)’
> 23 | char const *k = [: foo (^^d) :];
> | ~~~~^~~~~
> pr126088.C:6:8: error: ‘"str4"’ is not a valid template argument of type
> ‘const char*’ because ‘"str4"’ is not a variable or function
> 6 | [[=A { "str4" }]] int d = 1;
> | ^~~~~~
> This is similar to why
> template <const char *P>
> void foo () {}
> const char a[] = "str";
> void bar () { foo <a> (); foo <"str"> (); }
> rejects foo <"str"> but not foo <a>.
I'm satisfied, can close as not a bug. It would be nice if the reflection
error had more detail about why it failed. Indicating the end of the splice
operator, along with "reflect_constant failed" is not very helpful.