Patchwork C++ PATCH for c++/48446 (ICE with VLA)

login
register
mail settings
Submitter Jason Merrill
Date April 14, 2011, 2:52 p.m.
Message ID <4DA70A16.8050303@redhat.com>
Download mbox | patch
Permalink /patch/91246/
State New
Headers show

Comments

Jason Merrill - April 14, 2011, 2:52 p.m.
The issue here was that with a complex expression in DECL_SIZE for z, 
when wrap_cleanups tried to protect the initializer of m it walked into 
the sizeof and thus the bounds expression, which it really shouldn't be 
messing with.

This patch avoids this issue by saving bounds values which have side 
effects into a local automatic variable (since VLAs can only appear in 
automatic variables).  We stick with the SAVE_EXPR approach for bounds 
without side-effects to avoid breaking vla9.C.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit e491243ab5dce11b38cae78911f107652fa0048b
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Apr 8 17:43:42 2011 -0400

    	PR c++/48446
    	* decl.c (compute_array_index_type): Use get_temp_regvar instead
    	of variable_size.
    	* init.c (get_temp_regvar): No longer static.
    	* cp-tree.h: Declare it.

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 15c1974..3ca44c2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4964,6 +4964,7 @@  extern tree build_offset_ref			(tree, tree, bool);
 extern tree build_new				(VEC(tree,gc) **, tree, tree,
 						 VEC(tree,gc) **, int,
                                                  tsubst_flags_t);
+extern tree get_temp_regvar			(tree, tree);
 extern tree build_vec_init			(tree, tree, tree, bool, int,
                                                  tsubst_flags_t);
 extern tree build_delete			(tree, tree,
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7dea9b7..2c0f80f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7710,8 +7710,16 @@  compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
       processing_template_decl = saved_processing_template_decl;
 
       if (!TREE_CONSTANT (itype))
-	/* A variable sized array.  */
-	itype = variable_size (itype);
+	{
+	  /* A variable sized array.  */
+	  if (TREE_SIDE_EFFECTS (itype))
+	    /* Use get_temp_regvar rather than variable_size here so that
+	       people walking expressions that use a variable of this type
+	       don't walk into this expression.  */
+	    itype = get_temp_regvar (TREE_TYPE (itype), itype);
+	  else
+	    itype = variable_size (itype);
+	}
       /* Make sure that there was no overflow when creating to a signed
 	 index type.  (For example, on a 32-bit machine, an array with
 	 size 2^32 - 1 is too big.)  */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3131690..32afa03 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -45,7 +45,6 @@  static void expand_virtual_init (tree, tree);
 static tree sort_mem_initializers (tree, tree);
 static tree initializing_context (tree);
 static void expand_cleanup_for_base (tree, tree);
-static tree get_temp_regvar (tree, tree);
 static tree dfs_initialize_vtbl_ptrs (tree, void *);
 static tree build_dtor_call (tree, special_function_kind, int);
 static tree build_field_list (tree, tree, int *);
@@ -2875,7 +2874,7 @@  create_temporary_var (tree type)
    things when it comes time to do final cleanups (which take place
    "outside" the binding contour of the function).  */
 
-static tree
+tree
 get_temp_regvar (tree type, tree init)
 {
   tree decl;
diff --git a/gcc/testsuite/g++.dg/ext/vla10.C b/gcc/testsuite/g++.dg/ext/vla10.C
new file mode 100644
index 0000000..17cdb2f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vla10.C
@@ -0,0 +1,32 @@ 
+// PR c++/48446
+// { dg-options "" }
+
+template<typename T>
+struct A
+{
+  ~A ();
+  T *operator-> () const;
+};
+
+struct B
+{
+  typedef A <B> P;
+  static P foo (int);
+};
+
+struct C
+{
+  typedef A<C> P;
+  static const int c = 80;
+};
+
+C::P bar ();
+
+void
+baz ()
+{
+  char z[bar ()->c];
+  {
+    B::P m = B::foo (sizeof (z));
+  }
+}