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;