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;
}