Hello world,

the attached patch fixes the regression by making sure we never
try to create a temporary variable from a temporary variable,
which happened in the wrong order.

Regression-tested.  OK for trunk and 4.9?

2014-08-19  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR fortran/62106
        * gfortran.h (symbol_attribute):  Add fe_temp flag.
        * frontend-passes.c (is_fe_temp):  New function.
        (create_var):  Don't add a temporary for an already
        created variable or for a constant.
        (combine_ARRAY_constructor):  Remove special handling
        for constants.

2014-08-19  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR fortran/62106
        * gfortran.dg/array_constructor_49.f90:  New test.
Index: frontend-passes.c
===================================================================
--- frontend-passes.c	(Revision 213778)
+++ frontend-passes.c	(Arbeitskopie)
@@ -430,11 +430,26 @@ cfe_register_funcs (gfc_expr **e, int *walk_subtre
   return 0;
 }
 
+/* Auxiliary function to check if an expression is a temporary created by
+   create var.  */
+
+static bool
+is_fe_temp (gfc_expr *e)
+{
+  if (e->expr_type != EXPR_VARIABLE)
+    return false;
+
+  return e->symtree->n.sym->attr.fe_temp;
+}
+
+
 /* Returns a new expression (a variable) to be used in place of the old one,
    with an assignment statement before the current statement to set
    the value of the variable. Creates a new BLOCK for the statement if
    that hasn't already been done and puts the statement, plus the
-   newly created variables, in that block.  */
+   newly created variables, in that block.  Special cases:  If the
+   expression is constant or a temporary which has already
+   been created, just copy it.  */
 
 static gfc_expr*
 create_var (gfc_expr * e)
@@ -448,6 +463,9 @@ create_var (gfc_expr * e)
   gfc_namespace *ns;
   int i;
 
+  if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
+    return gfc_copy_expr (e);
+
   /* If the block hasn't already been created, do so.  */
   if (inserted_block == NULL)
     {
@@ -522,6 +540,7 @@ create_var (gfc_expr * e)
   symbol->attr.flavor = FL_VARIABLE;
   symbol->attr.referenced = 1;
   symbol->attr.dimension = e->rank > 0;
+  symbol->attr.fe_temp = 1;
   gfc_commit_symbol (symbol);
 
   result = gfc_get_expr ();
@@ -1082,10 +1101,7 @@ combine_array_constructor (gfc_expr *e)
   if (op2->ts.type == BT_CHARACTER)
     return false;
 
-  if (op2->expr_type == EXPR_CONSTANT)
-    scalar = gfc_copy_expr (op2);
-  else
-    scalar = create_var (gfc_copy_expr (op2));
+  scalar = create_var (gfc_copy_expr (op2));
 
   oldbase = op1->value.constructor;
   newbase = NULL;
Index: gfortran.h
===================================================================
--- gfortran.h	(Revision 213778)
+++ gfortran.h	(Arbeitskopie)
@@ -739,7 +739,7 @@ typedef struct
     optional:1, pointer:1, target:1, value:1, volatile_:1, temporary:1,
     dummy:1, result:1, assign:1, threadprivate:1, not_always_present:1,
     implied_index:1, subref_array_pointer:1, proc_pointer:1, asynchronous:1,
-    contiguous:1;
+    contiguous:1, fe_temp: 1;
 
   /* For CLASS containers, the pointer attribute is sometimes set internally
      even though it was not directly specified.  In this case, keep the
! { dg-do run }
! { dg-options "-ffrontend-optimize -fdump-tree-original" }
! PR 62106 - this used to give wrong results because
! of a bogus extra temporary variable.
! Original test case by Martien Hulsen
program t
  integer :: ndim=2, ndfp=4, i
  character (len=8) :: line
  write (unit=line,fmt='(4I2)'), (/ ( i, i = 1, ndfp ) /) + ndim
  if (line /= ' 3 4 5 6') call abort
end program t
! { dg-final { scan-tree-dump-times "__var" 3 "original" } }
! { dg-final { cleanup-tree-dump "original" } }

Reply via email to