]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/43555 (wrong address calculation of multidimensional variable-length array...
authorJason Merrill <jason@redhat.com>
Thu, 27 May 2010 20:02:10 +0000 (16:02 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 27 May 2010 20:02:10 +0000 (16:02 -0400)
PR c++/43555
* decl.c (grokdeclarator) [cdk_pointer et al]: Force evaluation of
anonymous VLA size.

From-SVN: r159945

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/vla9.C [new file with mode: 0644]

index 75a53daced9901e54359de58a607867c7f4502fd..ad998d3db199cb509f5443bc30cdf1319b722852 100644 (file)
@@ -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-22  Release Manager
 
        * GCC 4.3.5 released.
index c737169837caa7cd5270e20d59285171fb1f3632..239bac337c094351bc384881c7dcd5a07efb99a0 100644 (file)
@@ -8248,6 +8248,40 @@ grokdeclarator (const cp_declarator *declarator,
              memfn_quals = TYPE_UNQUALIFIED;
            }
 
+         if (TREE_CODE (type) == FUNCTION_TYPE
+             && cp_type_quals (type) != TYPE_UNQUALIFIED)
+           error ("cannot declare %s to qualified function type %qT",
+                  declarator->kind == cdk_reference ? "reference" : "pointer",
+                  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
index 2f6bab9fd5c631112de39cde9bbe923e3113d157..a646a165a3ea63e4ff942c1ac692ac26997c8841 100644 (file)
@@ -1,3 +1,8 @@
+2010-05-27  Jason Merrill  <jason@redhat.com>
+
+       PR c++/43555
+       * g++.dg/ext/vla9.C: New.
+
 2010-05-22  Release Manager
 
        * GCC 4.3.5 released.
diff --git a/gcc/testsuite/g++.dg/ext/vla9.C b/gcc/testsuite/g++.dg/ext/vla9.C
new file mode 100644 (file)
index 0000000..c58edbc
--- /dev/null
@@ -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;
+}