From e6a54b01852b536ce67c8a6639adc455f36f3891 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 1 Jun 2015 20:49:18 +0000 Subject: [PATCH] gimplify.c (gimplify_modify_expr_rhs): Use simple test on the size. * gimplify.c (gimplify_modify_expr_rhs): Use simple test on the size. * cgraph.c (cgraph_redirect_edge_call_stmt_to_callee): Do not remove the LHS of a no-return call if its type has variable size. * tree-cfgcleanup.c (fixup_noreturn_call): Likewise. * tree-cfg.c (verify_gimple_call): Accept these no-return calls. From-SVN: r223997 --- gcc/ChangeLog | 8 +++++++ gcc/cgraph.c | 6 +++-- gcc/gimplify.c | 3 ++- gcc/testsuite/ChangeLog | 5 ++++ .../gnat.dg/specs/varsize_return2.ads | 12 ++++++++++ .../gnat.dg/specs/varsize_return2_pkg.adb | 18 +++++++++++++++ .../gnat.dg/specs/varsize_return2_pkg.ads | 20 ++++++++++++++++ gcc/tree-cfg.c | 23 ++++++++++--------- gcc/tree-cfgcleanup.c | 6 +++-- 9 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/specs/varsize_return2.ads create mode 100644 gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.ads diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a7f3071e913..a19528320f1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-06-01 Eric Botcazou + + * gimplify.c (gimplify_modify_expr_rhs): Use simple test on the size. + * cgraph.c (cgraph_redirect_edge_call_stmt_to_callee): Do not remove + the LHS of a no-return call if its type has variable size. + * tree-cfgcleanup.c (fixup_noreturn_call): Likewise. + * tree-cfg.c (verify_gimple_call): Accept these no-return calls. + 2015-06-01 Andreas Tobler * read-rtl.c: Adapt to use HAVE_DECL_ATOLL instead of HAVE_ATOLL. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 6a674db4078..2ded5af546e 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1464,8 +1464,10 @@ cgraph_edge::redirect_call_stmt_to_callee (void) 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) { diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2720d02f47a..58a60bfd62a 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4341,7 +4341,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8168fabd76c..09395da513c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-06-01 Eric Botcazou + + * gnat.dg/specs/varsize_return2.ads: New test. + * gnat.dg/specs/varsize_return2_pkg.ad[sb]: New helper. + 2015-06-01 Yuri Rumyantsev * gcc.dg/vect/vect-outer-simd-1.c: New test. diff --git a/gcc/testsuite/gnat.dg/specs/varsize_return2.ads b/gcc/testsuite/gnat.dg/specs/varsize_return2.ads new file mode 100644 index 00000000000..1f7d1a0d860 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/varsize_return2.ads @@ -0,0 +1,12 @@ +-- { dg-do compile } +-- { dg-options "-O" } + +with Varsize_Return2_Pkg; use Varsize_Return2_Pkg; + +package Varsize_Return2 is + + package My_G is new G (0); + + Result : constant T := My_G.Get; + +end Varsize_Return2; diff --git a/gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.adb b/gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.adb new file mode 100644 index 00000000000..f37d2fafd6d --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.adb @@ -0,0 +1,18 @@ +package body Varsize_Return2_Pkg is + + function Len return Positive is + begin + return 4; + end; + + package body G is + + function Get return Small_T is + begin + raise Program_Error; + return Get; + end; + + end G; + +end Varsize_Return2_Pkg; diff --git a/gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.ads b/gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.ads new file mode 100644 index 00000000000..1fe40b9b285 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.ads @@ -0,0 +1,20 @@ +-- { dg-excess-errors "no code generated" } + +package Varsize_Return2_Pkg is + + type T (D: Positive) is record + Data: String (1 .. D); + end record; + + function Len return Positive; + + generic + I : Integer; + package G is + + subtype Small_T is T(Len); + function Get return Small_T; + + end G; + +end Varsize_Return2_Pkg; diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 99b27c7dc97..c53cf3e76e9 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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; } diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 26258aad1ef..562f5923614 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -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); -- 2.30.2