This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: PING: [patch, fortran] PR 27997: Implement F2003-style array constructor with typespec
- From: FX <fxcoudert at gmail dot com>
- To: Daniel Kraft <d at domob dot eu>
- Cc: Fortran List <fortran at gcc dot gnu dot org>
- Date: Fri, 25 Apr 2008 15:09:38 +0200
- Subject: Re: PING: [patch, fortran] PR 27997: Implement F2003-style array constructor with typespec
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:in-reply-to:references:mime-version:content-type:message-id:cc:content-transfer-encoding:from:subject:date:to:x-mailer; bh=89qlW62yli9WTVVlkbb4ha4FviwaD3SDtWRy8ShlhD0=; b=kayFpsl21dSp6M3lEnGIyTKmDAFqHBZp6JuBlBKV6vUJjdqAkb9e+gEF/gRuDORZXnMwjnif7lrLJfa43u4GNMpzXlzR/h8SZJXRKH+nxGU0cUK8/+x6rPvLD0ntts1OtYtbKZTMHpzJQlEed8VkYObr/Bz2biN+HDTszUtflNQ=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=in-reply-to:references:mime-version:content-type:message-id:cc:content-transfer-encoding:from:subject:date:to:x-mailer; b=ci5k7xQordXVLyhEq6DDTUPyil4PhnMpTVh+tTAR3risgSOFxQlIfvnRpgNcNDsvMiUFQZoiXEbbtqW/pbPxp2nVuu8COVcWD9mvds4vC4HasTV1W0AcJPB7It/Sqp3n2q7IDwzEcxKGHuj7p08QZYMfSpcttmN0T2uUUXyhe3c=
- References: <480E2FA1.4050601@domob.eu>
Hi Daniel,
Ante-scriptum 1: Any news from you copyright assignment?
Ante-scriptum 2: I'm reviewing this one a plane, so I don't get
access to web and bugzilla... I might say thus report an issue that
is already know :)
Please find my review below. It's globally a well-written patch,
following GNU coding standards and has quite a testcases, which is
good and we sometime overlook a bit (writing elaborate testcases
covering all cases one can think of is a tiresome exercise). This is
not yet OK to commit (although it's fairly close), I suspect you'll
want to update it and respond to some of my comments below.
2008-04-07 Daniel Kraft <d@domob.eu>
PR fortran/27997
* gfortran.h: Added field "length_from_typespec" to
gfc_charlength needed for the patch.
* array.c: Added parsing of typespec to
gfc_match_array_constructor and extended
gfc_resolve_character_array_constructor to correctly
pad strings when a constant character length was given
by a typespec.
* trans-array.c: Added code to gfc_trans_array_constructor
to support explicit but dynamic character lengths.
The correct format includes the names of each function touched:
YYYY-MM-DD Joe Hacker <joe@hacker.name>
PR ######
* file1.h (function1): This is what I changed in function1.
(function2): This is what I changed in function2.
(function3): Again.
* file2.c (function1, function2): Made same changes in both
functions.
2008-04-07 Daniel Kraft <d@domob.eu>
PR fortran/27997
* gfortran.dg/array_constructor_type_1.f03: New test
* gfortran.dg/array_constructor_type_2.f03: New test
* gfortran.dg/array_constructor_type_3.f03: New test
* gfortran.dg/array_constructor_type_4.f03: New test
* gfortran.dg/array_constructor_type_5.f03: New test
* gfortran.dg/array_constructor_type_6.f03: New test
* gfortran.dg/array_constructor_type_7.f03: New test
* gfortran.dg/array_constructor_type_8.f03: New test
* gfortran.dg/array_constructor_type_9.f: New test
* gfortran.dg/array_constructor_type_10.f03: New test
* gfortran.dg/array_constructor_type_11.f03: New test
* gfortran.dg/array_constructor_type_12.f03: New test
* gfortran.dg/array_constructor_type_13.f90: New test
I am wondering: could you add some testcases with failing conversion
to the constructor type. I see four cases I'd like covered: a too
long string, like that:
write *, [ character(len=1) :: "I am too long", "me too" ]
and a value that doesn't fit in the constructor type, like that:
write *, [ integer(4) :: huge(0_8) ]
Also, I think we should also include a testcase with derived types:
type foo
integer i
real x
end type foo
type(foo), parameter :: x = foo(42, 42.)
print *, [type(foo) :: x, foo(0,1) ]
end
(this one just shows that it works, but is not dejagnu-ified). Also,
a rejected conversion of derived types:
print *, [type(foo) :: x, foo(0,1), bar(.true.) ]
1
Error: Can't convert TYPE(bar) to TYPE(foo) at (1)
And constructors withing constructors, like this:
print *, [ integer(kind=8) :: 4, [ integer(kind=4) :: 42, 12 ] ]
print *, [ integer(kind=8) :: [ integer(kind=4) :: 42, 12 ] ]
print *, [ integer(kind=8) :: [ integer(kind=4) :: ] ]
print *, [ character(len=8) :: "foo", [ character(len=4) :: "bar",
"gee" ] ]
print *, [ character(len=8) :: "foo", [ character(len=4) :: ] ]
print *, [ character(len=8) :: [ character(len=4) :: ] ]
end
OK, let's dig in:
Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c (revision 133867)
+++ gcc/fortran/trans-array.c (working copy)
@@ -960,9 +960,10 @@
}
-/* Assign an element of an array constructor. */
+/* Variables needed for bounds-checking. */
static bool first_len;
static tree first_len_val;
+static bool typespec_ctor;
static void
gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
@@ -999,7 +1000,7 @@
se->string_length,
se->expr);
}
- if (flag_bounds_check)
+ if (flag_bounds_check && !typespec_ctor)
{
if (first_len)
{
I've tried to trigger that code and could not see it work. I cannot
see a runtime error, neither with
call test ("this is long")
contains
subroutine test(s)
character(len=*) :: s
print *, [ character(len=3) :: s, "foo" ]
end subroutine test
end
nor with
call test ("this is long")
contains
subroutine test(s)
character(len=*) :: s
print *, [ s, "foo" ]
end subroutine test
end
As this was not working previously, I'm not asking you to fix it in
this patch :) But, being now our most proficient expert in array
constructors, you might have an opinion as to why that doesn't
work... Otherwise, please file a PR so it's fixed later.
@@ -1681,7 +1682,11 @@
tree type;
bool dynamic;
- if (flag_bounds_check && ss->expr->ts.type == BT_CHARACTER)
+ /* Do bounds-checking here and in gfc_trans_array_ctor_element
only if no
+ typespec was given for the array constructor. */
+ typespec_ctor = (ss->expr->ts.cl && ss->expr->ts.cl-
>length_from_typespec);
This means you only ever set typespec_ctor for character arrays. This
is fine with me, because that's the information we need, but I
suggest giving the variable a name that indicates this fact (lest
someone uses it for other type).
+ /* XXX: Adding typespec_ctor here was merely a hack to make
+ gfortran.dg/array_constructor_17.f90 work (ICE otherwise). Is this
+ ok anyway or should I look for another solution? */
I can't tell, because there is no gfortran.dg/
array_constructor_17.f90 testcase in your patch :) It depends on why
we had an ICE, but it looks OK as it is.
+ /* XXX: This works for my tests, but is this the correct way to
+ transform the gfc_expr into a tree? */
Ah... well, it rather depends... you've got the right function, but
I'd suggest here using the variant with a type, gfc_conv_expr_type():
+ gfc_init_se (&length_se, NULL);
+ gfc_conv_expr (&length_se, ss->expr->ts.cl->length);
That second line would be :
gfc_conv_expr_type (&length_se, ss->expr->ts.cl-
>length, gfc_charlen_type_node);
+ ss->string_length = length_se.expr;
That one is fine. But, you have created gfc_se, and it might have pre
and post blocks (i.e. things that were added before and after the
loop, like evaluation of some loop invariant quantities). This is
done by:
gfc_add_block_to_block (&loop->pre, &length_se.pre);
gfc_add_block_to_block (&loop->post, &length_se.post);
which adds these pre and post blocks to the pre and post blocks of
the global loop (passed as a parameter to the function).
/* Update the character length of the array constructor. */
expr->ts.cl->length = gfc_int_expr (max_length);
- /* Update the element constructors. */
- for (p = expr->value.constructor; p; p = p->next)
- if (p->expr->expr_type == EXPR_CONSTANT)
- gfc_set_constant_character_len (max_length, p->expr, true);
+ generated_length = true;
+ /* Real update follows below. */
Hum, the comments should be rewritten, removing the "historical"
ones, like:
/* Mark
+ if (expr->ts.cl->length->ts.type == BT_INTEGER)
+ {
+ if (expr->ts.cl->length->expr_type == EXPR_CONSTANT)
+ {
+ /* Got a constant character length, pad according to this. */
+ max_length = mpz_get_si (expr->ts.cl->length->value.integer);
+ }
+ }
+ }
I imagine this is written that way for historical reasons. The proper
style would be:
/* We've got a character length specified. It should be an
integer,
otherwise an error is signalled elsewhere. */
gcc_assert (expr->ts.cl->length);
/* If we've got a constant character length, pad according to
this. */
if (expr->ts.cl->length->ts.type == BT_INTEGER
&& expr->ts.cl->length->expr_type == EXPR_CONSTANT)
max_length = mpz_get_si (expr->ts.cl->length->value.integer);
(indentation of this code might be weird, as I'm writing this
directly in the mailer).
As for the use of mpz_get_si() directly on the value, it is done too
often in currently existing code but is not a good coding practice:
the expr->ts.cl->length->value.integer might not fit in a host
integer. Please use gfc_extract_int() instead. (It is m project, at
some point, to audit all uses of mpz_get_si in the front-end, but I
never got around to it; we should also have a function
gfc_extract_hwint that returns a HOST_WIDE_INT instead of a
gfc_extract_int, for that matter).
+ if (generated_length || ! cl
+ || (cl->expr_type == EXPR_CONSTANT
+ && cl->ts.type == BT_INTEGER
+ && mpz_get_si (cl->value.integer) < max_length))
+ {
+ gfc_set_constant_character_len (max_length, p->expr, true);
+ }
Unneeded braces. It looks like we could easily emit an error for
strings of constant length that are too long, couldn't we?
Thanks for this very fine patch. I look forward to reading your
comments.
FX
--
François-Xavier Coudert
http://www.homepages.ucl.ac.uk/~uccafco/