re PR fortran/50981 ([OOP] Wrong-code for scalarizing ELEMENTAL call with absent...
authorMikael Morin <mikael@gcc.gnu.org>
Wed, 4 Jan 2012 14:04:24 +0000 (14:04 +0000)
committerMikael Morin <mikael@gcc.gnu.org>
Wed, 4 Jan 2012 14:04:24 +0000 (14:04 +0000)
PR fortran/50981
* trans.h (struct gfc_ss_info): New field data::scalar::can_be_null_ref
* trans-array.c: If the reference can be NULL, save the reference
instead of the value.
* trans-expr.c (gfc_conv_expr): If we have saved a reference,
dereference it.

From-SVN: r182874

gcc/fortran/ChangeLog
gcc/fortran/trans-array.c
gcc/fortran/trans-expr.c
gcc/fortran/trans.h

index 86de8bdac6eb9c7538488fd9daa4ed285211c03f..3f6c5dcebd7ad7ac544faebe5d46818003f0d4ec 100644 (file)
@@ -1,3 +1,12 @@
+2012-01-04  Mikael Morin  <mikael@gcc.gnu.org>
+
+       PR fortran/50981
+       * trans.h (struct gfc_ss_info): New field data::scalar::can_be_null_ref
+       * trans-array.c: If the reference can be NULL, save the reference
+       instead of the value.
+       * trans-expr.c (gfc_conv_expr): If we have saved a reference,
+       dereference it.
+
 2012-01-04  Mikael Morin  <mikael@gcc.gnu.org>
 
        * trans-expr.c (gfc_conv_expr): Move address taking...
index 50e1ee422f90dedc77822000f72fae2846ad87f4..a9a060d820601002181e1cd105bec518be470136 100644 (file)
@@ -2422,10 +2422,21 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
          break;
 
        case GFC_SS_REFERENCE:
-         /* Scalar argument to elemental procedure.  Evaluate this
-            now.  */
+         /* Scalar argument to elemental procedure.  */
          gfc_init_se (&se, NULL);
-         gfc_conv_expr (&se, expr);
+         if (ss_info->data.scalar.can_be_null_ref)
+           {
+             /* If the actual argument can be absent (in other words, it can
+                be a NULL reference), don't try to evaluate it; pass instead
+                the reference directly.  */
+             gfc_conv_expr_reference (&se, expr);
+           }
+         else
+           {
+             /* Otherwise, evaluate the argument outside the loop and pass
+                a reference to the value.  */
+             gfc_conv_expr (&se, expr);
+           }
          gfc_add_block_to_block (&outer_loop->pre, &se.pre);
          gfc_add_block_to_block (&outer_loop->post, &se.post);
          if (gfc_is_class_scalar_expr (expr))
index 12d382de2f6b7bce54c43eb51a45246c858d37d6..54572fbf3dbb174ae75665d9ea1f516abdb6b254 100644 (file)
@@ -5331,6 +5331,11 @@ gfc_conv_expr (gfc_se * se, gfc_expr * expr)
       /* Substitute a scalar expression evaluated outside the scalarization
          loop.  */
       se->expr = ss_info->data.scalar.value;
+      /* If the reference can be NULL, the value field contains the reference,
+        not the value the reference points to (see gfc_add_loop_ss_code).  */
+      if (ss_info->data.scalar.can_be_null_ref)
+       se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
+
       se->string_length = ss_info->string_length;
       gfc_advance_se_ss_chain (se);
       return;
index 259a08aae069f5bac26aecd8c9e7d6be16549cae..61a48172e5c7b057be7ee61760c702263636516a 100644 (file)
@@ -145,8 +145,9 @@ typedef enum
   GFC_SS_SCALAR,
 
   /* Like GFC_SS_SCALAR it evaluates the expression outside the
-     loop. Is always evaluated as a reference to the temporary.
-     Used for elemental function arguments.  */
+     loop.  Is always evaluated as a reference to the temporary, unless
+     temporary evaluation can result in a NULL pointer dereferencing (case of
+     optional arguments).  Used for elemental function arguments.  */
   GFC_SS_REFERENCE,
 
   /* An array section.  Scalarization indices will be substituted during
@@ -196,6 +197,9 @@ typedef struct gfc_ss_info
     struct
     {
       tree value;
+      /* Tells whether the reference can be null in the GFC_SS_REFERENCE case.
+        Used to handle elemental procedures' optional arguments.  */
+      bool can_be_null_ref;
     }
     scalar;