gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2) Command: g++ -c -std=c++14 ice.cpp Output: ice.cpp: In member function ‘auto B::g(Args&& ...) [with Args = {A<char>, const char (&)[1]}]’: ice.cpp:15:41: internal compiler error: in create_tmp_var, at gimple-expr.c:524 return [=](){ return f(args...); }; ice.cpp: template <typename T> struct A { A() { } A(const A &) { } }; struct B { B(); template <typename... Args> auto g(Args&&... args) { return [=](){ return f(args...); }; } void f(A<char>,const char*) { } }; B::B() { g(A<char>(),""); }
Confirmed. All supported gcc versions are affected. markus@x4 /tmp % cat ice.ii struct A { A(); A(const A &); }; struct B { B(); template <typename... Args> auto g(Args &&... p1) { return [=] { f(p1...); }; } void f(A, const char *); }; B::B() { g(A(), ""); } markus@x4 /tmp % g++ -c ice.ii ice.ii: In member function ‘auto B::g(Args&& ...) [with Args = {A, const char (&)[1]}]’: ice.ii:8:28: internal compiler error: in create_tmp_var, at gimple-expr.c:473 return [=] { f(p1...); }; ^ 0xafcb20 create_tmp_var(tree_node*, char const*) ../../gcc/gcc/gimple-expr.c:473 0xb2f384 create_tmp_from_val ../../gcc/gcc/gimplify.c:500 0xb2f384 lookup_tmp_var ../../gcc/gcc/gimplify.c:521 0xb2f384 internal_get_tmp_var ../../gcc/gcc/gimplify.c:574 0xb26cc1 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gcc/gimplify.c:11483 0xb2ab27 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gcc/gimplify.c:10701 0xb301a6 gimplify_compound_lval ../../gcc/gcc/gimplify.c:2195 0xb27165 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gcc/gimplify.c:10495 0xb3a6cf gimplify_modify_expr ../../gcc/gcc/gimplify.c:4824 0xb29008 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gcc/gimplify.c:10543 0xb2c407 gimplify_stmt(tree_node**, gimple**) ../../gcc/gcc/gimplify.c:5805 0xb2c5e8 gimplify_and_add(tree_node*, gimple**) ../../gcc/gcc/gimplify.c:427 0xb2c5e8 gimplify_init_ctor_eval ../../gcc/gcc/gimplify.c:3799 0xb32e9f gimplify_init_constructor ../../gcc/gcc/gimplify.c:4171 0xb33d17 gimplify_modify_expr_rhs ../../gcc/gcc/gimplify.c:4432 0xb3a4d0 gimplify_modify_expr ../../gcc/gcc/gimplify.c:4769 0xb29008 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gcc/gimplify.c:10543 0xb2c407 gimplify_stmt(tree_node**, gimple**) ../../gcc/gcc/gimplify.c:5805 0xb28116 gimplify_and_add(tree_node*, gimple**) ../../gcc/gcc/gimplify.c:427 0xb28116 gimplify_return_expr ../../gcc/gcc/gimplify.c:1371
Started with r202605.
The problem is that some expressions are genericized twice. First when genericizing the whole function, RESULT_DECL is determined to be is_invisiref_parm and therefore references to it are turned into INDIRECT_REF around it and the RESULT_DECL becomes REFERENCE_TYPE. Later on gimplify_body calls unshare_body and unshares the INDIRECT_REF. Then the INDIRECT_REF is gimplified into a MEM_REF. And finally: (cp_gimplify_expr) <case VEC_INIT_EXPR> does: 625 cp_walk_tree (expr_p, cp_fold_r, &pset, NULL); 626 cp_genericize_tree (expr_p); and sees the is_invisiref_parm RESULT_DECL again (inside of MEM_REF) and turns it again into INDIRECT_REF and that is later gimplified again into MEM_REF. So we have 2 nested MEM_REFs, so one indirection too many. I think one possibility would be to be careful about REFERENCE_REF_Ps and corresponding MEM_REFs (I guess would need to double check that the offset is 0 and type is compatible with the type of the reference), if their argument is is_invisiref_parm, ensure it isn't convert_from_reference again. Will try to implement that now.
Or another option perhaps would be in cp_genericize_data note whether it is cp_genericize_tree called from cp_genericize or from elsewhere, and only replace invisiref parms if called from cp_genericize.
https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02275.html
Author: jakub Date: Wed Nov 23 15:54:39 2016 New Revision: 242766 URL: https://gcc.gnu.org/viewcvs?rev=242766&root=gcc&view=rev Log: PR c++/77739 * cp-gimplify.c (cp_gimplify_tree) <case VEC_INIT_EXPR>: Pass false as handle_invisiref_parm_p to cp_genericize_tree. (struct cp_genericize_data): Add handle_invisiref_parm_p field. (cp_genericize_r): Don't wrap is_invisiref_parm into references if !wtd->handle_invisiref_parm_p. (cp_genericize_tree): Add handle_invisiref_parm_p argument, set wtd.handle_invisiref_parm_p to it. (cp_genericize): Pass true as handle_invisiref_parm_p to cp_genericize_tree. Formatting fix. * g++.dg/cpp1y/pr77739.C: New test. Added: trunk/gcc/testsuite/g++.dg/cpp1y/pr77739.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-gimplify.c trunk/gcc/testsuite/ChangeLog
Fixed on the trunk so far.
Author: jakub Date: Wed Dec 7 22:55:04 2016 New Revision: 243407 URL: https://gcc.gnu.org/viewcvs?rev=243407&root=gcc&view=rev Log: Backported from mainline 2016-11-23 Jakub Jelinek <jakub@redhat.com> PR c++/77739 * cp-gimplify.c (cp_gimplify_tree) <case VEC_INIT_EXPR>: Pass false as handle_invisiref_parm_p to cp_genericize_tree. (struct cp_genericize_data): Add handle_invisiref_parm_p field. (cp_genericize_r): Don't wrap is_invisiref_parm into references if !wtd->handle_invisiref_parm_p. (cp_genericize_tree): Add handle_invisiref_parm_p argument, set wtd.handle_invisiref_parm_p to it. (cp_genericize): Pass true as handle_invisiref_parm_p to cp_genericize_tree. Formatting fix. * g++.dg/cpp1y/pr77739.C: New test. Added: branches/gcc-6-branch/gcc/testsuite/g++.dg/cpp1y/pr77739.C Modified: branches/gcc-6-branch/gcc/cp/ChangeLog branches/gcc-6-branch/gcc/cp/cp-gimplify.c branches/gcc-6-branch/gcc/testsuite/ChangeLog
Fixed for 6.3+ as well.
*** Bug 69001 has been marked as a duplicate of this bug. ***
Author: jakub Date: Tue May 30 07:44:11 2017 New Revision: 248627 URL: https://gcc.gnu.org/viewcvs?rev=248627&root=gcc&view=rev Log: Backported from mainline 2016-11-23 Jakub Jelinek <jakub@redhat.com> PR c++/77739 * cp-gimplify.c (cp_gimplify_tree) <case VEC_INIT_EXPR>: Pass false as handle_invisiref_parm_p to cp_genericize_tree. (struct cp_genericize_data): Add handle_invisiref_parm_p field. (cp_genericize_r): Don't wrap is_invisiref_parm into references if !wtd->handle_invisiref_parm_p. (cp_genericize_tree): Add handle_invisiref_parm_p argument, set wtd.handle_invisiref_parm_p to it. (cp_genericize): Pass true as handle_invisiref_parm_p to cp_genericize_tree. Formatting fix. * g++.dg/cpp1y/pr77739.C: New test. Added: branches/gcc-5-branch/gcc/testsuite/g++.dg/cpp1y/pr77739.C Modified: branches/gcc-5-branch/gcc/cp/ChangeLog branches/gcc-5-branch/gcc/cp/cp-gimplify.c branches/gcc-5-branch/gcc/testsuite/ChangeLog
Fixed.