c++: Fix cast to pointer to VLA.
authorJason Merrill <jason@redhat.com>
Sat, 1 Feb 2020 02:59:48 +0000 (21:59 -0500)
committerJason Merrill <jason@redhat.com>
Mon, 3 Feb 2020 14:21:06 +0000 (09:21 -0500)
The C front-end fixed this issue in r257620 by adding a DECL_EXPR from
grokdeclarator.  We don't have an easy way to do that in the C++ front-end,
but it works fine to create and prepend a DECL_EXPR when we are genericizing
the NOP_EXPR for the cast.

The C patch wraps the DECL_EXPR in a BIND_EXPR, but that seems unnecessary
in C++; this is just a hook to run gimplify_type_sizes, we aren't actually
declaring anything that we need to worry about scoping for.

PR c++/88256
* cp-gimplify.c (predeclare_vla): New.
(cp_genericize_r) [NOP_EXPR]: Call it.

gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/testsuite/c-c++-common/pr84305.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/pr84305.c [deleted file]

index 4e2b0c5e4e38188df04e450387462db3dd8f8acf..3144688f090c406a38fc16aeb95e045f27bd08b5 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-03  Jason Merrill  <jason@redhat.com>
+
+       PR c++/88256
+       * cp-gimplify.c (predeclare_vla): New.
+       (cp_genericize_r) [NOP_EXPR]: Call it.
+
 2020-02-03  Jun Ma <JunMa@linux.alibaba.com>
 
        * coroutines.cc (transform_await_wrapper): Set actor funcion as
index 4fb3a1a8b8af39bdb95a5031adbe3ab4f7f01762..10ab99515e66594b3175e22737cd543ea1f5b03a 100644 (file)
@@ -1188,6 +1188,36 @@ static tree genericize_spaceship (tree expr)
   return genericize_spaceship (type, op0, op1);
 }
 
+/* If EXPR involves an anonymous VLA type, prepend a DECL_EXPR for that type
+   to trigger gimplify_type_sizes; otherwise a cast to pointer-to-VLA confuses
+   the middle-end (c++/88256).  */
+
+static tree
+predeclare_vla (tree expr)
+{
+  tree type = TREE_TYPE (expr);
+  if (type == error_mark_node)
+    return expr;
+
+  /* We need to strip pointers for gimplify_type_sizes.  */
+  tree vla = type;
+  while (POINTER_TYPE_P (vla))
+    {
+      if (TYPE_NAME (vla))
+       return expr;
+      vla = TREE_TYPE (vla);
+    }
+  if (TYPE_NAME (vla) || !variably_modified_type_p (vla, NULL_TREE))
+    return expr;
+
+  tree decl = build_decl (input_location, TYPE_DECL, NULL_TREE, vla);
+  DECL_ARTIFICIAL (decl) = 1;
+  TYPE_NAME (vla) = decl;
+  tree dexp = build_stmt (input_location, DECL_EXPR, decl);
+  expr = build2 (COMPOUND_EXPR, type, dexp, expr);
+  return expr;
+}
+
 /* Perform any pre-gimplification lowering of C++ front end trees to
    GENERIC.  */
 
@@ -1648,6 +1678,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       break;
 
     case NOP_EXPR:
+      *stmt_p = predeclare_vla (*stmt_p);
       if (!wtd->no_sanitize_p
          && sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT)
          && TYPE_REF_P (TREE_TYPE (stmt)))
diff --git a/gcc/testsuite/c-c++-common/pr84305.c b/gcc/testsuite/c-c++-common/pr84305.c
new file mode 100644 (file)
index 0000000..27150dd
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-additional-options -O3 }
+
+int res, a, b;
+void *foo;
+static void f2 (int arg) { res = ((int (*)[arg][b]) foo)[0][0][0]; }
+void f1 (void) { f2 (a); }
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr84305.c b/gcc/testsuite/gcc.c-torture/compile/pr84305.c
deleted file mode 100644 (file)
index 374fa67..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-int res, a, b;
-void *foo;
-static void f2 (int arg) { res = ((int (*)[arg][b]) foo)[0][0][0]; }
-void f1 (void) { f2 (a); }