From: Harald Anlauf <anlauf@gmx.de>
To: Mikael Morin <morin-mikael@orange.fr>, sgk@troutmask.apl.washington.edu
Cc: fortran <fortran@gcc.gnu.org>, gcc-patches <gcc-patches@gcc.gnu.org>
Subject: [PATCH, v3] Fortran: restrictions on integer arguments to SYSTEM_CLOCK [PR112609]
Date: Tue, 21 Nov 2023 22:54:50 +0100 [thread overview]
Message-ID: <06b5440b-fdab-4c02-988a-ea849aadfd48@gmx.de> (raw)
In-Reply-To: <84f48fee-a5b8-4bef-aa9b-f176d3cfbfa6@orange.fr>
[-- Attachment #1: Type: text/plain, Size: 1228 bytes --]
Hi Mikael, Steve,
On 11/21/23 12:33, Mikael Morin wrote:
> Harald, you mentioned the lack of GFC_STD_F2023_DEL feature group in
> your first message, but I don't quite understand why you didn't add one.
> It seems to me the most natural way to do this.
thanks for insisting on this variant.
In my first attack at this problem, I overlooked one place in
libgfortran.h, which I now was able to find and adjust.
Now everything falls into place.
> I suggest we emit a warning by default, error with -std=f2023 (I agree
> with Steve that we should push towards strict f2023 conformance), and no
> diagnostic with -std=gnu or -std=f2018 or lower.
As the majority agrees on this, I accept it. The attached patch
now does this and fixes the testcases accordingly.
>> It seems that the solution is to fix the code in the testsuite.
>
> Agreed, these seem to explicitly test mismatching kinds, so add an
> option to prevent error.
Done.
I also fixed a few issues in the documentation in gfortran.texi .
As I currently cannot build a full compiler (see PR112643),
patch V3 is not properly regtested yet, but appears to give
results as discussed.
Comments?
> Mikael
Thanks,
Harald
[-- Attachment #2: pr104819-v3.patch --]
[-- Type: text/x-patch, Size: 11057 bytes --]
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 6c45e6542f0..e5cf6a495b5 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -4357,6 +4357,9 @@ gfc_check_null (gfc_expr *mold)
if (mold == NULL)
return true;
+ if (mold->expr_type == EXPR_NULL)
+ return true;
+
if (!variable_check (mold, 0, true))
return false;
@@ -5189,7 +5192,7 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr)
{
*msg = NULL;
- if (expr->expr_type == EXPR_NULL)
+ if (expr->expr_type == EXPR_NULL && expr->ts.type == BT_UNKNOWN)
{
*msg = "NULL() is not interoperable";
return false;
diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index fc4fe662eab..641edf9d059 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -2387,6 +2387,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
gfc_component *ppc;
bool codimension = false;
gfc_array_spec *formal_as;
+ bool pointer_arg, allocatable_arg;
+ bool pre2018 = ((gfc_option.allow_std & GFC_STD_F2018) == 0);
/* If the formal arg has type BT_VOID, it's to one of the iso_c_binding
procs c_f_pointer or c_f_procpointer, and we need to accept most
@@ -2564,13 +2566,20 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
}
}
+ pointer_arg = gfc_expr_attr (actual).pointer;
+ allocatable_arg = gfc_expr_attr (actual).allocatable;
+
/* F08: 12.5.2.5 Allocatable and pointer dummy variables. However, this
is necessary also for F03, so retain error for both.
+ F2018:15.5.2.5 relaxes this constraint to same attributes.
NOTE: Other type/kind errors pre-empt this error. Since they are F03
compatible, no attempt has been made to channel to this one. */
if (UNLIMITED_POLY (formal) && !UNLIMITED_POLY (actual)
&& (CLASS_DATA (formal)->attr.allocatable
- ||CLASS_DATA (formal)->attr.class_pointer))
+ || CLASS_DATA (formal)->attr.class_pointer)
+ && (pre2018
+ || (allocatable_arg && CLASS_DATA (formal)->attr.allocatable)
+ || (pointer_arg && CLASS_DATA (formal)->attr.class_pointer)))
{
if (where)
gfc_error ("Actual argument to %qs at %L must be unlimited "
@@ -2710,7 +2719,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
rank_check = where != NULL && !is_elemental && formal_as
&& (formal_as->type == AS_ASSUMED_SHAPE
|| formal_as->type == AS_DEFERRED)
- && actual->expr_type != EXPR_NULL;
+ && !(actual->expr_type == EXPR_NULL
+ && actual->ts.type == BT_UNKNOWN);
/* Skip rank checks for NO_ARG_CHECK. */
if (formal->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
@@ -3184,8 +3194,10 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
gfc_array_ref *actual_arr_ref;
gfc_array_spec *fas, *aas;
bool pointer_dummy, pointer_arg, allocatable_arg;
+ bool procptr_dummy, optional_dummy, allocatable_dummy;
bool ok = true;
+ bool pre2018 = ((gfc_option.allow_std & GFC_STD_F2018) == 0);
actual = *ap;
@@ -3296,15 +3308,66 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
&& a->expr->ts.type != BT_ASSUMED)
gfc_find_vtab (&a->expr->ts);
+ /* Checks for NULL() actual arguments without MOLD. */
+ if (a->expr->expr_type == EXPR_NULL && a->expr->ts.type == BT_UNKNOWN)
+ {
+ /* Interp J3/22-146:
+ "If the context of the reference to NULL is an <actual argument>
+ corresponding to an <assumed-rank> dummy argument, MOLD shall be
+ present." */
+ fas = (f->sym->ts.type == BT_CLASS && CLASS_DATA (f->sym)
+ ? CLASS_DATA (f->sym)->as
+ : f->sym->as);
+ if (fas && fas->type == AS_ASSUMED_RANK)
+ {
+ gfc_error ("Intrinsic %<NULL()%> without %<MOLD%> argument "
+ "at %L passed to assumed-rank dummy %qs",
+ &a->expr->where, f->sym->name);
+ ok = false;
+ goto match;
+ }
+
+ /* Asummed-length dummy argument. */
+ if (f->sym->ts.type == BT_CHARACTER
+ && !f->sym->ts.deferred
+ && f->sym->ts.u.cl
+ && f->sym->ts.u.cl->length == NULL)
+ {
+ gfc_error ("Intrinsic %<NULL()%> without %<MOLD%> argument "
+ "at %L passed to assumed-length dummy %qs",
+ &a->expr->where, f->sym->name);
+ ok = false;
+ goto match;
+ }
+ }
+
+ /* Allow passing of NULL() as disassociated pointer, procedure
+ pointer, or unallocated allocatable (F2008+) to a respective dummy
+ argument. */
+ pointer_dummy = ((f->sym->ts.type != BT_CLASS
+ && f->sym->attr.pointer)
+ || (f->sym->ts.type == BT_CLASS
+ && CLASS_DATA (f->sym)->attr.class_pointer));
+
+ procptr_dummy = ((f->sym->ts.type != BT_CLASS
+ && f->sym->attr.proc_pointer)
+ || (f->sym->ts.type == BT_CLASS
+ && CLASS_DATA (f->sym)->attr.proc_pointer));
+
+ optional_dummy = f->sym->attr.optional;
+
+ allocatable_dummy = ((f->sym->ts.type != BT_CLASS
+ && f->sym->attr.allocatable)
+ || (f->sym->ts.type == BT_CLASS
+ && CLASS_DATA (f->sym)->attr.allocatable));
+
if (a->expr->expr_type == EXPR_NULL
- && ((f->sym->ts.type != BT_CLASS && !f->sym->attr.pointer
- && (f->sym->attr.allocatable || !f->sym->attr.optional
- || (gfc_option.allow_std & GFC_STD_F2008) == 0))
- || (f->sym->ts.type == BT_CLASS
- && !CLASS_DATA (f->sym)->attr.class_pointer
- && (CLASS_DATA (f->sym)->attr.allocatable
- || !f->sym->attr.optional
- || (gfc_option.allow_std & GFC_STD_F2008) == 0))))
+ && !pointer_dummy
+ && !procptr_dummy
+ && !(optional_dummy
+ && (gfc_option.allow_std & GFC_STD_F2008) != 0)
+ && !(allocatable_dummy
+ && (gfc_option.allow_std & GFC_STD_F2008) != 0))
{
if (where
&& (!f->sym->attr.optional
@@ -3409,6 +3472,9 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
if (f->sym->ts.type == BT_CLASS)
goto skip_size_check;
+ if (a->expr->expr_type == EXPR_NULL)
+ goto skip_size_check;
+
actual_size = get_expr_storage_size (a->expr);
formal_size = get_sym_storage_size (f->sym);
if (actual_size != 0 && actual_size < formal_size
@@ -3606,6 +3672,71 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
}
}
+ /* Check conditions on allocatable and pointer dummy variables:
+
+ "The actual argument shall be polymorphic if and only if the
+ associated dummy argument is polymorphic, and either both the
+ actual and dummy arguments shall be unlimited polymorphic, or the
+ declared type of the actual argument shall be the same as the
+ declared type of the dummy argument."
+
+ with a minor difference from F2008:15.5.2.5 to F2018:15.5.2.5,
+ where the latter applies only to same (ALLOCATABLE or POINTER)
+ attributes. Note that checks related to unlimited polymorphism
+ are also done in compare_parameter(). */
+ if ((pointer_dummy || allocatable_dummy)
+ && (pointer_arg || allocatable_arg)
+ && (pre2018
+ || (pointer_dummy && pointer_arg)
+ || (allocatable_dummy && allocatable_arg))
+ && (f->sym->ts.type == BT_CLASS
+ || a->expr->ts.type == BT_CLASS))
+ {
+ if (f->sym->ts.type == BT_CLASS && a->expr->ts.type != BT_CLASS
+ && pointer_dummy)
+ {
+ if (where)
+ gfc_error ("Actual argument to %qs at %L must be a "
+ "CLASS POINTER",
+ f->sym->name, &a->expr->where);
+ ok = false;
+ goto match;
+ }
+
+ if (f->sym->ts.type != BT_CLASS && a->expr->ts.type == BT_CLASS
+ && pointer_arg)
+ {
+ if (where)
+ gfc_error ("Actual argument to %qs at %L cannot be a "
+ "CLASS POINTER",
+ f->sym->name, &a->expr->where);
+ ok = false;
+ goto match;
+ }
+
+ if (f->sym->ts.type == BT_CLASS && a->expr->ts.type != BT_CLASS
+ && allocatable_dummy)
+ {
+ if (where)
+ gfc_error ("Actual argument to %qs at %L must be a "
+ "CLASS ALLOCATABLE",
+ f->sym->name, &a->expr->where);
+ ok = false;
+ goto match;
+ }
+
+ if (f->sym->ts.type != BT_CLASS && a->expr->ts.type == BT_CLASS
+ && allocatable_arg)
+ {
+ if (where)
+ gfc_error ("Actual argument to %qs at %L cannot be a "
+ "CLASS ALLOCATABLE",
+ f->sym->name, &a->expr->where);
+ ok = false;
+ goto match;
+ }
+ }
+
/* Fortran 2008, C1242. */
if (f->sym->attr.pointer && gfc_is_coindexed (a->expr))
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 50c4604a025..30b941356b6 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6288,16 +6288,37 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
&& (fsym->ts.type != BT_CLASS
|| !CLASS_DATA (fsym)->attr.class_pointer))
{
- /* Pass a NULL pointer to denote an absent arg. */
- gcc_assert (fsym->attr.optional && !fsym->attr.allocatable
- && (fsym->ts.type != BT_CLASS
- || !CLASS_DATA (fsym)->attr.allocatable));
- gfc_init_se (&parmse, NULL);
- parmse.expr = null_pointer_node;
- if (arg->associated_dummy
- && gfc_dummy_arg_get_typespec (*arg->associated_dummy).type
- == BT_CHARACTER)
- parmse.string_length = build_int_cst (gfc_charlen_type_node, 0);
+ if ((fsym->ts.type != BT_CLASS
+ && fsym->attr.allocatable)
+ || (fsym->ts.type == BT_CLASS
+ && CLASS_DATA (fsym)->attr.allocatable))
+ {
+ /* Pass descriptor equivalent to an unallocated allocatable
+ actual argument. */
+ if (e->rank != 0)
+ gfc_internal_error ("gfc_conv_procedure_call() TODO: "
+ "NULL(allocatable(rank != 0))");
+ /* Scalar version below. */
+ gfc_init_se (&parmse, NULL);
+ gfc_conv_expr_reference (&parmse, e);
+ tmp = parmse.expr;
+ if (TREE_CODE (tmp) == ADDR_EXPR)
+ tmp = TREE_OPERAND (tmp, 0);
+ parmse.expr = gfc_conv_scalar_to_descriptor (&parmse, tmp,
+ fsym->attr);
+ parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
+ }
+ else
+ {
+ /* Pass a NULL pointer to denote an absent optional arg. */
+ gcc_assert (fsym->attr.optional);
+ gfc_init_se (&parmse, NULL);
+ parmse.expr = null_pointer_node;
+ if (arg->associated_dummy
+ && gfc_dummy_arg_get_typespec (*arg->associated_dummy).type
+ == BT_CHARACTER)
+ parmse.string_length = build_int_cst (gfc_charlen_type_node, 0);
+ }
}
else if (fsym && fsym->ts.type == BT_CLASS
&& e->ts.type == BT_DERIVED)
@@ -6852,7 +6873,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
we can assign it to the data field. */
if (fsym && fsym->as && fsym->as->type == AS_ASSUMED_RANK
- && fsym->ts.type != BT_CLASS && e->expr_type != EXPR_NULL)
+ && fsym->ts.type != BT_CLASS
+ && !(e->expr_type == EXPR_NULL
+ && e->ts.type == BT_UNKNOWN))
{
tmp = parmse.expr;
if (TREE_CODE (tmp) == ADDR_EXPR)
next prev parent reply other threads:[~2023-11-21 21:54 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-18 22:12 [PATCH] " Harald Anlauf
2023-11-19 0:04 ` Steve Kargl
2023-11-19 20:46 ` [PATCH, v2] " Harald Anlauf
2023-11-20 19:02 ` Steve Kargl
2023-11-21 11:33 ` Mikael Morin
2023-11-21 21:54 ` Harald Anlauf [this message]
2023-11-21 22:09 ` [PATCH, v3] " Harald Anlauf
2023-11-22 9:36 ` Mikael Morin
2023-11-22 18:03 ` Steve Kargl
2023-11-22 20:40 ` Harald Anlauf
2023-11-22 20:40 ` Harald Anlauf
2023-11-22 20:36 ` [PATCH, v4] " Harald Anlauf
2023-11-23 9:07 ` Mikael Morin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=06b5440b-fdab-4c02-988a-ea849aadfd48@gmx.de \
--to=anlauf@gmx.de \
--cc=fortran@gcc.gnu.org \
--cc=gcc-patches@gcc.gnu.org \
--cc=morin-mikael@orange.fr \
--cc=sgk@troutmask.apl.washington.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).