https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124149

            Bug ID: 124149
           Summary: [reflection] std::meta::extract for a char const*
                    annotation -> exception:reflect_constant_array
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: BruceIde at protonmail dot com
  Target Milestone: ---

Created attachment 63709
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63709&action=edit
g++ verbose version info

I'm experimenting with annotations
(https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r2.html) with a
freshly-built g++16 (See attachment for verbose version.) I have two very
simple test cases; A struct with an int member, which I am able to reflect with
the current annotation support, and a struct with a char const* member, which
yields a uncaught exception of type ‘std::meta::exception’; ‘what()’:
‘reflect_constant failed’
.


Test case is:

#include <meta>
#include <iostream>

struct NumAnnotation {
  int number;
};

// Due to compile time requirements, I need to pass the info as a
// template object, and this function needs to be constexpr
template <std::meta::info Info>
consteval int num_annotation_value() {
  constexpr auto annotations =
std::define_static_array(std::meta::annotations_of_with_type(Info,
^^NumAnnotation));
  constexpr NumAnnotation extracted =
std::meta::extract<NumAnnotation>(annotations[0]);
  return extracted.number;
}

void IntTest1() {
  [[=NumAnnotation{42}]] int i{0};
  i = num_annotation_value<^^i>();
  // prints i == 42
  std::cout << "IntTest1: i == " << i << std::endl;
}

/* */
// Same setup as the int one. String and string view do not work well with
// extract,
[P3394](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r2.html)
// uses char const* data in its section 3.3 serialization example
struct StringAnnotation {
  char const* data;
};

// Exactly copying the consteval function above and changing the type
template <std::meta::info Info>
consteval char const* string_annotation_value() {
  constexpr auto annotations =
std::define_static_array(std::meta::annotations_of_with_type(Info,
^^StringAnnotation));
  constexpr StringAnnotation extracted =
std::meta::extract<StringAnnotation>(annotations[0]);
  return extracted.data;
}

void StringTest2() {
  [[=StringAnnotation("Hello, world!")]] int i{0};
  char const* data = string_annotation_value<^^i>();
  std::cout << "String annotation: \"" << data << "\"" << "i == " << i <<
std::endl;
}

/* */

int main(int argc, char *argv[]) {
  IntTest1();
  /* */
  StringTest2();
  /* */
}


Here is my command line and attempt to build:

cd /tmp/build/test && /usr/local/gcc-16/bin/g++-16   -freflection -std=c++26
-Wall -Wextra -save-temps -fno-strict-aliasing -fwrapv
-fno-aggressive-loop-optimizations -MD -MT
test/CMakeFiles/standalone.dir/SimpleStringAnnotation.cpp.o -MF
CMakeFiles/standalone.dir/SimpleStringAnnotation.cpp.o.d -o
CMakeFiles/standalone.dir/SimpleStringAnnotation.cpp.o -c
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp: In
instantiation of ‘consteval const char* string_annotation_value() [with
std::meta::info Info = ^^i]’:
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp:57:50:  
required from here
   57 |   char const* data = string_annotation_value<^^i>();
      |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp:51:30: error:
uncaught exception of type ‘std::meta::exception’; ‘what()’: ‘reflect_constant
failed’
   51 |   constexpr StringAnnotation extracted =
std::meta::extract<StringAnnotation>(annotations[0]);
      |                              ^~~~~~~~~
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp: In function
‘void StringTest2()’:
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp:57:50: error:
call to consteval function ‘string_annotation_value<^^i>()’ is not a constant
expression
   57 |   char const* data = string_annotation_value<^^i>();
      |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp:57:50: error:
‘consteval const char* string_annotation_value() [with std::meta::info Info =
^^i]’ called in a constant expression
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp: In function
‘int main(int, char**)’:
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp:63:14:
warning: unused parameter ‘argc’ [-Wunused-parameter]
   63 | int main(int argc, char *argv[]) {
      |          ~~~~^~~~
/home/greyfox/sandbox/p2996_tests/test/SimpleStringAnnotation.cpp:63:26:
warning: unused parameter ‘argv’ [-Wunused-parameter]
   63 | int main(int argc, char *argv[]) {
      |                    ~~~~~~^~~~~~
gmake[2]: *** [test/CMakeFiles/standalone.dir/build.make:79:
test/CMakeFiles/standalone.dir/SimpleStringAnnotation.cpp.o] Error 1
gmake[2]: Leaving directory '/tmp/build'
gmake[1]: *** [CMakeFiles/Makefile2:141: test/CMakeFiles/standalone.dir/all]
Error 2
gmake[1]: Leaving directory '/tmp/build'
gmake: *** [Makefile:91: all] Error 2


This may be related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123819, as
it looks like there are only a couple of places in the gcc code where that
exception can originate and what we're trying to do seems to be similar.

I can include the temps if you need them but it works out to 2.1MB of stuff
that comes with the compiler and the test cases here are as boiled down as I
can make them.

Reply via email to