Le 27/11/2022 à 20:17, Mikael Morin a écrit :
Le 21/11/2022 à 19:46, Steve Kargl a écrit :
On Mon, Nov 21, 2022 at 11:34:07AM +0100, Mikael Morin wrote:
Le 21/11/2022 à 00:31, Steve Kargl via Fortran a écrit :
Unfortunately, gfortran does not define a namespace for an implied-do
index and uses a kludge by adding the attr.implied_index attribute to
the symbol. Unfortunately**2, gfortran uses gfc_match_iterator for
all places that 'i = start, stop [,step]' and there is no way to know
if what is being parsed. With the introduction of an optional
typespec,
there is no easy way to deal with it in a clean way. Things get messy
quickly when trying to deal with implicit typing and explicitly typed
symbols. So, if the implied-do index has previously been typed such as
integer(8) i
print *, (i, integer(2) i=1, 3)
the integer(2) is ignored. That's this part of the gfc_match_iterator
diff
+ if (seen_ts && var->ts.type == BT_UNKNOWN)
+ {
+ var->ts.type = ts.type;
+ var->ts.kind = ts.kind;
+ var->symtree->n.sym->ts.type = ts.type;
+ var->symtree->n.sym->ts.kind = ts.kind;
+ }
Perhaps, a better way would be to simply create a shadow symbol
if a typespec appears in an iterator
print *, (i, integer i=1,3)
would become
print *, (_i, integer _i=1,3)
The issue is then that implied-do object list needs to be walked
and all occurrence of i must be replaced with _i.
Or maybe a namespace could be created if seen_ts is true?
Yes, I thought about creating a new namespace, but I don't
have too much experience on how to deal with them. Even
with a new namespace, we have to deal with an implied-do
loop in an initialization expression. At the moment,
gfc_reduce_init_expr() does recognize some (all?) implied-do
loops.
This is legal code, which uses implicit typing. Here,
I get an integer type, but gfc_reduce_init_expr() rejects
the construct.
program foo
use iso_fortran_env, only : k => real_kinds
integer, parameter :: n = size(k)
integer, parameter ::p(n) = [(digits(real(1.,k(i))),i = 1,n)]
print '(*(I0,X))', p
end program foo
% gfortran -o z a.f90
a.f90:6:30:
6 | & p(n) = [(digits(real(1.,k(i))), i = 1, n)]
| 1
Error: Invalid kind for REAL at (1)
I have looked at it, it is a tricky bug.
The first step of gfc_check_init_expr, way before trying to expand the
array constructor, is to resolve it. Resolution of the array
constructor needs resolution of the ac-value expression, which needs
resolution of the real(...) expression. Resolution of that expression
calls gfc_check_real, which checks that the KIND argument is a valid
kind, which means among other things being constant, and being able to
extract its value to check it against the list of defined kinds for the
platform. And we can't extract its value before the expansion of the
array constructor, so the error is emitted, which prevents array
constructor expansion later on.
So it's a kind of chicken and egg problem.
Right now, I don't see any solution (except simply removing the error).
With the following patch, no error is reported in case of failure of
gfc_extract_int. As the constantness and type checks have been
redundantly checked in kind_check before the call to gfc_extract_int, we
only miss to report an error if the value doesn't fit on a host int. I
think it's an acceptable loss.
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index 91d87a1b2c1..a8edeebe9cd 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -654,12 +654,14 @@ kind_check (gfc_expr *k, int n, bt type)
return false;
}
- if (gfc_extract_int (k, &kind)
- || gfc_validate_kind (type, kind, true) < 0)
+ if (!gfc_extract_int (k, &kind))
{
- gfc_error ("Invalid kind for %s at %L", gfc_basic_typename (type),
- &k->where);
- return false;
+ if (gfc_validate_kind (type, kind, true) < 0)
+ {
+ gfc_error ("Invalid kind for %s at %L", gfc_basic_typename (type),
+ &k->where);
+ return false;
+ }
}
return true;
This avoids emitting the error you were facing.
Unfortunately, the same error is caught later at a different place.
test.f90:4:48:
4 | integer, parameter ::p(n) = [(digits(real(1.,k(i))),i = 1,n)]
| 1
Error: KIND parameter of REAL at (1) must be an initialization expression