*Ping* [PATCH] PR fortran/101084 - [10/11/12 Regression] ICE in gfc_typenode_for_spec, at fortran/trans-types.c:1124
*Ping* > Gesendet: Dienstag, 15. Juni 2021 um 21:31 Uhr > Von: "Harald Anlauf" > An: "fortran" , "gcc-patches" > Betreff: [PATCH] PR fortran/101084 - [10/11/12 Regression] ICE in > gfc_typenode_for_spec, at fortran/trans-types.c:1124 > > A recent change to the checking of legacy FORMAT tags did not handle > cases where the type is not set. Adjust the check. > > Regtested on x86_64-pc-linux-gnu. > > OK for mainline / 11- / 10-branch? > > Thanks, > Harald > > > Fortran: reject FORMAT tag of unknown type. > > gcc/fortran/ChangeLog: > > PR fortran/101084 > * io.c (resolve_tag_format): Extend FORMAT check to unknown type. > > gcc/testsuite/ChangeLog: > > PR fortran/101084 > * gfortran.dg/fmt_nonchar_3.f90: New test. > >
Re: [PATCH] PR fortran/100950 - ICE in output_constructor_regular_field, at varasm.c:5514
Hi Tobias, > On 10.06.21 20:52, Harald Anlauf via Fortran wrote: > > +static bool > > +substring_has_constant_len (gfc_expr *e) > > +{ > > + ptrdiff_t istart, iend; > > + size_t length; > > + bool equal_length = false; > > + > > + if (e->ts.type != BT_CHARACTER > > + || !e->ref > > + || e->ref->type != REF_SUBSTRING > > Is there a reason why you do not handle: > > type t >character(len=5) :: str1 >character(len=:), allocatable :: str2 > end type > type(t) :: x > > allocate(x%str2, source="abd") > if (len (x%str)) /= 1) ... > if (len (x%str2(1:2) /= 2) ... > etc. > > Namely: Search the last_ref = expr->ref->next->next ...? > and then check that lastref? I was assuming that the argument passed to LEN() is already the ultimate component for the case of substrings, and I was unable to find a case which requires implementing that iteration. The cases you provided do not seem to apply here: - derived type component str1, which is a string of given length, poses no problem. I added a case to the testcase, see attached updated patch. - derived type component str2 has deferred length. I do not see that the simplification can be applied here, as the allocation could lead to str2 being too short, and we do not want to simplify invalid code, such as: type t character(len=:), allocatable :: str2 end type type(t) :: x allocate(x%str2, source="z") if (len (x%str2(1:2)) /= 2) stop 1 end If we want this to be catchable by bounds checking, we need to punt at simplification of this. The updated patch skips deferred strings. >* * * > > Slightly unrelated: I think the following does not violate > F2018's R916 / C923 – but is rejected, namely: >R916 type-param-inquiry is designator % type-param-name > the latter is 'len' or 'kind' for intrinsic types. And: >R901 designator is ... > or substring > But > > character(len=5) :: str > print *, str(1:3)%len > end > > fails with > > 2 | print *, str(1:3)%len >| 1 > Error: Syntax error in PRINT statement at (1) > > > Assuming you don't want to handle it, can you open a new PR? > Thanks! Good point. I'd rather open a separate PR for this, though. > > + istart = gfc_mpz_get_hwi (e->ref->u.ss.start->value.integer); > > + iend = gfc_mpz_get_hwi (e->ref->u.ss.end->value.integer); > > + length = gfc_mpz_get_hwi (e->ref->u.ss.length->length->value.integer); > > + > > + if (istart <= iend) > > +{ > > + if (istart < 1) > > + { > > + gfc_error ("Substring start index (%ld) at %L below 1", > > + (long) istart, &e->ref->u.ss.start->where); > > As mentioned by Bernhard, you could use HOST_WIDE_INT_PRINT_DEC. > > (It probably only matters on Windows which uses long == int = 32bit for > strings longer than INT_MAX.) I am not familiar enough with Windows. What is HOST_WIDE_INT on that system? (As compared to e.g. size_t, ptrdiff_t). The (slightly) updated patch regtests fine. Thanks, Harald diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index c27b47aa98f..7f22372afec 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -4512,6 +4512,62 @@ gfc_simplify_leadz (gfc_expr *e) } +/* Check for constant length of a substring. */ + +static bool +substring_has_constant_len (gfc_expr *e) +{ + ptrdiff_t istart, iend; + size_t length; + bool equal_length = false; + + if (e->ts.type != BT_CHARACTER + || e->ts.deferred + || !e->ref + || e->ref->type != REF_SUBSTRING + || !e->ref->u.ss.start + || e->ref->u.ss.start->expr_type != EXPR_CONSTANT + || !e->ref->u.ss.end + || e->ref->u.ss.end->expr_type != EXPR_CONSTANT + || !e->ref->u.ss.length + || !e->ref->u.ss.length->length + || e->ref->u.ss.length->length->expr_type != EXPR_CONSTANT) +return false; + + /* Basic checks on substring starting and ending indices. */ + if (!gfc_resolve_substring (e->ref, &equal_length)) +return false; + + istart = gfc_mpz_get_hwi (e->ref->u.ss.start->value.integer); + iend = gfc_mpz_get_hwi (e->ref->u.ss.end->value.integer); + length = gfc_mpz_get_hwi (e->ref->u.ss.length->length->value.integer); + + if (istart <= iend) +{ + if (istart < 1) + { + gfc_error ("Substring start index (%ld) at %L below 1", + (long) istart, &e->ref->u.ss.start->where); + return false; + } + if (iend > (ssize_t) length) + { + gfc_error ("Substring end index (%ld) at %L exceeds string " + "length", (long) iend, &e->ref->u.ss.end->where); + return false; + } + length = iend - istart + 1; +} + else +length = 0; + + /* Fix substring length. */ + e->value.character.length = length; + + return true; +} + + gfc_expr * gfc_simplify_len (gfc_expr *e, gfc_expr *kind) { @@ -4521,7 +4577,11 @@ gfc_simplify_len (gfc_expr *e, gfc_expr *kind) if (k == -1) return &gfc_bad_expr; - if (e->expr_type == EXPR_CONSTANT) + if (e->ts.deferred) +return
Re: [Patch, fortran] PR fortran/100906/100907/100911/100914/100915/100916
On 6/13/21 12:36 PM, José Rui Faustino de Sousa via Gcc-patches wrote: Hi All! Proposed patch to: Bug 100906 - Bind(c): failure handling character with len/=1 Bug 100907 - Bind(c): failure handling wide character Bug 100911 - Bind(c): failure handling C_PTR Bug 100914 - Bind(c): errors handling complex Bug 100915 - Bind(c): failure handling C_FUNPTR Bug 100916 - Bind(c): CFI_type_other unimplemented I've been playing a bit with this patch in conjunction with my TS29113 testsuite. It seems to help some things, but it causes a regression in library/section-1.f90 that I don't really understand. :-S I'm also still running up against the long double bug in PR100917; after doing some experiments on top of this patch, I suggested some possible solutions/workarounds in that issue. Patch tested only on x86_64-pc-linux-gnu. In general, I think it is a good idea to test interoperability features on a 32-bit host as well. I've been building i686-pc-linux-gnu and testing both -m32 and -m64 multilibs. ISO_Fortran_binding.h is pretty broken on 32-bit host but I'll have a patch for that in the next day or so. Anyway, I have a few comments on the libgfortran changes, mostly cosmetic things. I'm not at all familiar with the workings of the Fortran front end code that produces descriptors, so I don't think I have anything useful to say about that part of the patch. diff --git a/libgfortran/runtime/ISO_Fortran_binding.c b/libgfortran/runtime/ISO_Fortran_binding.c index 20833ad..3a269d7 100644 --- a/libgfortran/runtime/ISO_Fortran_binding.c +++ b/libgfortran/runtime/ISO_Fortran_binding.c @@ -36,31 +36,81 @@ export_proto(cfi_desc_to_gfc_desc); void cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr) { + signed char type, kind; + size_t size; int n; - index_type kind; CFI_cdesc_t *s = *s_ptr; if (!s) return; + /* Verify descriptor. */ + switch(s->attribute) GNU coding standards: space before the open paren. +{ +case CFI_attribute_pointer: +case CFI_attribute_allocatable: + break; +case CFI_attribute_other: + if (s->base_addr) + break; + /* FALL THROUGH */ +default: + internal_error (NULL, "INVALID CFI DESCRIPTOR"); We could have a better message here that doesn't SHOUT. Maybe "Invalid attribute in CFI descriptor"? + kind = _CFI_DECODE_KIND (s->type); + switch(type) Space before the paren again. +{ +case BT_INTEGER: +case BT_LOGICAL: +case BT_REAL: + size = (size_t)kind; + break; +case BT_COMPLEX: + size = (size_t)(kind << 1); + break; +case BT_DERIVED: +case BT_CHARACTER: +case BT_VOID: + size = s->elem_len; + break; +default: + if (type != CFI_type_other) + internal_error(NULL, "TYPE ERROR"); Space before the paren and better error message again. Section 18.5.4 of the Fortran 2018 standard says: "If a C type is not interoperable with a Fortran type and kind supported by the Fortran processor, its macro shall evaluate to a negative value." And in fact I'll have a patch for PR101305 soon that will use a negative value distinct from CFI_type_other for that. If you construct a descriptor for such an object in C and try passing it to Fortran, I think that's a user error, not an internal error. + if (size <= 0) +internal_error(NULL, "SIZE ERROR"); Same issues here with fixing formatting and better message. + GFC_DESCRIPTOR_SIZE (d) = size; + d->dtype.version = s->version; + + if ((s->rank < 0) || (s->rank > CFI_MAX_RANK)) You could delete the inner parentheses here. +internal_error(NULL, "Rank out of range."); Space before the paren again. It also looks like other error messages in libgfortran don't add punctuation at the end. There are several more instances of space-before-paren problems and fixing the errpr messages, I'm not going to point the rest of them out individually. @@ -74,14 +124,19 @@ cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr) } d->offset = 0; - for (n = 0; n < GFC_DESCRIPTOR_RANK (d); n++) -{ - GFC_DESCRIPTOR_LBOUND(d, n) = (index_type)s->dim[n].lower_bound; - GFC_DESCRIPTOR_UBOUND(d, n) = (index_type)(s->dim[n].extent - + s->dim[n].lower_bound - 1); - GFC_DESCRIPTOR_STRIDE(d, n) = (index_type)(s->dim[n].sm / s->elem_len); - d->offset -= GFC_DESCRIPTOR_STRIDE(d, n) * GFC_DESCRIPTOR_LBOUND(d, n); -} + if (GFC_DESCRIPTOR_DATA (d)) +for (n = 0; n < GFC_DESCRIPTOR_RANK (d); n++) + { + CFI_index_t lb = 1; + + if (s->attribute != CFI_attribute_other) + lb = s->dim[n].lower_bound; + + GFC_DESCRIPTOR_LBOUND(d, n) = (index_type)lb; + GFC_DESCRIPTOR_UBOUND(d, n) = (index_type)(s->dim[n].extent + lb - 1); + GFC_DESCRIPTOR_STRIDE(d, n) = (index_type)(s->dim[n].sm / s->elem_len); + d->offset -= GFC_DESCRIPTOR