Hi!

The following (invalid) testcase ICEs, because we try to store into
CONST_DECL's FIELD.  Normally in GIMPLE we have MEM_REF[&C.1234] and
writes to that expand gracefully into a MEM, but as soon as we use
get_inner_reference in expand_assignment (even if the MEM is just reverse
order, or we just want to store to a part of it etc.), get_inner_reference
looks through even that MEM_REF.  Instead of hacking that around in
expand_assignment, just attempting to handle EXPAND_WRITE into CONST_DECL
looked easier to me.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-10-14  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/77959
        * expr.c (expand_expr_real_1) <case CONST_DECL>: For EXPAND_WRITE
        return a MEM.

        * gfortran.dg/pr77959.f90: New test.

--- gcc/expr.c.jj       2016-10-09 13:19:09.000000000 +0200
+++ gcc/expr.c  2016-10-13 11:49:36.386993921 +0200
@@ -9914,6 +9914,19 @@ expand_expr_real_1 (tree exp, rtx target
       }
 
     case CONST_DECL:
+      if (modifier == EXPAND_WRITE)
+       {
+         /* Writing into CONST_DECL is always invalid, but handle it
+            gracefully.  */
+         addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
+         machine_mode address_mode = targetm.addr_space.address_mode (as);
+         op0 = expand_expr_addr_expr_1 (exp, NULL_RTX, address_mode,
+                                        EXPAND_NORMAL, as);
+         op0 = memory_address_addr_space (mode, op0, as);
+         temp = gen_rtx_MEM (mode, op0);
+         set_mem_addr_space (temp, as);
+         return temp;
+       }
       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
 
     case REAL_CST:
--- gcc/testsuite/gfortran.dg/pr77959.f90.jj    2016-10-13 11:57:30.019992471 
+0200
+++ gcc/testsuite/gfortran.dg/pr77959.f90       2016-10-13 11:58:50.719969914 
+0200
@@ -0,0 +1,16 @@
+! PR middle-end/77959
+! { dg-do compile }
+! { dg-options "-O2" }
+
+program pr77959
+  interface
+    subroutine foo(x)  ! { dg-warning "Type mismatch in argument" }
+      real :: x
+    end
+  end interface
+  call foo(1.0)
+end
+subroutine foo(x)
+  complex :: x
+  x = x + 1
+end

        Jakub

Reply via email to