public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch, fortran] PRs 105152, 100193, 87946, 103389, 104429 and 82774
@ 2023-04-22  8:32 Paul Richard Thomas
  2023-04-23 21:48 ` Harald Anlauf
  0 siblings, 1 reply; 3+ messages in thread
From: Paul Richard Thomas @ 2023-04-22  8:32 UTC (permalink / raw)
  To: fortran, gcc-patches


[-- Attachment #1.1: Type: text/plain, Size: 1479 bytes --]

Hi All,

As usual, I received a string of emails on retargeting for PRs for which I
was either responsible or was on the cc list. This time I decided to take a
look at them all, in order to reward the tireless efforts of Richi, Jakub
and Martin with some attention at least.

I have fixed the PRs in the title line: See the attached changelog, patch
and testcases.

OK for 14-branch?

Of the others:
PR100815 - fixed already for 12-branch on. Martin located the fix from
Tobias, for which thanks. It's quite large but has stood the test of time.
Should I backport to 11-branch?
PR103366 - fixed on 12-branch on. I closed it.
PR103715 - might be fixed but the report is for gcc with checking enabled.
I will give that a go.
PR103716 - a gimple problem with assumed shape characters. A TODO.
PR103931 - I couldn't reproduce the bug, which involves 'ambiguous c_ptr'.
To judge by the comments, it seems that this bug is a bit elusive.
PR65381 - Seems to be fixed for 12-branch on
PR82064 - Seems to be fixed.
PR83209 - Coarray allocation - seems to be fixed.
PR84244 - Coarray segfault. I have no acquaintance with the inner works of
coarrays and so don't think that I can fix this one.
PR87674 - Segfault in runtime with non-overridable proc-pointer. A TODO.
PR96087 - A module procedure problem. A TODO.

I have dejagnu-ified testcases for the already fixed PRs ready to go.
Should these be committed or do we assume that the fixes already provided
adequate tests?

Regards

Paul

[-- Attachment #2: pr105152.f90 --]
[-- Type: text/x-fortran, Size: 445 bytes --]

! { dg-do compile }
!
! Contributed by Gerhard Steinmetz  <gscfq@t-online.de>
!
program p
   use iso_c_binding
   type, bind(c) :: t
      integer(c_int) :: a
   end type
   interface
      function f(x) bind(c) result(z)
         import :: c_int, t
         type(t) :: x(:)
         integer(c_int) :: z
      end
   end interface
   class(*), allocatable :: y(:)
   n = f(y) ! { dg-error "either an unlimited polymorphic or assumed type" }
end

[-- Attachment #3: pr100193.f90 --]
[-- Type: text/x-fortran, Size: 440 bytes --]

! { dg-do compile }
!
! Contributed by Gerhard Steinmetz  <gscfq@t-online.de>
!
module m
   implicit none
   type t
      procedure(f), pointer, nopass :: g
   end type
contains
   function f()
      character(:), allocatable :: f
      f = 'abc'
   end
   subroutine s
      type(t) :: z
      z%g = 'x'  ! { dg-error "is a procedure pointer" }
      if ( z%g() /= 'abc' ) stop
   end
end
program p
   use m
   implicit none
   call s
end

[-- Attachment #4: pr87946.f90 --]
[-- Type: text/x-fortran, Size: 801 bytes --]

! { dg-do run }
!
! Contributed by Gerhard Steinmetz  <gscfq@t-online.de>
!
module m
   type t
   contains
      generic :: h => g
      procedure, private :: g
   end type
contains
   function g(x, y) result(z)
      class(t), intent(in) :: x
      real, intent(in) :: y(:, :)
      real :: z(size(y, 2))
      integer :: i
      do i = 1, size(y, 2)
        z(i) = i
      end do
   end
end
module m2
   use m
   type t2
      class(t), allocatable :: u(:)
   end type
end
   use m2
   type(t2) :: x
   real :: y(1,5)
   allocate (x%u(1))
   if (any (int(f (x, y)) .ne. [1,2,3,4,5])) stop 1
   deallocate (x%u)
contains
   function f(x, y) result(z)
      use m2
      type(t2) :: x
      real :: y(:, :)
      real :: z(size(y, 2))
      z = x%u(1)%h(y)          ! Used to segfault here
   end
end

[-- Attachment #5: pr103389.f90 --]
[-- Type: text/x-fortran, Size: 406 bytes --]

! { dg-do run }
!
! Contributed by Gerhard Steinmetz  <gscfq@t-online.de>
!
program p
   type t
      integer, allocatable :: a(:)
   end type
   type(t) :: y
   y%a = [1,2]
   call s((y))
   if (any (y%a .ne. [3,4])) stop 1
contains
   subroutine s(x)
      class(*) :: x
      select type (x)
        type is (t)
          x%a = x%a + 2
        class default
          stop 2
      end select
   end
end

[-- Attachment #6: pr104429.f90 --]
[-- Type: text/x-fortran, Size: 678 bytes --]

! { dg-do run }
module m
   type t
      real :: r
   contains
      procedure :: op
      procedure :: assign
      generic :: operator(*) => op
      generic :: assignment(=) => assign
   end type
contains
   function op (x, y)
      class(t), allocatable :: op
      class(t), intent(in) :: x
      real, intent(in) :: y
      allocate (op, source = t (x%r * y))
   end
   subroutine assign (z, x)
      type(t), intent(in) :: x
      class(t), intent(out) :: z
      z%r = x%r
   end
end
program p
   use m
   class(t), allocatable :: x
   real :: y = 2
   allocate (x, source = t (2.0))
   x = x * y
   if (int (x%r) .ne. 4) stop 1
   if (allocated (x)) deallocate (x)
end

[-- Attachment #7: pr82774.f90 --]
[-- Type: text/x-fortran, Size: 395 bytes --]

! { dg-do run }
!
! Contributed by Steve Kargl  <kargl@gcc.gnu.org>
!
program main
   implicit none
   type stuff
      character(:), allocatable :: key
   end type stuff
   type(stuff) nonsense, total
   nonsense = stuff('Xe')
   total = stuff(nonsense%key) ! trim nonsense%key made this work
   if (nonsense%key /= total%key) call abort
   if (len(total%key) /= 2) call abort
end program main

[-- Attachment #8: Change.Logs --]
[-- Type: application/octet-stream, Size: 2020 bytes --]

Fortran: Fix an assortment of bugs

2023-04-22  Paul Thomas  <pault@gcc.gnu.org>

gcc/fortran
	PR fortran/105152
	* interface.cc (gfc_compare_actual_formal): Emit an error if an
	unlimited polymorphic actual is not matched either to an
	unlimited or assumed type formal argument.

	PR fortran/100193
	* resolve.cc (resolve_ordinary_assign): Emit an error if the
	var expression of an ordinary assignment is a proc pointer
	component.

	PR fortran/87496
	* trans-array.cc (gfc_walk_array_ref): Provide assumed shape
	arrays coming from interface mapping with a viable arrayspec.

	PR fortran/103389
	* trans-expr.cc (gfc_conv_intrinsic_to_class): Tidy up flagging
	of unlimited polymorphic 'class_ts'.
	(gfc_conv_gfc_desc_to_cfi_desc): Assumed type is unlimited
	polymorphic and should accept any actual type.

	PR fortran/104429
	(gfc_conv_procedure_call): Replace dreadful kludge with a call
	to gfc_finalize_tree_expr. Avoid dereferencing a void pointer
	by giving it the pointer type of the actual argument.

	PR fortran/82774
	(alloc_scalar_allocatable_subcomponent): Shorten the function
	name and replace the symbol argument with the se string length.
	If a deferred length character length is either not present or
	is not a variable, give the typespec a variable and assign the
	string length to that. Use gfc_deferred_strlen to find the
	hidden string length component.
	(gfc_trans_subcomponent_assign): Convert the expression before
	the call to alloc_scalar_allocatable_subcomponent so that a
	good string length is provided.
	(gfc_trans_structure_assign): Remove the unneeded derived type
	symbol from calls to gfc_trans_subcomponent_assign.

gcc/testsuite/
	PR fortran/105152
	* gfortran.dg/pr105152.f90 : New test

	PR fortran/100193
	* gfortran.dg/pr100193.f90 : New test

	PR fortran/87946
	* gfortran.dg/pr87946.f90 : New test

	PR fortran/103389
	* gfortran.dg/pr103389.f90 : New test

	PR fortran/104429
	* gfortran.dg/pr100193.f90 : New test

	PR fortran/82774
	* gfortran.dg/pr100193.f90 : New test

[-- Attachment #9: submit.diff --]
[-- Type: text/x-patch, Size: 9731 bytes --]

diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index e9843e9549c..fa505ab7ed9 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -3312,6 +3312,16 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
 	    }
 	}
 
+      if (UNLIMITED_POLY (a->expr)
+	  && !(f->sym->ts.type == BT_ASSUMED || UNLIMITED_POLY (f->sym)))
+	{
+	  gfc_error ("Unlimited polymorphic actual argument at %L is not "
+		     "matched with either an unlimited polymorphic or "
+		     "assumed type dummy argument", &a->expr->where);
+	  ok = false;
+	  goto match;
+	}
+
       /* Special case for character arguments.  For allocatable, pointer
 	 and assumed-shape dummies, the string length needs to match
 	 exactly.  */
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 55d8e326a87..aaca772320a 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -11129,6 +11129,17 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
   lhs = code->expr1;
   rhs = code->expr2;
 
+  if ((lhs->symtree->n.sym->ts.type == BT_DERIVED
+       || lhs->symtree->n.sym->ts.type == BT_CLASS)
+      && !lhs->symtree->n.sym->attr.proc_pointer
+      && gfc_expr_attr (lhs).proc_pointer)
+    {
+      gfc_error ("Variable in the ordinary assignment at %L is a procedure "
+		 "pointer component",
+		 &lhs->where);
+      return false;
+    }
+
   if ((gfc_numeric_ts (&lhs->ts) || lhs->ts.type == BT_LOGICAL)
       && rhs->ts.type == BT_CHARACTER
       && (rhs->expr_type != EXPR_CONSTANT || !flag_dec_char_conversions))
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index e1725808033..6c47b537dfc 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -11471,6 +11471,12 @@ gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
 	  break;
 
 	case AR_FULL:
+	  /* Assumed shape arrays from interface mapping need this fix.  */
+	  if (!ar->as && expr->symtree->n.sym->as)
+	    {
+	      ar->as = gfc_get_array_spec();
+	      *ar->as = *expr->symtree->n.sym->as;
+	    }
 	  newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
 	  newss->info->data.array.ref = ref;
 
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 09cdd9263c4..74d6948b0ae 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -996,6 +996,12 @@ gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
   tree var;
   tree tmp;
   int dim;
+  bool unlimited_poly;
+
+  unlimited_poly = class_ts.type == BT_CLASS
+		   && class_ts.u.derived->components->ts.type == BT_DERIVED
+		   && class_ts.u.derived->components->ts.u.derived
+						->attr.unlimited_polymorphic;
 
   /* The intrinsic type needs to be converted to a temporary
      CLASS object.  */
@@ -1067,9 +1073,7 @@ gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
     }
 
   gcc_assert (class_ts.type == BT_CLASS);
-  if (class_ts.u.derived->components->ts.type == BT_DERIVED
-      && class_ts.u.derived->components->ts.u.derived
-		 ->attr.unlimited_polymorphic)
+  if (unlimited_poly)
     {
       ctree = gfc_class_len_get (var);
       /* When the actual arg is a char array, then set the _len component of the
@@ -1116,10 +1120,7 @@ gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
 
       gfc_add_modify (&parmse->pre, ctree, fold_convert (TREE_TYPE (ctree), tmp));
     }
-  else if (class_ts.type == BT_CLASS
-	   && class_ts.u.derived->components
-	   && class_ts.u.derived->components->ts.u
-		.derived->attr.unlimited_polymorphic)
+  else if (unlimited_poly)
     {
       ctree = gfc_class_len_get (var);
       gfc_add_modify (&parmse->pre, ctree,
@@ -5650,7 +5651,7 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
 	  itype = CFI_type_other;  // FIXME: Or CFI_type_cptr ?
 	  break;
 	case BT_CLASS:
-	  if (UNLIMITED_POLY (e) && fsym->ts.type == BT_ASSUMED)
+	  if (fsym->ts.type == BT_ASSUMED)
 	    {
 	      // F2017: 7.3.2.2: "An entity that is declared using the TYPE(*)
 	      // type specifier is assumed-type and is an unlimited polymorphic
@@ -6682,20 +6683,11 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 			{
 			  tree zero;
 
-			  gfc_expr *var;
-
-			  /* Borrow the function symbol to make a call to
-			     gfc_add_finalizer_call and then restore it.  */
-			  tmp = e->symtree->n.sym->backend_decl;
-			  e->symtree->n.sym->backend_decl
-					= TREE_OPERAND (parmse.expr, 0);
-			  e->symtree->n.sym->attr.flavor = FL_VARIABLE;
-			  var = gfc_lval_expr_from_sym (e->symtree->n.sym);
-			  finalized = gfc_add_finalizer_call (&parmse.post,
-							      var);
-			  gfc_free_expr (var);
-			  e->symtree->n.sym->backend_decl = tmp;
-			  e->symtree->n.sym->attr.flavor = FL_PROCEDURE;
+			  /* Finalize the expression.  */
+			  gfc_finalize_tree_expr (&parmse, NULL,
+						  gfc_expr_attr (e), e->rank);
+			  gfc_add_block_to_block (&parmse.post,
+						  &parmse.finalblock);
 
 			  /* Then free the class _data.  */
 			  zero = build_int_cst (TREE_TYPE (parmse.expr), 0);
@@ -7131,7 +7123,15 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 		 types passed to class formals need the _data component.  */
 	      tmp = gfc_class_data_get (tmp);
 	      if (!CLASS_DATA (fsym)->attr.dimension)
-		tmp = build_fold_indirect_ref_loc (input_location, tmp);
+		{
+		  if (UNLIMITED_POLY (fsym))
+		    {
+		      tree type = gfc_typenode_for_spec (&e->ts);
+		      type = build_pointer_type (type);
+		      tmp = fold_convert (type, tmp);
+		    }
+		  tmp = build_fold_indirect_ref_loc (input_location, tmp);
+		}
 	    }
 
 	  if (e->expr_type == EXPR_OP
@@ -8767,11 +8767,9 @@ gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm,
 /* Allocate or reallocate scalar component, as necessary.  */
 
 static void
-alloc_scalar_allocatable_for_subcomponent_assignment (stmtblock_t *block,
-						      tree comp,
-						      gfc_component *cm,
-						      gfc_expr *expr2,
-						      gfc_symbol *sym)
+alloc_scalar_allocatable_subcomponent (stmtblock_t *block, tree comp,
+				       gfc_component *cm, gfc_expr *expr2,
+				       tree slen)
 {
   tree tmp;
   tree ptr;
@@ -8789,26 +8787,20 @@ alloc_scalar_allocatable_for_subcomponent_assignment (stmtblock_t *block,
 
   if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
     {
-      char name[GFC_MAX_SYMBOL_LEN+9];
-      gfc_component *strlen;
-      /* Use the rhs string length and the lhs element size.  */
       gcc_assert (expr2->ts.type == BT_CHARACTER);
-      if (!expr2->ts.u.cl->backend_decl)
-	{
-	  gfc_conv_string_length (expr2->ts.u.cl, expr2, block);
-	  gcc_assert (expr2->ts.u.cl->backend_decl);
-	}
+      if (!expr2->ts.u.cl->backend_decl
+	  || !VAR_P (expr2->ts.u.cl->backend_decl))
+	expr2->ts.u.cl->backend_decl = gfc_create_var (TREE_TYPE (slen),
+						       "slen");
+      gfc_add_modify (block, expr2->ts.u.cl->backend_decl, slen);
 
       size = expr2->ts.u.cl->backend_decl;
 
-      /* Ensure that cm->ts.u.cl->backend_decl is a componentref to _%s_length
-	 component.  */
-      sprintf (name, "_%s_length", cm->name);
-      strlen = gfc_find_component (sym, name, true, true, NULL);
+      gfc_deferred_strlen (cm, &tmp);
       lhs_cl_size = fold_build3_loc (input_location, COMPONENT_REF,
 				     gfc_charlen_type_node,
 				     TREE_OPERAND (comp, 0),
-				     strlen->backend_decl, NULL_TREE);
+				     tmp, NULL_TREE);
 
       tmp = TREE_TYPE (gfc_typenode_for_spec (&cm->ts));
       tmp = TYPE_SIZE_UNIT (tmp);
@@ -8881,8 +8873,8 @@ alloc_scalar_allocatable_for_subcomponent_assignment (stmtblock_t *block,
 /* Assign a single component of a derived type constructor.  */
 
 static tree
-gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr,
-			       gfc_symbol *sym, bool init)
+gfc_trans_subcomponent_assign (tree dest, gfc_component * cm,
+			       gfc_expr * expr, bool init)
 {
   gfc_se se;
   gfc_se lse;
@@ -8976,19 +8968,17 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr,
 	   || (cm->ts.type == BT_CLASS && CLASS_DATA (cm)->attr.allocatable
 	       && expr->ts.type != BT_CLASS)))
     {
+      gfc_init_se (&se, NULL);
+      gfc_conv_expr (&se, expr);
+
       /* Take care about non-array allocatable components here.  The alloc_*
 	 routine below is motivated by the alloc_scalar_allocatable_for_
 	 assignment() routine, but with the realloc portions removed and
 	 different input.  */
-      alloc_scalar_allocatable_for_subcomponent_assignment (&block,
-							    dest,
-							    cm,
-							    expr,
-							    sym);
+      alloc_scalar_allocatable_subcomponent (&block, dest, cm, expr,
+					     se.string_length);
       /* The remainder of these instructions follow the if (cm->attr.pointer)
 	 if (!cm->attr.dimension) part above.  */
-      gfc_init_se (&se, NULL);
-      gfc_conv_expr (&se, expr);
       gfc_add_block_to_block (&block, &se.pre);
 
       if (expr->symtree && expr->symtree->n.sym->attr.proc_pointer
@@ -9252,13 +9242,11 @@ gfc_trans_structure_assign (tree dest, gfc_expr * expr, bool init, bool coarray)
       if (!c->expr)
 	{
 	  gfc_expr *e = gfc_get_null_expr (NULL);
-	  tmp = gfc_trans_subcomponent_assign (tmp, cm, e, expr->ts.u.derived,
-					       init);
+	  tmp = gfc_trans_subcomponent_assign (tmp, cm, e, init);
 	  gfc_free_expr (e);
 	}
       else
-        tmp = gfc_trans_subcomponent_assign (tmp, cm, c->expr,
-                                             expr->ts.u.derived, init);
+        tmp = gfc_trans_subcomponent_assign (tmp, cm, c->expr, init);
       gfc_add_expr_to_block (&block, tmp);
     }
   return gfc_finish_block (&block);

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-04-24 16:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-22  8:32 [Patch, fortran] PRs 105152, 100193, 87946, 103389, 104429 and 82774 Paul Richard Thomas
2023-04-23 21:48 ` Harald Anlauf
2023-04-24 16:41   ` Bernhard Reutner-Fischer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).