aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-05-27 14:39:28 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-05-27 14:39:28 -0400
commit6ab4e49cf07eb5a88ee22018db6b4be5715dc4f3 (patch)
tree1b85f7a0d257ecc9011ec995e7345b82efe83f45
parent7ec62b257548e59a77eb7b7c2ffc467bc5fa21c7 (diff)
downloadgcc-6ab4e49cf07eb5a88ee22018db6b4be5715dc4f3.zip
gcc-6ab4e49cf07eb5a88ee22018db6b4be5715dc4f3.tar.gz
gcc-6ab4e49cf07eb5a88ee22018db6b4be5715dc4f3.tar.bz2
re PR c++/43555 (wrong address calculation of multidimensional variable-length array element)
PR c++/43555 * decl.c (grokdeclarator) [cdk_pointer et al]: Force evaluation of anonymous VLA size. From-SVN: r159939
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c28
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ext/vla9.C38
4 files changed, 77 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5c094b7..f63703e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2010-05-27 Jason Merrill <jason@redhat.com>
+
+ PR c++/43555
+ * decl.c (grokdeclarator) [cdk_pointer et al]: Force evaluation of
+ anonymous VLA size.
+
2010-05-27 Kai Tietz <kai.tietz@onevision.com>
PR bootstrap/44287
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e560cb4..0d30340 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8705,6 +8705,34 @@ grokdeclarator (const cp_declarator *declarator,
: G_("cannot declare pointer to qualified function type %qT"),
type);
+ /* When the pointed-to type involves components of variable size,
+ care must be taken to ensure that the size evaluation code is
+ emitted early enough to dominate all the possible later uses
+ and late enough for the variables on which it depends to have
+ been assigned.
+
+ This is expected to happen automatically when the pointed-to
+ type has a name/declaration of it's own, but special attention
+ is required if the type is anonymous.
+
+ We handle the NORMAL and FIELD contexts here by inserting a
+ dummy statement that just evaluates the size at a safe point
+ and ensures it is not deferred until e.g. within a deeper
+ conditional context (c++/43555).
+
+ We expect nothing to be needed here for PARM or TYPENAME.
+ Evaluating the size at this point for TYPENAME would
+ actually be incorrect, as we might be in the middle of an
+ expression with side effects on the pointed-to type size
+ "arguments" prior to the pointer declaration point and the
+ size evaluation could end up prior to the side effects. */
+
+ if (!TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && at_function_scope_p ()
+ && variably_modified_type_p (type, NULL_TREE))
+ finish_expr_stmt (TYPE_SIZE (type));
+
if (declarator->kind == cdk_reference)
{
/* In C++0x, the type we are creating a reference to might be
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 63e32a3..5501c8d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-05-27 Jason Merrill <jason@redhat.com>
+
+ PR c++/43555
+ * g++.dg/ext/vla9.C: New.
+
2010-05-27 Iain Sandoe <iains@gcc.gnu.org>
PR ObjC/44140
diff --git a/gcc/testsuite/g++.dg/ext/vla9.C b/gcc/testsuite/g++.dg/ext/vla9.C
new file mode 100644
index 0000000..c58edbc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vla9.C
@@ -0,0 +1,38 @@
+// PR c++/43555
+// { dg-options "" }
+// { dg-do run }
+
+extern "C" void * malloc (__SIZE_TYPE__);
+extern "C" int printf (const char *, ...);
+extern "C" void abort(void);
+
+int nx,ny;
+
+void f(double *x1d,int choice)
+{
+ double (*x2d)[nx][ny]=(double(*)[nx][ny])x1d;
+ unsigned long delta;
+// (*x2d)[0][0]=123; // <- this line affects the result
+ if (choice!=0)
+ {
+ delta=&(*x2d)[1][0]-x1d;
+ }
+ else
+ {
+ delta=&(*x2d)[1][0]-x1d;
+ }
+ printf("Choice: %d, Delta: %ld\n",choice,delta);
+ if (delta != ny)
+ abort ();
+}
+
+int main()
+{
+ double *data;
+ nx=100;
+ ny=100;
+ data=(double*)malloc(nx*ny*sizeof(double));
+ f(data,0);
+ f(data,1);
+ return 0;
+}