diff options
author | Harald Anlauf <anlauf@gmx.de> | 2025-02-15 20:36:15 +0100 |
---|---|---|
committer | Harald Anlauf <anlauf@gmx.de> | 2025-02-15 20:36:15 +0100 |
commit | 8859dce9037bcb242819305f02e16edbea38923c (patch) | |
tree | fe2989610ecc4b1735d46170d90f945997fda4d2 /gcc/fortran | |
parent | 12771b1d77aef71f9eceead9b46323292f3dd7e4 (diff) | |
download | gcc-8859dce9037bcb242819305f02e16edbea38923c.zip gcc-8859dce9037bcb242819305f02e16edbea38923c.tar.gz gcc-8859dce9037bcb242819305f02e16edbea38923c.tar.bz2 |
Fortran: passing of derived type to VALUE,OPTIONAL dummy argument [PR118080]
For scalar OPTIONAL dummy arguments with the VALUE attribute, gfortran
passes a hidden flag to denote presence or absence of the actual argument
for intrinsic types. Extend this treatment to derived type (user-defined
as well as from intrinsic module ISO_C_BINDING).
PR fortran/118080
gcc/fortran/ChangeLog:
* gfortran.texi: Adjust documentation.
* trans-decl.cc (create_function_arglist): Adjust to pass hidden
presence flag also for derived type dummies with VALUE,OPTIONAL
attribute.
* trans-expr.cc (gfc_conv_expr_present): Expect hidden presence
flag also for derived type dummies with VALUE,OPTIONAL attribute.
(conv_cond_temp): Adjust to allow derived types.
(conv_dummy_value): Extend to handle derived type dummies with
VALUE,OPTIONAL attribute.
(gfc_conv_procedure_call): Adjust for actual arguments passed to
derived type dummies with VALUE,OPTIONAL attribute.
* trans-types.cc (gfc_get_function_type): Adjust fndecl for
hidden presence flag.
gcc/testsuite/ChangeLog:
* gfortran.dg/value_optional_2.f90: New test.
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/gfortran.texi | 1 | ||||
-rw-r--r-- | gcc/fortran/trans-decl.cc | 8 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.cc | 39 | ||||
-rw-r--r-- | gcc/fortran/trans-types.cc | 5 |
4 files changed, 30 insertions, 23 deletions
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index ab8a4cb..fa7f563 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -3960,6 +3960,7 @@ passed by value. For @code{OPTIONAL} dummy arguments, an absent argument is denoted by a NULL pointer, except for scalar dummy arguments of intrinsic type +or derived type (but not @code{CLASS}) and that have the @code{VALUE} attribute. For those, a hidden Boolean argument (@code{logical(kind=C_bool),value}) is used to indicate whether the argument is present. diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 83f8130..0acf0e9 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -2775,8 +2775,7 @@ create_function_arglist (gfc_symbol * sym) for (f = gfc_sym_get_dummy_args (sym); f; f = f->next) if (f->sym != NULL && f->sym->attr.optional && f->sym->attr.value - && !f->sym->attr.dimension && f->sym->ts.type != BT_CLASS - && !gfc_bt_struct (f->sym->ts.type)) + && !f->sym->attr.dimension && f->sym->ts.type != BT_CLASS) hidden_typelist = TREE_CHAIN (hidden_typelist); for (f = gfc_sym_get_dummy_args (sym); f; f = f->next) @@ -2858,12 +2857,11 @@ create_function_arglist (gfc_symbol * sym) type = gfc_sym_type (f->sym); } } - /* For scalar intrinsic types, VALUE passes the value, + /* For scalar intrinsic types or derived types, VALUE passes the value, hence, the optional status cannot be transferred via a NULL pointer. Thus, we will use a hidden argument in that case. */ if (f->sym->attr.optional && f->sym->attr.value - && !f->sym->attr.dimension && f->sym->ts.type != BT_CLASS - && !gfc_bt_struct (f->sym->ts.type)) + && !f->sym->attr.dimension && f->sym->ts.type != BT_CLASS) { tree tmp; strcpy (&name[1], f->sym->name); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 1329efc..9d29fe7 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -2132,10 +2132,9 @@ gfc_conv_expr_present (gfc_symbol * sym, bool use_saved_desc) gcc_assert (sym->attr.dummy); orig_decl = decl = gfc_get_symbol_decl (sym); - /* Intrinsic scalars with VALUE attribute which are passed by value - use a hidden argument to denote the present status. */ - if (sym->attr.value && !sym->attr.dimension - && sym->ts.type != BT_CLASS && !gfc_bt_struct (sym->ts.type)) + /* Intrinsic scalars and derived types with VALUE attribute which are passed + by value use a hidden argument to denote the presence status. */ + if (sym->attr.value && !sym->attr.dimension && sym->ts.type != BT_CLASS) { char name[GFC_MAX_SYMBOL_LEN + 2]; tree tree_name; @@ -6458,13 +6457,13 @@ post_call: /* Create "conditional temporary" to handle scalar dummy variables with the OPTIONAL+VALUE attribute that shall not be dereferenced. Use null value - as fallback. Only instances of intrinsic basic type are supported. */ + as fallback. Does not handle CLASS. */ static void conv_cond_temp (gfc_se * parmse, gfc_expr * e, tree cond) { tree temp; - gcc_assert (e->ts.type != BT_DERIVED && e->ts.type != BT_CLASS); + gcc_assert (e && e->ts.type != BT_CLASS); gcc_assert (e->rank == 0); temp = gfc_create_var (TREE_TYPE (parmse->expr), "condtemp"); TREE_STATIC (temp) = 1; @@ -6500,6 +6499,17 @@ conv_dummy_value (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym, parmse->expr = null_pointer_node; parmse->string_length = build_int_cst (gfc_charlen_type_node, 0); } + else if (gfc_bt_struct (fsym->ts.type) + && !(fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING)) + { + /* Pass null struct. Types c_ptr and c_funptr from ISO_C_BINDING + are pointers and passed as such below. */ + tree temp = gfc_create_var (gfc_sym_type (fsym), "absent"); + TREE_CONSTANT (temp) = 1; + TREE_READONLY (temp) = 1; + DECL_INITIAL (temp) = build_zero_cst (TREE_TYPE (temp)); + parmse->expr = temp; + } else parmse->expr = fold_convert (gfc_sym_type (fsym), integer_zero_node); @@ -6529,9 +6539,7 @@ conv_dummy_value (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym, parmse->string_length = slen1; } - if (fsym->attr.optional - && fsym->ts.type != BT_CLASS - && fsym->ts.type != BT_DERIVED) + if (fsym->attr.optional && fsym->ts.type != BT_CLASS) { /* F2018:15.5.2.12 Argument presence and restrictions on arguments not present. */ @@ -6561,7 +6569,10 @@ conv_dummy_value (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym, else { tmp = gfc_conv_expr_present (e->symtree->n.sym); - if (e->ts.type != BT_CHARACTER && !e->symtree->n.sym->attr.value) + if (gfc_bt_struct (fsym->ts.type) + && !(fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING)) + conv_cond_temp (parmse, e, tmp); + else if (e->ts.type != BT_CHARACTER && !e->symtree->n.sym->attr.value) parmse->expr = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (parmse->expr), @@ -6881,7 +6892,6 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, && fsym->attr.value && fsym->attr.optional && !fsym->attr.dimension - && fsym->ts.type != BT_DERIVED && fsym->ts.type != BT_CLASS)) { if (se->ignore_optional) @@ -6903,8 +6913,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, value, pass "0" and a hidden argument gives the optional status. */ if (fsym && fsym->attr.optional && fsym->attr.value - && !fsym->attr.dimension && fsym->ts.type != BT_CLASS - && !gfc_bt_struct (sym->ts.type)) + && !fsym->attr.dimension && fsym->ts.type != BT_CLASS) { conv_dummy_value (&parmse, e, fsym, optionalargs); } @@ -7016,10 +7025,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, } } - /* Scalar dummy arguments of intrinsic type with VALUE attribute. */ + /* Scalar dummy arguments of intrinsic type or derived type with + VALUE attribute. */ if (fsym && fsym->attr.value - && fsym->ts.type != BT_DERIVED && fsym->ts.type != BT_CLASS) conv_dummy_value (&parmse, e, fsym, optionalargs); diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index 5ad0fe6..0411400 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -3475,15 +3475,14 @@ gfc_get_function_type (gfc_symbol * sym, gfc_actual_arglist *actual_args, vec_safe_push (hidden_typelist, type); } - /* For scalar intrinsic types, VALUE passes the value, + /* For scalar intrinsic types or derived types, VALUE passes the value, hence, the optional status cannot be transferred via a NULL pointer. Thus, we will use a hidden argument in that case. */ if (arg && arg->attr.optional && arg->attr.value && !arg->attr.dimension - && arg->ts.type != BT_CLASS - && !gfc_bt_struct (arg->ts.type)) + && arg->ts.type != BT_CLASS) vec_safe_push (typelist, boolean_type_node); /* Coarrays which are descriptorless or assumed-shape pass with -fcoarray=lib the token and the offset as hidden arguments. */ |