Found on ARM, reproducible on x86 (32bit) as well: char[] func1() { return []; } void test1() { func1()[] = 'y'; } gdc -c test7.d -m32 In d_build_call CALL_EXPR_RETURN_SLOT_OPT is set on 32 bit targets only and build_target_expr is called. in ExprVisitor::AssignExp we call d_save_expr on the result. For 32 bit targets is_lvalue_p returns true, as we have a TARGET_EXPR and not CALL_EXPR. Because of that we don't create a SAVE_EXPR. The codegen then somehow recursively accesses some expressions which causes the error below. Also "gdc -c test7.d -m32 -fdump-tree-original" does not work and enters an infinite loop. --------------------------------------------------------- test7.d: In function 'test1': test7.d:8:5: internal compiler error: in gimple_add_tmp_var, at gimplify.c:703 func1()[] = 'y'; ^ 0x9d16b9 gimple_add_tmp_var(tree_node*) ../../gcc-7-20160619/gcc/gimplify.c:703 0x9d9867 gimplify_target_expr ../../gcc-7-20160619/gcc/gimplify.c:5688 0x9d9867 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc-7-20160619/gcc/gimplify.c:10803 0x9deb03 gimplify_compound_lval ../../gcc-7-20160619/gcc/gimplify.c:2195 0x9d5d4a gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc-7-20160619/gcc/gimplify.c:10386 0x9e8cfa gimplify_modify_expr ../../gcc-7-20160619/gcc/gimplify.c:4798 0x9d7b8a gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc-7-20160619/gcc/gimplify.c:10434 0x9daee6 gimplify_stmt(tree_node**, gimple**) ../../gcc-7-20160619/gcc/gimplify.c:5767 0x9d5e9b gimplify_statement_list ../../gcc-7-20160619/gcc/gimplify.c:1549 0x9d5e9b gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc-7-20160619/gcc/gimplify.c:10851 0x9daee6 gimplify_stmt(tree_node**, gimple**) ../../gcc-7-20160619/gcc/gimplify.c:5767 0x9dc135 gimplify_bind_expr ../../gcc-7-20160619/gcc/gimplify.c:1154 0x9d8045 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc-7-20160619/gcc/gimplify.c:10633 0x9daee6 gimplify_stmt(tree_node**, gimple**) ../../gcc-7-20160619/gcc/gimplify.c:5767 0x9dbb01 gimplify_compound_expr ../../gcc-7-20160619/gcc/gimplify.c:5029 0x9e1ba7 gimplify_modify_expr_rhs ../../gcc-7-20160619/gcc/gimplify.c:4407 0x9e8b39 gimplify_modify_expr ../../gcc-7-20160619/gcc/gimplify.c:4757 0x9d7b8a gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc-7-20160619/gcc/gimplify.c:10434 0x9d7cce gimplify_target_expr ../../gcc-7-20160619/gcc/gimplify.c:5698 0x9d7cce gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc-7-20160619/gcc/gimplify.c:10803 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://bugzilla.gdcproject.org> for instructions.
I guess the right way to go about it is to separate save_expr into lvalue and rvalue variants. Probably the best way to ensure we don't try to initialize a temporary. Places that really need save_expr I guess would then just call save_expr directly.
Looks like something recursive is going on. --- $ gdc bug235.d -m32 -fdump-tree-original=stdout ;; Function func1 (_D6bug2355func1FZAa) ;; enabled by -tree-original { return <retval> = {.length=0, .ptr=0B}; } ;; Function test1 (_D6bug2355test1FZv) ;; enabled by -tree-original gdc: internal compiler error: Segmentation fault (program cc1d) Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. --- It hangs for a while before the segfault. Best guess would be stack overflow.
In compound_expr --- if (TREE_CODE (arg1) == TARGET_EXPR) { // If the rhs is a TARGET_EXPR, then build the compound expression // inside the target_expr's initializer. This helps the compiler // to eliminate unnecessary temporaries. tree init = compound_expr(arg0, TREE_OPERAND (arg1, 1)); TREE_OPERAND (arg1, 1) = init; return arg1; } --- (gdb) call debug_generic_expr (arg1) TARGET_EXPR <D.3436, func1 () [return slot optimization]> --- (gdb) call debug_generic_expr (init) { char * D.3438; uint D.3437; D.3437 = (TARGET_EXPR <D.3436, func1 () [return slot optimization]>).length; D.3438 = (TARGET_EXPR <D.3436, func1 () [return slot optimization]>).ptr; while (1) { if (D.3437 == 0) break; *D.3438 = 121; D.3438++ ; D.3437-- ; } }, func1 () [return slot optimization]; --- This is where the recursion comes from. On x86_64 no TARGET_EXPR is created. I'd say the creation of a TARGET_EXPR may be dubious anyway. Hmm...
https://github.com/D-Programming-GDC/GDC/commit/30764bdc2b7587f672eb51dd8704575db30010f6