diff options
author | Harald Anlauf <anlauf@gmx.de> | 2019-02-09 17:25:23 +0000 |
---|---|---|
committer | Harald Anlauf <anlauf@gcc.gnu.org> | 2019-02-09 17:25:23 +0000 |
commit | 1fe27030ff6424736ddda42874a018d6bc35db70 (patch) | |
tree | cd215e137ab074f7b775c4f7669e2327ff4b535d /gcc/fortran/resolve.c | |
parent | 5585759fdb6cc1e870670970473b789b3b920961 (diff) | |
download | gcc-1fe27030ff6424736ddda42874a018d6bc35db70.zip gcc-1fe27030ff6424736ddda42874a018d6bc35db70.tar.gz gcc-1fe27030ff6424736ddda42874a018d6bc35db70.tar.bz2 |
re PR fortran/89077 (ICE using * as len specifier for character parameter)
2019-02-09 Harald Anlauf <anlauf@gmx.de>
PR fortran/89077
* resolve.c (gfc_resolve_substring_charlen): Check substring
length for constantness prior to general calculation of length.
PR fortran/89077
* gfortran.dg/substr_simplify.f90: New test.
From-SVN: r268726
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r-- | gcc/fortran/resolve.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 92d27fc..3a8f402 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -4965,6 +4965,7 @@ gfc_resolve_substring_charlen (gfc_expr *e) gfc_ref *char_ref; gfc_expr *start, *end; gfc_typespec *ts = NULL; + mpz_t diff; for (char_ref = e->ref; char_ref; char_ref = char_ref->next) { @@ -5016,11 +5017,25 @@ gfc_resolve_substring_charlen (gfc_expr *e) return; } - /* Length = (end - start + 1). */ - e->ts.u.cl->length = gfc_subtract (end, start); - e->ts.u.cl->length = gfc_add (e->ts.u.cl->length, - gfc_get_int_expr (gfc_charlen_int_kind, - NULL, 1)); + /* Length = (end - start + 1). + Check first whether it has a constant length. */ + if (gfc_dep_difference (end, start, &diff)) + { + gfc_expr *len = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind, + &e->where); + + mpz_add_ui (len->value.integer, diff, 1); + mpz_clear (diff); + e->ts.u.cl->length = len; + /* The check for length < 0 is handled below */ + } + else + { + e->ts.u.cl->length = gfc_subtract (end, start); + e->ts.u.cl->length = gfc_add (e->ts.u.cl->length, + gfc_get_int_expr (gfc_charlen_int_kind, + NULL, 1)); + } /* F2008, 6.4.1: Both the starting point and the ending point shall be within the range 1, 2, ..., n unless the starting point exceeds |