Re: [PATCH] Fortran: improve bounds checking for DATA with implied-do [PR35095]

2023-08-24 Thread Jerry D via Fortran

On 8/24/23 2:28 PM, Harald Anlauf via Fortran wrote:

Dear all,

the attached patch adds stricter bounds-checking for DATA statements
with implied-do.  I chose to allow overindexing (for arrays of rank
greater than 1) for -std=legacy, as there might be codes in the wild
that need this (and this is accepted by some other compilers, while
NAG is strict here).  We now get a warning with -std=gnu, and an
error with -std=f.

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

(The PR is over 15 years old, so no backport intended... ;-)

Thanks,
Harald



Looks good Harold, OK for mainline.


[PATCH] Fortran: improve bounds checking for DATA with implied-do [PR35095]

2023-08-24 Thread Harald Anlauf via Fortran
Dear all,

the attached patch adds stricter bounds-checking for DATA statements
with implied-do.  I chose to allow overindexing (for arrays of rank
greater than 1) for -std=legacy, as there might be codes in the wild
that need this (and this is accepted by some other compilers, while
NAG is strict here).  We now get a warning with -std=gnu, and an
error with -std=f.

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

(The PR is over 15 years old, so no backport intended... ;-)

Thanks,
Harald

From 420804e7399dbc307a80f084cfb840444b8ebfe7 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Thu, 24 Aug 2023 23:16:25 +0200
Subject: [PATCH] Fortran: improve bounds checking for DATA with implied-do
 [PR35095]

gcc/fortran/ChangeLog:

	PR fortran/35095
	* data.cc (get_array_index): Add bounds-checking code and return error
	status.  Overindexing will be allowed as an extension for -std=legacy
	and generate an error in standard-conforming mode.
	(gfc_assign_data_value): Use error status from get_array_index for
	graceful error recovery.

gcc/testsuite/ChangeLog:

	PR fortran/35095
	* gfortran.dg/data_bounds_1.f90: Adjust options to disable warnings.
	* gfortran.dg/data_bounds_2.f90: New test.
---
 gcc/fortran/data.cc | 47 ++---
 gcc/testsuite/gfortran.dg/data_bounds_1.f90 |  2 +-
 gcc/testsuite/gfortran.dg/data_bounds_2.f90 |  9 
 3 files changed, 51 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/data_bounds_2.f90

diff --git a/gcc/fortran/data.cc b/gcc/fortran/data.cc
index 7c2537dd3f0..0589fc3906f 100644
--- a/gcc/fortran/data.cc
+++ b/gcc/fortran/data.cc
@@ -43,13 +43,14 @@ static void formalize_init_expr (gfc_expr *);

 /* Calculate the array element offset.  */

-static void
+static bool
 get_array_index (gfc_array_ref *ar, mpz_t *offset)
 {
   gfc_expr *e;
   int i;
   mpz_t delta;
   mpz_t tmp;
+  bool ok = true;

   mpz_init (tmp);
   mpz_set_si (*offset, 0);
@@ -59,13 +60,42 @@ get_array_index (gfc_array_ref *ar, mpz_t *offset)
   e = gfc_copy_expr (ar->start[i]);
   gfc_simplify_expr (e, 1);

-  if ((gfc_is_constant_expr (ar->as->lower[i]) == 0)
-	  || (gfc_is_constant_expr (ar->as->upper[i]) == 0)
-	  || (gfc_is_constant_expr (e) == 0))
-	gfc_error ("non-constant array in DATA statement %L", >where);
+  if (!gfc_is_constant_expr (ar->as->lower[i])
+	  || !gfc_is_constant_expr (ar->as->upper[i])
+	  || !gfc_is_constant_expr (e))
+	{
+	  gfc_error ("non-constant array in DATA statement %L", >where);
+	  ok = false;
+	  break;
+	}

   mpz_set (tmp, e->value.integer);
   gfc_free_expr (e);
+
+  /* Overindexing is only allowed as a legacy extension.  */
+  if (mpz_cmp (tmp, ar->as->lower[i]->value.integer) < 0
+	  && !gfc_notify_std (GFC_STD_LEGACY,
+			  "Subscript at %L below array lower bound "
+			  "(%ld < %ld) in dimension %d", >c_where[i],
+			  mpz_get_si (tmp),
+			  mpz_get_si (ar->as->lower[i]->value.integer),
+			  i+1))
+	{
+	  ok = false;
+	  break;
+	}
+  if (mpz_cmp (tmp, ar->as->upper[i]->value.integer) > 0
+	  && !gfc_notify_std (GFC_STD_LEGACY,
+			  "Subscript at %L above array upper bound "
+			  "(%ld > %ld) in dimension %d", >c_where[i],
+			  mpz_get_si (tmp),
+			  mpz_get_si (ar->as->upper[i]->value.integer),
+			  i+1))
+	{
+	  ok = false;
+	  break;
+	}
+
   mpz_sub (tmp, tmp, ar->as->lower[i]->value.integer);
   mpz_mul (tmp, tmp, delta);
   mpz_add (*offset, tmp, *offset);
@@ -77,6 +107,8 @@ get_array_index (gfc_array_ref *ar, mpz_t *offset)
 }
   mpz_clear (delta);
   mpz_clear (tmp);
