gimplify.c (gimplify_modify_expr_rhs): Use simple test on the size.
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 1 Jun 2015 20:49:18 +0000 (20:49 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 1 Jun 2015 20:49:18 +0000 (20:49 +0000)
* 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
gcc/cgraph.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/specs/varsize_return2.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.ads [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-cfgcleanup.c

index a7f3071e91375f4ee526a2e37ac20a571e85e055..a19528320f199e7fce4f1584607005f47e3a3821 100644 (file)
@@ -1,3 +1,11 @@
+2015-06-01  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * 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  <andreast@gcc.gnu.org>
 
        * read-rtl.c: Adapt to use HAVE_DECL_ATOLL instead of HAVE_ATOLL.
index 6a674db4078f13352427b6aeef7d10a3796a287c..2ded5af546e1e499074642988fed12fef9ba0921 100644 (file)
@@ -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)
        {
index 2720d02f47aa1457080a471a46367a82afd52269..58a60bfd62a8238f4a8f1fcfc7bbbe9e5c1bbefa 100644 (file)
@@ -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.  */
index 8168fabd76c6ab55a44e150796e6b6e4e1e1e4b2..09395da513ca38d0e7285bdb9fc7b08abb3bfcaa 100644 (file)
@@ -1,3 +1,8 @@
+2015-06-01  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/specs/varsize_return2.ads: New test.
+       * gnat.dg/specs/varsize_return2_pkg.ad[sb]: New helper.
+
 2015-06-01  Yuri Rumyantsev  <ysrumyan@gmail.com>
 
        * 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 (file)
index 0000000..1f7d1a0
--- /dev/null
@@ -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 (file)
index 0000000..f37d2fa
--- /dev/null
@@ -0,0 +1,18 @@
+package body Varsize_Return2_Pkg is\r
+\r
+   function Len return Positive is\r
+   begin\r
+      return 4;\r
+   end;\r
+\r
+   package body G is\r
+\r
+      function Get return Small_T is\r
+      begin\r
+         raise Program_Error;\r
+         return Get;\r
+      end;\r
+\r
+   end G;\r
+\r
+end Varsize_Return2_Pkg;\r
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 (file)
index 0000000..1fe40b9
--- /dev/null
@@ -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;
index 99b27c7dc97d979fb883cf9dce3e2d3231b8749d..c53cf3e76e965295effbfcf482ebf37c847d81f6 100644 (file)
@@ -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;
     }
index 26258aad1ef0da9ba58868ed2f9c56352ac23602..562f59236148d7967cefaefa2283eb45bd5ef6e6 100644 (file)
@@ -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);