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

            Bug ID: 123783
           Summary: [reflection] Internal Compiler Error when reflecting
                    on function parameters in lambda capture
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: volker.hilsheimer at qt dot io
  Target Milestone: ---

Created attachment 63467
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63467&action=edit
Preprocessed sources as generated by -freport-bug

Using gcc from trunk (as of now, 09358c6693ec8e3f924be7c5a6d227edac47b843) on
WSL to build the code below (preprocessed source attached) with

/opt/gcc-trunk/bin/g++ main.cpp -freflection -std=c++26

results in the following error:

main.cpp: In instantiation of ‘func(int, float)::<lambda()> [with auto e =
^^counter]’:
required from ‘constexpr void __impl::replicator_type<vals>::operator>>(F)
const [with F = func(int, float)::<lambda()>; auto ...vals = {^^counter,
^^factor}]’
main.cpp:8:40:   
    8 |         (body.template operator()<vals>(), ...);
      |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
required from here
main.cpp:37:5:   
   37 |     };
      |     ^
main.cpp:36:24: internal compiler error: trying to capture ‘counter’ in
instantiation of generic lambda
   36 |         args[i++] = &[:e:];
      |                      ~~^~~
0x2ad176f internal_error(char const*, ...)
        ../../gcc-trunk/gcc/diagnostic-global-context.cc:787
0xc94fbf add_capture(tree_node*, tree_node*, tree_node*, bool, bool, unsigned
int*)
        ../../gcc-trunk/gcc/cp/lambda.cc:729
0xc9503e add_default_capture(tree_node*, tree_node*, tree_node*)
        ../../gcc-trunk/gcc/cp/lambda.cc:789
0xe173f0 check_splice_expr(unsigned long, unsigned long, tree_node*, bool,
bool, bool)
        ../../gcc-trunk/gcc/cp/reflect.cc:8403
0xdd18fa tsubst_splice_expr
        ../../gcc-trunk/gcc/cp/pt.cc:16727
0xdcaca7 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
        ../../gcc-trunk/gcc/cp/pt.cc:23055
0xdcbb31 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
        ../../gcc-trunk/gcc/cp/pt.cc:21415
0xdcbcdb tsubst_expr(tree_node*, tree_node*, int, tree_node*)
        ../../gcc-trunk/gcc/cp/pt.cc:21740
0xdf926f tsubst_stmt
        ../../gcc-trunk/gcc/cp/pt.cc:20561
0xdfa208 tsubst_stmt
        ../../gcc-trunk/gcc/cp/pt.cc:19352
0xdfac9d tsubst_stmt
        ../../gcc-trunk/gcc/cp/pt.cc:19755
0xdfa550 tsubst_stmt
        ../../gcc-trunk/gcc/cp/pt.cc:19334
0xdfac9d tsubst_stmt
        ../../gcc-trunk/gcc/cp/pt.cc:19755
0xe01fc6 tsubst_stmt
        ../../gcc-trunk/gcc/cp/pt.cc:19320
0xe01fc6 instantiate_body
        ../../gcc-trunk/gcc/cp/pt.cc:28363
0xe02dac instantiate_decl(tree_node*, bool, bool)
        ../../gcc-trunk/gcc/cp/pt.cc:28656
0xc5c6b0 maybe_instantiate_decl(tree_node*)
        ../../gcc-trunk/gcc/cp/decl2.cc:6433
0xc5c6b0 maybe_instantiate_decl(tree_node*)
        ../../gcc-trunk/gcc/cp/decl2.cc:6421
0xc5e557 mark_used(tree_node*, int)
        ../../gcc-trunk/gcc/cp/decl2.cc:6789
0xb6155b build_over_call
        ../../gcc-trunk/gcc/cp/call.cc:11023


Reproducible on Compiler Explorer at: https://godbolt.org/z/b9Kf331dE

I believe this should work, esp given that explicitly capturing the parameters
does.


#include <meta>

namespace __impl {
  template<auto... vals>
  struct replicator_type {
    template<typename F>
      constexpr void operator>>(F body) const {
        (body.template operator()<vals>(), ...);
      }
  };

  template<auto... vals>
  replicator_type<vals...> replicator = {};
}

template<typename R>
consteval auto expand(R range) {
  std::vector<std::meta::info> args;
  for (auto r : range) {
    args.push_back(reflect_constant(r));
  }
  return substitute(^^__impl::replicator, args);
}

int func(int counter, float factor) {
    std::array<void *, parameters_of(^^func).size()> args;

    std::size_t i = 0;
    [:expand(parameters_of(^^func)):] >>
#if 0 // set to true as a "workaround"
        [&i, &counter, &factor, &args]<auto e>
#else
        [&]<auto e>
#endif
    {
        args[i++] = &[:e:];
    };
    return 0;
}

int main()
{
    func(11, 22);
    func(33, 44);

    return 0;
}
  • [Bug c++/123783] New: [reflect... volker.hilsheimer at qt dot io via Gcc-bugs

Reply via email to