*Ping* [PATCH] PR fortran/101084 - [10/11/12 Regression] ICE in gfc_typenode_for_spec, at fortran/trans-types.c:1124

2021-07-12 Thread Harald Anlauf via Fortran
*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

2021-07-12 Thread Harald Anlauf via Fortran
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

2021-07-12 Thread Sandra Loosemore

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