+
+  return ok;
 }

 /* Find if there is a constructor which component is equal to COM.
@@ -298,7 +330,10 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index,
 	}

 	  if (ref->u.ar.type == AR_ELEMENT)
-	get_array_index (>u.ar, );
+	{
+	  if (!get_array_index (>u.ar, ))
+		goto abort;
+	}
 	  else
 	mpz_set (offset, index);

diff --git a/gcc/testsuite/gfortran.dg/data_bounds_1.f90 b/gcc/testsuite/gfortran.dg/data_bounds_1.f90
index 24cdc7c9815..1e6321a2884 100644
--- a/gcc/testsuite/gfortran.dg/data_bounds_1.f90
+++ b/gcc/testsuite/gfortran.dg/data_bounds_1.f90
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-std=gnu" }
+! { dg-options "-std=gnu -w" }
 ! Checks the fix for PR32315, in which the bounds checks below were not being done.
 !
 ! Contributed by Tobias Burnus 
diff --git a/gcc/testsuite/gfortran.dg/data_bounds_2.f90 b/gcc/testsuite/gfortran.dg/data_bounds_2.f90
new file mode 100644
index 000..1aa9fd4c423
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_bounds_2.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! { dg-options "-std=f2018" }
+! PR fortran/35095 - Improve bounds checking for DATA with implied-do
+
+program chkdata
+  character(len=2), dimension(2,2) :: str
+  data (str(i,1),i=1,3) / 'A','B','C' / ! { dg-error "above array upper bound" }
+  data 

Re: Help with fortran pointer ans OpenACC

2023-08-24 Thread Patrick Begou via Fortran

Hi Tobias,

many thanks for all these informations!
- I confirm, this clause solve the problem with GNU Fortran
- This workaround is fully compatible with Nvidia Fortran
- The problem with Cray Fortran remains (with this compiler, the 
test-case runs but the result is wrong)


I've tested the suggested options for debugging but I must admit that 
these intermediates files are a little bit out of my knowledge level to 
easily identify the problem.
In my work, portability is important and I have access to different 
compilers and GPU architectures and may be my best contribution to GNU 
software is limited to these tests and reports with small test-cases 
from a large scientific code that is expected to run on most GPU with 
various compilers.


Thanks again for your help and detailed explanation

Patrick

Le 23/08/2023 à 13:41, Tobias Burnus a écrit :

Hi,

On 23.08.23 12:19, Patrick Begou via Fortran wrote:

For several days I have some trouble with OpenACC offloading and
fortran pointers. I'm testing with a very small peace of code to
investigate but I do not progress for several days and I need your help.

Could someone give me advices or a small explanation on what I have
not understood there ?


First, for debugging, using -fdump-tree-original -fdump-tree-gimple
-fdump-tree-omplower and looking at the file .* might
help - grep for '#pragma'; this shows the internal representation
(incomplete) in a C like output. That's how I spotted the issue below.

* * *

For gfortran, the issue is:

    !$acc parallel loop collapse(2) default(present) if(runongpu)

It works if you add a "present(current)" → see also newly filed
https://gcc.gnu.org/PR16

gfortran seems to follow - but not completely - the spec:

Quoting from OpenACC 3.2: "2.6.2 Variables with Implicitly Determined
Data Attributes":

"A scalar variable will be treated as if it appears either:

* In a copy clause if the compute construct is a kernels construct.
* In a firstprivate clause otherwise.

Note: Any default(none) clause visible at the compute construct applies
to both aggregate and scalar variables. However, any default(present)
clause visible at the compute construct applies only to aggregate
variables."

However, the glossary defines:

"Aggregate variables – a variable of any non-scalar datatype, including
array or composite variables.
In Fortran, this includes any variable with allocatable or pointer
attribute and character variables."

And, as you have a (scalar) Fortran pointer, the following should have
applied instead:

"An aggregate variable will be treated as if it appears either:
• In a present clause if there is a default(present) clause visible at
the compute construct.
• In a copy clause otherwise."

* * *

Thus: It looks as if your program is valid, adding 'present(current)'
will fix it for gfortran (and Cray?), 'default(...)' and implicit
mapping is confusing, and there is now a gfortran PR to track this
issue: https://gcc.gnu.org/PR16

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 
201, 80634 München; Gesellschaft mit beschränkter Haftung; 
Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: 
München; Registergericht München, HRB 106955