Index: cgraph.c =================================================================== --- cgraph.c (revision 223897) +++ cgraph.c (working copy) @@ -1449,8 +1449,10 @@ cgraph_edge::redirect_call_stmt_to_calle update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); } - /* If the call becomes noreturn, remove the lhs. */ - if (lhs && (gimple_call_flags (new_stmt) & ECF_NORETURN)) + /* If the call becomes noreturn, remove the LHS if possible. */ + if (lhs + && (gimple_call_flags (new_stmt) & ECF_NORETURN) + && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST) { if (TREE_CODE (lhs) == SSA_NAME) { Index: gimplify.c =================================================================== --- gimplify.c (revision 223897) +++ gimplify.c (working copy) @@ -4341,7 +4341,8 @@ gimplify_modify_expr_rhs (tree *expr_p, /* It's OK to use the target directly if it's being initialized. */ use_target = true; - else if (variably_modified_type_p (TREE_TYPE (*to_p), NULL_TREE)) + else if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) + != INTEGER_CST) /* Always use the target and thus RSO for variable-sized types. GIMPLE cannot deal with a variable-sized assignment embedded in a call statement. */ Index: tree-cfgcleanup.c =================================================================== --- tree-cfgcleanup.c (revision 223897) +++ tree-cfgcleanup.c (working copy) @@ -612,9 +612,11 @@ fixup_noreturn_call (gimple stmt) } } - /* If there is an LHS, remove it. */ + /* If there is an LHS, remove it, but only if its type has fixed size. + The LHS will need to be recreated during RTL expansion and creating + temporaries of variable-sized types is not supported. */ tree lhs = gimple_call_lhs (stmt); - if (lhs) + if (lhs && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST) { gimple_call_set_lhs (stmt, NULL_TREE); Index: tree-cfg.c =================================================================== --- tree-cfg.c (revision 223897) +++ tree-cfg.c (working copy) @@ -3391,17 +3391,19 @@ verify_gimple_call (gcall *stmt) return true; } - if (gimple_call_lhs (stmt) - && (!is_gimple_lvalue (gimple_call_lhs (stmt)) - || verify_types_in_gimple_reference (gimple_call_lhs (stmt), true))) + tree lhs = gimple_call_lhs (stmt); + if (lhs + && (!is_gimple_lvalue (lhs) + || verify_types_in_gimple_reference (lhs, true))) { error ("invalid LHS in gimple call"); return true; } - if (gimple_call_ctrl_altering_p (stmt) - && gimple_call_lhs (stmt) - && gimple_call_noreturn_p (stmt)) + if (lhs + && gimple_call_ctrl_altering_p (stmt) + && gimple_call_noreturn_p (stmt) + && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST) { error ("LHS in noreturn call"); return true; @@ -3409,19 +3411,18 @@ verify_gimple_call (gcall *stmt) fntype = gimple_call_fntype (stmt); if (fntype - && gimple_call_lhs (stmt) - && !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)), - TREE_TYPE (fntype)) + && lhs + && !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (fntype)) /* ??? At least C++ misses conversions at assignments from void * call results. ??? Java is completely off. Especially with functions returning java.lang.Object. For now simply allow arbitrary pointer type conversions. */ - && !(POINTER_TYPE_P (TREE_TYPE (gimple_call_lhs (stmt))) + && !(POINTER_TYPE_P (TREE_TYPE (lhs)) && POINTER_TYPE_P (TREE_TYPE (fntype)))) { error ("invalid conversion in gimple call"); - debug_generic_stmt (TREE_TYPE (gimple_call_lhs (stmt))); + debug_generic_stmt (TREE_TYPE (lhs)); debug_generic_stmt (TREE_TYPE (fntype)); return true; }