summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2015-06-01 20:49:18 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2015-06-01 20:49:18 +0000
commit33b2642e544d575f2a62538b79cc677b0dfae746 (patch)
tree83d3f1184dd0b41ae0e5c786c8add2d6cfd17d07 /gcc
parentb5e563e408f9e1941f981da849114bb23f8c8473 (diff)
downloadgcc-33b2642e544d575f2a62538b79cc677b0dfae746.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223997 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cgraph.c6
-rw-r--r--gcc/gimplify.c3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gnat.dg/specs/varsize_return2.ads12
-rw-r--r--gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.adb18
-rw-r--r--gcc/testsuite/gnat.dg/specs/varsize_return2_pkg.ads20
-rw-r--r--gcc/tree-cfg.c23
-rw-r--r--gcc/tree-cfgcleanup.c6
9 files changed, 85 insertions, 16 deletions
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 <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.
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 <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
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);