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

            Bug ID: 123440
           Summary: [reflection] internal compiler error: canonical types
                    differ for identical types
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mpolacek at gcc dot gnu.org
  Target Milestone: ---

```
#include <meta>
#include <ranges>
using namespace std::meta;
struct test_struct
{
    int data_member;
    void fn1() {}
    void fn2() {}
    int getter() { return data_member; }
    void setter(int i) { data_member = i; }
    virtual int virtual_fn(char*, bool) { return 0; }
    virtual int pure_virtual_fn(char*, int) = 0;
    static int static_member_fn(bool b) { return b ? 42 : 0; }
};
template<typename T, size_t I>
consteval info get_member_at()
{
    constexpr auto ctx          = access_context::current();
    constexpr auto pointable    = [](info i) consteval -> bool {
        return !is_destructor(i) && !is_constructor(i) &&
!is_special_member_function(i);
    };
    return (members_of(^^T, ctx) | std::views::filter(pointable) |
std::ranges::to<std::vector>())[I];
}
template<typename T, size_t I>
consteval info get_member_type() {
    return type_of(get_member_at<T, I>());
}
template<typename T, size_t I>
consteval auto get_member_ptr() {
    constexpr info member   = get_member_at<T, I>();
    constexpr info mem_type = add_pointer(get_member_type<T, I>());
    using type              = typename[: mem_type :];
    return extract<type>(member);
}
constinit auto ex_0 = extract<int test_struct::*>(get_member_at<test_struct,
0>());
constinit auto ex_1 = extract<void
(test_struct::*)()>(get_member_at<test_struct, 1>());
constinit auto ex_2 = extract<void
(test_struct::*)()>(get_member_at<test_struct, 2>());
constinit auto ex_3 = extract<int
(test_struct::*)()>(get_member_at<test_struct, 3>());
constinit auto ex_4 = extract<void
(test_struct::*)(int)>(get_member_at<test_struct, 4>());
constinit auto ex_5 = extract<int (test_struct::*)(char*,
bool)>(get_member_at<test_struct, 5>());
constinit auto ex_6 = extract<int (test_struct::*)(char*,
int)>(get_member_at<test_struct, 6>());
constinit auto ex_7 = extract<int(*)(bool)>(get_member_at<test_struct, 7>());
constinit auto ex_8 = get_member_ptr<test_struct, 7>();
constinit auto test_1 = get_member_ptr<test_struct, 1>();
constinit auto test_2 = get_member_ptr<test_struct, 2>();
constinit auto test_3 = get_member_ptr<test_struct, 3>();
constinit auto test_4 = get_member_ptr<test_struct, 4>();
constinit auto test_5 = get_member_ptr<test_struct, 5>();
constinit auto test_5 = get_member_ptr<test_struct, 6>();
```

results in:

in ‘constexpr’ expansion of ‘get_member_ptr<test_struct, 1>()’
report1.C:36:55:   
   36 | constinit auto test_1 = get_member_ptr<test_struct, 1>();
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
report1.C:33:25: internal compiler error: canonical types differ for identical
types ‘void (test_struct::*)()’ and ‘void (test_struct::*)()’
   33 |     return extract<type>(member);
      |            ~~~~~~~~~~~~~^~~~~~~~
0x3018568 internal_error(char const*, ...)
        /home/mpolacek/src/forge/gcc/gcc/diagnostic-global-context.cc:787
0x90d472 comptypes(tree_node*, tree_node*, int)
        /home/mpolacek/src/forge/gcc/gcc/cp/typeck.cc:1737
0x86c7a4 can_extract_member_or_function_p
        /home/mpolacek/src/forge/gcc/gcc/cp/reflect.cc:7303
0x86c8a0 extract_member_or_function
        /home/mpolacek/src/forge/gcc/gcc/cp/reflect.cc:7341
0x86cabb eval_extract
        /home/mpolacek/src/forge/gcc/gcc/cp/reflect.cc:7386
0x86f3d0 process_metafunction(constexpr_ctx const*, tree_node*, tree_node*,
bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/reflect.cc:7792
0x491132 cxx_eval_call_expression
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:3867
0x4a8eaa cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:9203
0x4abafd cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:9916
0x4a22d5 cxx_eval_store_expression
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:7658
0x4a9c74 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:9375
0x4a9d65 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:9388
0x4aa413 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:9472
0x4a5bc5 cxx_eval_statement_list
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:8480
0x4ad511 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:10183
0x4ad63d cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:10192
0x493b39 cxx_eval_call_expression
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:4366
0x4a8eaa cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:9203
0x4b0c19 cxx_eval_outermost_constant_expr
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:10715
0x4b2416 maybe_constant_value(tree_node*, tree_node*, mce_value)
        /home/mpolacek/src/forge/gcc/gcc/cp/constexpr.cc:11137


Thanks to Nathan Simon for the test.

Reply via email to