https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126112
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jakub at gcc dot gnu.org
--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
#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>.