aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorHarald Anlauf <anlauf@gmx.de>2025-02-15 20:36:15 +0100
committerHarald Anlauf <anlauf@gmx.de>2025-02-15 20:36:15 +0100
commit8859dce9037bcb242819305f02e16edbea38923c (patch)
treefe2989610ecc4b1735d46170d90f945997fda4d2 /gcc/fortran
parent12771b1d77aef71f9eceead9b46323292f3dd7e4 (diff)
downloadgcc-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.texi1
-rw-r--r--gcc/fortran/trans-decl.cc8
-rw-r--r--gcc/fortran/trans-expr.cc39
-rw-r--r--gcc/fortran/trans-types.cc5
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. */