https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30372

--- Comment #13 from kargl at gcc dot gnu.org ---
This patch makes the UMASK subroutine a generic subprogram.  This is
accomplished by converting its arguments to INTEGER(4), call
_gfortran_umask_i4_sub, and converting the OLD argument back to an appropriate
integer kind.  Don't know if it works with -fdefault-real-8, but who cares. 
That option should be removed from gfortran.

Index: gcc/fortran/check.c
===================================================================
--- gcc/fortran/check.c (revision 280157)
+++ gcc/fortran/check.c (working copy)
@@ -7236,6 +7236,14 @@ gfc_check_umask_sub (gfc_expr *mask, gfc_expr *old)
   if (!type_check (old, 1, BT_INTEGER))
     return false;

+  if (old->expr_type != EXPR_VARIABLE
+      || (old->symtree && old->symtree->n.sym
+         && old->symtree->n.sym->attr.intent == INTENT_IN))
+    {
+      gfc_error ("OLD at %L shall be an INTENT(OUT) variable", &old->where);
+      return false;
+    }
+
   return true;
 }

Index: gcc/fortran/intrinsic.texi
===================================================================
--- gcc/fortran/intrinsic.texi  (revision 280157)
+++ gcc/fortran/intrinsic.texi  (working copy)
@@ -14795,9 +14795,10 @@ corresponding to the lower cobound of the array along 

 @table @asis
 @item @emph{Description}:
-Sets the file creation mask to @var{MASK}. If called as a function, it
-returns the old value. If called as a subroutine and argument @var{OLD}
-if it is supplied, it is set to the old value. See @code{umask(2)}.
+Sets the file creation mask to @var{MASK}.
+If called as a function, it returns the old value.
+If called as a subroutine, and @var{OLD} is present, 
+it sets @var{OLD} to the previous value.

 @item @emph{Standard}:
 GNU extension
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c    (revision 280157)
+++ gcc/fortran/trans-decl.c    (working copy)
@@ -212,12 +212,13 @@ tree gfor_fndecl_convert_char4_to_char1;


 /* Other misc. runtime library functions.  */
-tree gfor_fndecl_size0;
-tree gfor_fndecl_size1;
 tree gfor_fndecl_iargc;
+tree gfor_fndecl_is_contiguous0;
 tree gfor_fndecl_kill;
 tree gfor_fndecl_kill_sub;
-tree gfor_fndecl_is_contiguous0;
+tree gfor_fndecl_size0;
+tree gfor_fndecl_size1;
+tree gfor_fndecl_umask_sub;


 /* Intrinsic functions implemented in Fortran.  */
@@ -3635,6 +3636,10 @@ gfc_build_intrinsic_function_decls (void)
   gfor_fndecl_iargc = gfc_build_library_function_decl (
        get_identifier (PREFIX ("iargc")), gfc_int4_type_node, 0);
   TREE_NOTHROW (gfor_fndecl_iargc) = 1;
+
+  gfor_fndecl_umask_sub = gfc_build_library_function_decl (
+       get_identifier (PREFIX ("umask_i4_sub")), void_type_node,
+       2, gfc_pint4_type_node, gfc_pint4_type_node);

   gfor_fndecl_kill_sub = gfc_build_library_function_decl (
        get_identifier (PREFIX ("kill_sub")), void_type_node,
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c       (revision 280157)
+++ gcc/fortran/trans-intrinsic.c       (working copy)
@@ -9138,7 +9138,51 @@ conv_intrinsic_kill_sub (gfc_code *code)
 }


+/* Translate a call to the UMASK subroutine.  */

+static tree
+conv_intrinsic_umask_sub (gfc_code *code)
+{
+  stmtblock_t block;
+  gfc_se se, se_old;
+  tree int4_type_node = gfc_get_int_type (4);
+  tree mask;
+  tree oldp = NULL_TREE;
+  tree tmp;
+
+  /* Make the function call.  */
+  gfc_init_block (&block);
+  gfc_init_se (&se, NULL);
+
+  /* Convert mask to an INTEGER(4) entity.  */
+  gfc_conv_expr (&se, code->ext.actual->expr);
+  gfc_add_block_to_block (&block, &se.pre);
+  mask = fold_convert (int4_type_node, gfc_evaluate_now (se.expr, &block));
+  gfc_add_block_to_block (&block, &se.post);
+
+  /* Deal with an optional OLD.  */
+  if (code->ext.actual->next->expr)
+    {
+      gfc_init_se (&se_old, NULL);
+      gfc_conv_expr (&se_old, code->ext.actual->next->expr);
+      oldp = gfc_create_var (int4_type_node, "_oldp");
+    }
+
+  tmp = build_call_expr_loc (input_location, gfor_fndecl_umask_sub, 2,
+                            gfc_build_addr_expr (NULL_TREE, mask),
+                            oldp ? gfc_build_addr_expr (NULL_TREE, oldp)
+                               : null_pointer_node);
+
+  gfc_add_expr_to_block (&block, tmp);
+
+  if (oldp && oldp != se_old.expr)
+    gfc_add_modify (&block, se_old.expr,
+                   fold_convert (TREE_TYPE (se_old.expr), oldp));
+
+  return gfc_finish_block (&block);
+}
+
+
 /* The loc intrinsic returns the address of its argument as
    gfc_index_integer_kind integer.  */

@@ -11899,6 +11943,10 @@ gfc_conv_intrinsic_subroutine (gfc_code *code)

     case GFC_ISYM_KILL:
       res = conv_intrinsic_kill_sub (code);
+      break;
+
+    case GFC_ISYM_UMASK:
+      res = conv_intrinsic_umask_sub (code);
       break;

     case GFC_ISYM_SYSTEM_CLOCK:
Index: gcc/fortran/trans.h
===================================================================
--- gcc/fortran/trans.h (revision 280157)
+++ gcc/fortran/trans.h (working copy)
@@ -939,12 +939,13 @@ extern GTY(()) tree gfor_fndecl_convert_char1_to_char4
 extern GTY(()) tree gfor_fndecl_convert_char4_to_char1;

 /* Other misc. runtime library functions.  */
-extern GTY(()) tree gfor_fndecl_size0;
-extern GTY(()) tree gfor_fndecl_size1;
 extern GTY(()) tree gfor_fndecl_iargc;
+extern GTY(()) tree gfor_fndecl_is_contiguous0;
 extern GTY(()) tree gfor_fndecl_kill;
 extern GTY(()) tree gfor_fndecl_kill_sub;
-extern GTY(()) tree gfor_fndecl_is_contiguous0;
+extern GTY(()) tree gfor_fndecl_size0;
+extern GTY(()) tree gfor_fndecl_size1;
+extern GTY(()) tree gfor_fndecl_umask_sub;

 /* Implemented in Fortran.  */
 extern GTY(()) tree gfor_fndecl_sc_kind;

Reply via email to