aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-typeck.c10
-rw-r--r--gcc/cgraphunit.c4
-rw-r--r--gcc/gimplify.c3
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/nested-func-10.c56
-rw-r--r--gcc/testsuite/gcc.dg/nested-func-9.c47
8 files changed, 138 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d1dd80f..0af222e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2016-03-16 Marek Polacek <polacek@redhat.com>
+
+ PR c/70093
+ * cgraphunit.c (cgraph_node::expand_thunk): Also build call to the
+ function being thunked if the result type doesn't have fixed size.
+ * gimplify.c (gimplify_modify_expr): Also set LHS if the result type
+ doesn't have fixed size.
+
2016-03-16 Bin Cheng <bin.cheng@arm.com>
* tree-vect-loop.c (vect_analyze_loop_2): Fix wrong dump info by
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 95fde9f..fa657e5 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,9 @@
+2016-03-16 Marek Polacek <polacek@redhat.com>
+
+ PR c/70093
+ * c-typeck.c (build_function_call_vec): Create a TARGET_EXPR for
+ nested functions returning VM types.
+
2016-03-09 Cesar Philippidis <cesar@codesourcery.com>
* c-parser.c (c_parser_oacc_loop): Update cclauses and clauses
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 6aa0f03..de9d465 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3068,6 +3068,16 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
result = build_call_array_loc (loc, TREE_TYPE (fntype),
function, nargs, argarray);
+ /* In this improbable scenario, a nested function returns a VM type.
+ Create a TARGET_EXPR so that the call always has a LHS, much as
+ what the C++ FE does for functions returning non-PODs. */
+ if (variably_modified_type_p (TREE_TYPE (fntype), NULL_TREE))
+ {
+ tree tmp = create_tmp_var_raw (TREE_TYPE (fntype));
+ result = build4 (TARGET_EXPR, TREE_TYPE (fntype), tmp, result,
+ NULL_TREE, NULL_TREE);
+ }
+
if (VOID_TYPE_P (TREE_TYPE (result)))
{
if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 8b3fddc..4351ae4 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1708,7 +1708,9 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
/* Build call to the function being thunked. */
if (!VOID_TYPE_P (restype)
- && (!alias_is_noreturn || TREE_ADDRESSABLE (restype)))
+ && (!alias_is_noreturn
+ || TREE_ADDRESSABLE (restype)
+ || TREE_CODE (TYPE_SIZE_UNIT (restype)) != INTEGER_CST))
{
if (DECL_BY_REFERENCE (resdecl))
{
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index b331e41..692d168 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4838,7 +4838,8 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
}
notice_special_calls (call_stmt);
if (!gimple_call_noreturn_p (call_stmt)
- || TREE_ADDRESSABLE (TREE_TYPE (*to_p)))
+ || TREE_ADDRESSABLE (TREE_TYPE (*to_p))
+ || TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) != INTEGER_CST)
gimple_call_set_lhs (call_stmt, *to_p);
assign = call_stmt;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0f61a7e..5b46956 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-03-16 Marek Polacek <polacek@redhat.com>
+
+ PR c/70093
+ * gcc.dg/nested-func-10.c: New test.
+ * gcc.dg/nested-func-9.c: New test.
+
2016-03-16 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/68714
diff --git a/gcc/testsuite/gcc.dg/nested-func-10.c b/gcc/testsuite/gcc.dg/nested-func-10.c
new file mode 100644
index 0000000..ac6f76f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/nested-func-10.c
@@ -0,0 +1,56 @@
+/* PR c/70093 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void __attribute__((noinline, noclone))
+foo (int n)
+{
+ struct S { int a[n]; };
+
+ struct S __attribute__((noreturn))
+ fn (void)
+ {
+ __builtin_abort ();
+ }
+
+ auto struct S __attribute__((noreturn))
+ fn2 (void)
+ {
+ __builtin_abort ();
+ }
+
+ struct S x;
+ __typeof__ (fn ()) *p = &x;
+ switch (n)
+ {
+ case 1:
+ fn ();
+ break;
+ case 2:
+ fn2 ();
+ break;
+ case 3:
+ x = fn ();
+ if (x.a[0] != 42)
+ __builtin_abort ();
+ break;
+ case 4:
+ if (fn ().a[0] != 42)
+ __builtin_abort ();
+ break;
+ case 5:
+ if (p->a[0] != 42)
+ __builtin_abort ();
+ break;
+ case 6:
+ if (fn2 ().a[0] != 42)
+ __builtin_abort ();
+ break;
+ }
+}
+
+int
+main (void)
+{
+ foo (1);
+}
diff --git a/gcc/testsuite/gcc.dg/nested-func-9.c b/gcc/testsuite/gcc.dg/nested-func-9.c
new file mode 100644
index 0000000..902c258
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/nested-func-9.c
@@ -0,0 +1,47 @@
+/* PR c/70093 */
+/* { dg-do run } */
+/* { dg-options "" } */
+
+void
+foo (int n)
+{
+ struct S { int a[n]; };
+
+ struct S
+ fn (void)
+ {
+ struct S s;
+ s.a[0] = 42;
+ return s;
+ }
+
+ auto struct S
+ fn2 (void)
+ {
+ return fn ();
+ }
+
+ struct S x;
+ fn ();
+ fn2 ();
+ x = fn ();
+
+ if (x.a[0] != 42)
+ __builtin_abort ();
+
+ if (fn ().a[0] != 42)
+ __builtin_abort ();
+
+ __typeof__ (fn ()) *p = &x;
+ if (p->a[0] != 42)
+ __builtin_abort ();
+
+ if (fn2 ().a[0] != 42)
+ __builtin_abort ();
+}
+
+int
+main (void)
+{
+ foo (1);
+}