Add a DECL_EXPR for VLA pointer casts (PR 84305)
authorRichard Sandiford <richard.sandiford@linaro.org>
Tue, 13 Feb 2018 10:28:54 +0000 (10:28 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 13 Feb 2018 10:28:54 +0000 (10:28 +0000)
This PR was about a case in which we ended up with a MULT_EXPR
that was shared between an ungimplified VLA type and a pointer
calculation.  The SSA names used in the pointer calculation were
later freed, but they were still there in the VLA, and caused an
ICE when remapping the types during inlinling.

The fix is to add a DECL_EXPR that forces the VLA type sizes to be
gimplified too, but the tricky part is deciding where.  As the comment
in grokdeclarator says, we can't just add it to the statement list,
since the size might only be conditionally evaluated.  It might also
end up being evaluated out of sequence.

The patch gets around that by putting the DECL_EXPR in a BIND_EXPR
and adding the BIND_EXPR to the list of things that need to be
evaluated for the declarator.

2018-02-13  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/c/
PR c/84305
* c-decl.c (grokdeclarator): Create an anonymous TYPE_DECL
in PARM and TYPENAME contexts too, but attach it to a BIND_EXPR
and include the BIND_EXPR in the list of things that need to be
pre-evaluated.

gcc/testsuite/
PR c/84305
* gcc.c-torture/compile/pr84305.c: New test.

From-SVN: r257620

gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr84305.c [new file with mode: 0644]

index bca7268c118f271db163c54e66881e18bc9ad988..f0fd33e9790d584f074899156dee5e5961fe60c5 100644 (file)
@@ -1,3 +1,11 @@
+2018-02-13  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR c/84305
+       * c-decl.c (grokdeclarator): Create an anonymous TYPE_DECL
+       in PARM and TYPENAME contexts too, but attach it to a BIND_EXPR
+       and include the BIND_EXPR in the list of things that need to be
+       pre-evaluated.
+
 2018-02-09  Nathan Sidwell  <nathan@acm.org>
 
        PR c/84293
index f8004649a35ce68b44a572bd2d4ff16bc56130d4..f0198ec81c36aaa8a3b0f589b5a7336a6b8734ca 100644 (file)
@@ -6479,28 +6479,53 @@ grokdeclarator (const struct c_declarator *declarator,
               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 attaching an
-              artificial TYPE_DECL to such pointed-to type.  This forces the
-              sizes evaluation at a safe point and ensures it is not deferred
-              until e.g. within a deeper conditional context.
-
-              We expect nothing to be needed here for PARM or TYPENAME.
-              Pushing a TYPE_DECL 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 fake TYPE_DECL in the
-              enclosing context would force the size evaluation prior to the
-              side effects.  */
-
+              We attach an artificial TYPE_DECL to such pointed-to type
+              and arrange for it to be included in a DECL_EXPR.  This
+              forces the sizes evaluation at a safe point and ensures it
+              is not deferred until e.g. within a deeper conditional context.
+
+              PARM contexts have no enclosing statement list that
+              can hold the DECL_EXPR, so we need to use a BIND_EXPR
+              instead, and add it to the list of expressions that
+              need to be evaluated.
+
+              TYPENAME contexts do have an enclosing statement list,
+              but it would be incorrect to use it, as the size should
+              only be evaluated if the containing expression is
+              evaluated.  We might also 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 fake TYPE_DECL in the enclosing context would force
+              the size evaluation prior to the side effects.  We therefore
+              use BIND_EXPRs in TYPENAME contexts too.  */
            if (!TYPE_NAME (type)
-               && (decl_context == NORMAL || decl_context == FIELD)
                && variably_modified_type_p (type, NULL_TREE))
              {
+               tree bind = NULL_TREE;
+               if (decl_context == TYPENAME || decl_context == PARM)
+                 {
+                   bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
+                                  NULL_TREE, NULL_TREE);
+                   TREE_SIDE_EFFECTS (bind) = 1;
+                   BIND_EXPR_BODY (bind) = push_stmt_list ();
+                   push_scope ();
+                 }
                tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
                DECL_ARTIFICIAL (decl) = 1;
                pushdecl (decl);
                finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
                TYPE_NAME (type) = decl;
+               if (bind)
+                 {
+                   pop_scope ();
+                   BIND_EXPR_BODY (bind)
+                     = pop_stmt_list (BIND_EXPR_BODY (bind));
+                   if (*expr)
+                     *expr = build2 (COMPOUND_EXPR, void_type_node, *expr,
+                                     bind);
+                   else
+                     *expr = bind;
+                 }
              }
 
            type = c_build_pointer_type (type);
index 878a78e299e3475868e978c10235d3a546a6c555..42bd190a87252d8a95b69688f0c4d61dd29dfcda 100644 (file)
@@ -1,3 +1,8 @@
+2018-02-13  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR c/84305
+       * gcc.c-torture/compile/pr84305.c: New test.
+
 2018-02-13  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/84335
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr84305.c b/gcc/testsuite/gcc.c-torture/compile/pr84305.c
new file mode 100644 (file)
index 0000000..374fa67
--- /dev/null
@@ -0,0 +1,4 @@
+int res, a, b;
+void *foo;
+static void f2 (int arg) { res = ((int (*)[arg][b]) foo)[0][0][0]; }
+void f1 (void) { f2 (a); }