OSDN Git Service

PR fortran/50981
authormikael <mikael@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Jan 2012 14:04:24 +0000 (14:04 +0000)
committermikael <mikael@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Jan 2012 14:04:24 +0000 (14:04 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182874 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 86de8bd..3f6c5dc 100644 (file)
@@ -1,5 +1,14 @@
 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...
        (gfc_conv_expr_reference): ... here.
 
index 50e1ee4..a9a060d 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 12d382d..54572fb 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 259a08a..61a4817 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;