[PATCH] Fortran: update DATE_AND_TIME intrinsic for Fortran 2018 [PR96580]

2023-12-18 Thread Harald Anlauf
Dear all,

starting with Fortran 2018, DATE_AND_TIME allowed a non-default
integer VALUES argument.

While gfortran accepts this silently, this failed at runtime
because the library implementation beyond kind=4 and kind=8
was missing.

Futhermore, the standard effectively requires that the integer
kind is at least 2.  The attached patch adds several checks,
plus adds checking for the array size to be sufficient, extends
the implementation to the remaining kinds, and corrects several
issues in the related documentation.

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

Thanks,
Harald

From 1850bb6cbae7229e2c26e66a0a621817339f85e9 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Mon, 18 Dec 2023 18:59:02 +0100
Subject: [PATCH] Fortran: update DATE_AND_TIME intrinsic for Fortran 2018
 [PR96580]

Fortran 2018 allows a non-default integer kind for its VALUES argument if
it has a decimal exponent range of at least four.  Update checks, library
implementation and documentation.

gcc/fortran/ChangeLog:

	PR fortran/96580
	* check.cc (array_size_check): New helper function.
	(gfc_check_date_and_time): Use it for checking minimum size of
	VALUES argument.  Update kind check to Fortran 2018.
	* intrinsic.texi: Fix documentation of DATE_AND_TIME.

libgfortran/ChangeLog:

	PR fortran/96580
	* intrinsics/date_and_time.c (date_and_time): Handle VALUES argument
	for kind=2 and kind=16 (if available).

gcc/testsuite/ChangeLog:

	PR fortran/96580
	* gfortran.dg/date_and_time_2.f90: New test.
	* gfortran.dg/date_and_time_3.f90: New test.
	* gfortran.dg/date_and_time_4.f90: New test.
---
 gcc/fortran/check.cc  | 48 +++
 gcc/fortran/intrinsic.texi| 39 +++
 gcc/testsuite/gfortran.dg/date_and_time_2.f90 | 21 
 gcc/testsuite/gfortran.dg/date_and_time_3.f90 | 29 +++
 gcc/testsuite/gfortran.dg/date_and_time_4.f90 | 30 
 libgfortran/intrinsics/date_and_time.c| 32 +++--
 6 files changed, 177 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/date_and_time_2.f90
 create mode 100644 gcc/testsuite/gfortran.dg/date_and_time_3.f90
 create mode 100644 gcc/testsuite/gfortran.dg/date_and_time_4.f90

diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 3b1a0f9f4f4..b91a743be42 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -1251,6 +1251,33 @@ gfc_check_same_strlen (const gfc_expr *a, const gfc_expr *b, const char *name)
  }
 }

+/* Check size of an array argument against a required size.
+   Returns true if the requirement is satisfied or if the size cannot be
+   determined, otherwise return false and raise a gfc_error  */
+
+static bool
+array_size_check (gfc_expr *a, int n, long size_min)
+{
+  bool ok = true;
+  mpz_t size;
+
+  if (gfc_array_size (a, &size))
+{
+  HOST_WIDE_INT sz = gfc_mpz_get_hwi (size);
+  if (size_min >= 0 && sz < size_min)
+	{
+	  gfc_error ("Size of %qs argument of %qs intrinsic at %L "
+		 "too small (%wd/%ld)",
+		 gfc_current_intrinsic_arg[n]->name,
+		 gfc_current_intrinsic, &a->where, sz, size_min);
+	  ok = false;
+	}
+  mpz_clear (size);
+}
+
+  return ok;
+}
+

 /* Check functions */

@@ -6539,6 +6566,27 @@ gfc_check_date_and_time (gfc_expr *date, gfc_expr *time,
 	return false;
   if (!variable_check (values, 3, false))
 	return false;
+  if (!array_size_check (values, 3, 8))
+	return false;
+
+  if (values->ts.kind != gfc_default_integer_kind
+	  && !gfc_notify_std (GFC_STD_F2018, "VALUES argument of "
+			  "DATE_AND_TIME at %L has non-default kind",
+			  &values->where))
+	return false;
+
+  /* F2018:16.9.59 DATE_AND_TIME
+	 "VALUES shall be a rank-one array of type integer
+	 with a decimal exponent range of at least four."
+	 This is a hard limit also required by the implementation in
+	 libgfortran.  */
+  if (values->ts.kind < 2)
+	{
+	  gfc_error ("VALUES argument of DATE_AND_TIME at %L must have "
+		 "a decimal exponent range of at least four",
+		 &values->where);
+	  return false;
+	}
 }

   return true;
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index d4dd47fef0f..2c37cf4286a 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -4729,22 +4729,22 @@ end program test_ctime
 @item @emph{Description}:
 @code{DATE_AND_TIME(DATE, TIME, ZONE, VALUES)} gets the corresponding date and
 time information from the real-time system clock.  @var{DATE} is
-@code{INTENT(OUT)} and has form ccyymmdd.  @var{TIME} is @code{INTENT(OUT)} and
-has form hhmmss.sss.  @var{ZONE} is @code{INTENT(OUT)} and has form (+-)hhmm,
-representing the difference with respect to Coordinated Universal Time (UTC).
-Unavailable time and date parameters return blanks.
+@code{INTENT(OUT)} and of the form ccyymmdd.  @var{TIME} is @code{INTENT(OUT)}
+and of the form hhmmss.sss.  @var{ZONE} is @code{INTENT(OUT)} and of the form
+(+-)h

Re: [PATCH] Fortran: update DATE_AND_TIME intrinsic for Fortran 2018 [PR96580]

2023-12-18 Thread Steve Kargl
On Mon, Dec 18, 2023 at 07:11:59PM +0100, Harald Anlauf wrote:
> Dear all,
> 
> starting with Fortran 2018, DATE_AND_TIME allowed a non-default
> integer VALUES argument.
> 
> While gfortran accepts this silently, this failed at runtime
> because the library implementation beyond kind=4 and kind=8
> was missing.
> 
> Futhermore, the standard effectively requires that the integer
> kind is at least 2.  The attached patch adds several checks,
> plus adds checking for the array size to be sufficient, extends
> the implementation to the remaining kinds, and corrects several
> issues in the related documentation.
> 
> Regtested on x86_64-pc-linux-gnu.  OK for mainline?
> 

Yes.  Thanks for the patch.

-- 
Steve