From 2e3f487777bc08719871aed1a0807e9a969ab48d Mon Sep 17 00:00:00 2001
From: rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Thu, 12 Aug 2004 04:09:57 +0000
Subject: [PATCH]         * c-common.h (STATEMENT_LIST_HAS_LABEL): New.        
 * c-semantics.c (add_stmt): Set it.         * c-decl.c (finish_decl): Use it
 to create a new BIND_EXPR         before instantiating a variable sized type.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@85849 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                                 |  7 +++++++
 gcc/c-common.h                                |  6 +++++-
 gcc/c-decl.c                                  | 19 ++++++++++++++++++-
 gcc/c-semantics.c                             |  3 +++
 .../gcc.c-torture/execute/20040811-1.c        | 19 +++++++++++++++++++
 5 files changed, 52 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/20040811-1.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e3cd92d37258..b0e986be8fc2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2004-08-12  Richard Henderson  <rth@redhat.com>
+
+	* c-common.h (STATEMENT_LIST_HAS_LABEL): New.
+	* c-semantics.c (add_stmt): Set it.
+	* c-decl.c (finish_decl): Use it to create a new BIND_EXPR
+	before instantiating a variable sized type.
+
 2004-08-12  Richard Henderson  <rth@redhat.com>
 
 	* stor-layout.c (round_up, round_down): Move ...
diff --git a/gcc/c-common.h b/gcc/c-common.h
index e8d245c88b14..1c9286ef7b79 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -35,7 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       STMT_IS_FULL_EXPR_P (in _STMT)
       STATEMENT_LIST_STMT_EXPR (in STATEMENT_LIST)
    2: unused
-   3: unused
+   3: STATEMENT_LIST_HAS_LABEL (in STATEMENT_LIST)
    4: unused
 */
 
@@ -708,6 +708,10 @@ extern void finish_file	(void);
 #define STATEMENT_LIST_STMT_EXPR(NODE) \
   TREE_LANG_FLAG_1 (STATEMENT_LIST_CHECK (NODE))
 
+/* Nonzero if a label has been added to the statement list.  */
+#define STATEMENT_LIST_HAS_LABEL(NODE) \
+  TREE_LANG_FLAG_3 (STATEMENT_LIST_CHECK (NODE))
+
 /* WHILE_STMT accessors. These give access to the condition of the
    while statement and the body of the while statement, respectively.  */
 #define WHILE_COND(NODE)        TREE_OPERAND (WHILE_STMT_CHECK (NODE), 0)
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index c03c1262f3b5..82e42f04e663 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3061,7 +3061,24 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
 	    }
 
 	  if (TREE_CODE (decl) != FUNCTION_DECL)
-	    add_stmt (build_stmt (DECL_EXPR, decl));
+	    {
+	      /* If we're building a variable sized type, and we might be
+		 reachable other than via the top of the current binding
+		 level, then create a new BIND_EXPR so that we deallocate
+		 the object at the right time.  */
+	      /* Note that DECL_SIZE can be null due to errors.  */
+	      if (DECL_SIZE (decl)
+		  && !TREE_CONSTANT (DECL_SIZE (decl))
+		  && STATEMENT_LIST_HAS_LABEL (cur_stmt_list))
+		{
+		  tree bind;
+		  bind = build (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+		  TREE_SIDE_EFFECTS (bind) = 1;
+		  add_stmt (bind);
+		  BIND_EXPR_BODY (bind) = push_stmt_list ();
+		}
+	      add_stmt (build_stmt (DECL_EXPR, decl));
+	    }
 	}
   
 
diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c
index f40f5a2e495a..f011cb90a1e3 100644
--- a/gcc/c-semantics.c
+++ b/gcc/c-semantics.c
@@ -140,6 +140,9 @@ add_stmt (tree t)
       STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
     }
 
+  if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
+    STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
+
   /* Add T to the statement-tree.  Non-side-effect statements need to be
      recorded during statement expressions.  */
   append_to_statement_list_force (t, &cur_stmt_list);
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040811-1.c b/gcc/testsuite/gcc.c-torture/execute/20040811-1.c
new file mode 100644
index 000000000000..62f377a2f245
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20040811-1.c
@@ -0,0 +1,19 @@
+/* Ensure that we deallocate X when branching back before its
+   declaration.  */
+
+void *volatile p;
+                                                                                
+int
+main (void)
+{
+  int n = 0;
+ lab:;
+  int x[n % 1000 + 1];
+  x[0] = 1;
+  x[n % 1000] = 2;
+  p = x;
+  n++;
+  if (n < 1000000)
+    goto lab;
+  return 0;
+}
-- 
GitLab