diff mbox series

[fortran] PR99124 - [9/10/11 Regression] ICE in gfc_get_class_from_expr, at fortran/trans-expr.c:541

Message ID CAGkQGiLjBoKHxfse0-=9Y905H=SG2ZsGfH0k5mzkRYo0dURXLw@mail.gmail.com
State New
Headers show
Series [fortran] PR99124 - [9/10/11 Regression] ICE in gfc_get_class_from_expr, at fortran/trans-expr.c:541 | expand

Commit Message

Paul Richard Thomas Feb. 23, 2021, 11:52 a.m. UTC
Hi All,

This is a straightforward fix that had the side-effect of uncovering an
invalid testcase, class_assign_4.f90. I had worked up a new test, based on
the one in the PR, and found that another brand determined that it is
invalid according to F2018, C15100.

I was unable to find a way to use a typebound operator with a polymorphic
result and so resorted to correcting class_assign_4.f90 with an operator
interface. This respects the purpose of the test. I have left the commented
out lines in place for the review; these will be removed when committing.

Regtested on FC33/x86_64. OK for 9- to 11-branches?

Paul

Fortran: Fix for class functions as associated target [PR99124].

2021-02-23  Paul Thomas  <pault@gcc.gnu.org>

gcc/fortran
PR fortran/99124
* resolve.c (resolve_fl_procedure): Include class results in
the test for F2018, C15100.
* trans-array.c (get_class_info_from_ss): Do not use the saved
descriptor to obtain the class expression for variables. Use
gfc_get_class_from_expr instead.

gcc/testsuite/
PR fortran/99124
* gfortran.dg/class_defined_operator_2.f03 : New test.
* class_assign_4.f90: Correct the non-conforming elemental
function with an allocatable result with an operator interface
with array dummies and result.

Comments

Tobias Burnus Feb. 23, 2021, 12:30 p.m. UTC | #1
Hi Paul,

On 23.02.21 12:52, Paul Richard Thomas via Gcc-patches wrote:
> This is a straightforward fix that had the side-effect of uncovering an
> invalid testcase, class_assign_4.f90. I had worked up a new test, based on
> the one in the PR, and found that another brand determined that it is
> invalid according to F2018, C15100.

Namely: "C15100  All dummy arguments of an elemental procedure ... shall
not have the POINTER or ALLOCATABLE attribute."

The operator does not have to be elemental – as the fixed test case show.

→ Can you add also a testcase that which triggers the error message you
see in the unpatched  class_assign_4.f90?
> I was unable to find a way to use a typebound operator with a polymorphic
> result

I am confused – the attach testcase does seem to work fine with current
GCC. (And if we don't have such a testcase, it should be added.)

Can you elaborate?

> and so resorted to correcting class_assign_4.f90 with an operator
> interface. This respects the purpose of the test. I have left the commented
> out lines in place for the review; these will be removed when committing.
>
> Regtested on FC33/x86_64. OK for 9- to 11-branches?

The patch itself LGTM, except for testing the newly shown error message
and for the confusion about the type-bound operator.

Thanks,

Tobias

> Fortran: Fix for class functions as associated target [PR99124].
>
> 2021-02-23  Paul Thomas  <pault@gcc.gnu.org>
>
> gcc/fortran
> PR fortran/99124
> * resolve.c (resolve_fl_procedure): Include class results in
> the test for F2018, C15100.
> * trans-array.c (get_class_info_from_ss): Do not use the saved
> descriptor to obtain the class expression for variables. Use
> gfc_get_class_from_expr instead.
>
> gcc/testsuite/
> PR fortran/99124
> * gfortran.dg/class_defined_operator_2.f03 : New test.
> * class_assign_4.f90: Correct the non-conforming elemental
> function with an allocatable result with an operator interface
> with array dummies and result.
-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf
Paul Richard Thomas Feb. 23, 2021, 5:39 p.m. UTC | #2
Hi Tobias,

→ Can you add also a testcase that which triggers the error message you
> see in the unpatched  class_assign_4.f90?
> > I was unable to find a way to use a typebound operator with a polymorphic
> > result


> I am confused – the attach testcase does seem to work fine with current
> GCC. (And if we don't have such a testcase, it should be added.)


> Can you elaborate?
>



The polymorphic result must be allocatable or pointer for the dynamic type
to be transmitted. This means that the function cannot be elemental. If the
result of the non-elemental function is an array, gfc responds with:
"Error: Passed-object dummy argument of ‘f’ at (1) must be scalar"
If the procedure declaration is made nopass, the response is:
"Type-bound operator at (1) cannot be NOPASS"

See the attached elemental_result_2.f90, which tests the new error message.

From these points, I concluded that a typebound operator could not provide
the required polymorphic array result. If I am wrong about this, please let
me know and I will change the patch accordingly.

The interface operator does not have these constraints and so was
implemented in class_assign_4.f90.

The patch itself LGTM, except for testing the newly shown error message
> and for the confusion about the type-bound operator.
>

 All done. Note that the patch has changed slightly in resolve.c because
(1) it was the wrong version and (2) it sporadically segfaulted at line
13240.

Thanks

Paul
Tobias Burnus Feb. 23, 2021, 6:06 p.m. UTC | #3
Hi Paul,

On 23.02.21 18:39, Paul Richard Thomas via Fortran wrote:
>> Can you elaborate?
> The polymorphic result must be allocatable or pointer for the dynamic type
> to be transmitted. This means that the function cannot be elemental. If the
> result of the non-elemental function is an array, gfc responds with:
> "Error: Passed-object dummy argument of ‘f’ at (1) must be scalar"

Ok, I think I understood the issue: The problem is that with 'pass', you
get a scalar as argument; and with scalars, you'd need 'elemental',
which is not permitted.

Sorry, I missed the 'pass' → 'scalar' step. I did get the 'elemental' →
nonalloc step.

> All done. Note that the patch has changed slightly in resolve.c because
> (1) it was the wrong version and (2) it sporadically segfaulted at line
> 13240.

Ups!

LGTM. Thanks for the patch!

Tobias

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf
diff mbox series

Patch

diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 11b5dbc7a03..b4dd32163af 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -13051,6 +13051,7 @@  static bool
 resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
 {
   gfc_formal_arglist *arg;
+  bool allocatable_or_pointer;
 
   if (sym->attr.function
       && !resolve_fl_var_and_proc (sym, mp_flag))
@@ -13235,8 +13236,16 @@  resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
   /* F2018, C15100: "The result of an elemental function shall be scalar,
      and shall not have the POINTER or ALLOCATABLE attribute."  The scalar
      pointer is tested and caught elsewhere.  */
+  if (sym->result)
+    allocatable_or_pointer = sym->ts.type == BT_CLASS ?
+			     (CLASS_DATA (sym->result)->attr.allocatable
+			      || CLASS_DATA (sym->result)->attr.pointer) :
+			     (sym->result->attr.allocatable
+			      || sym->result->attr.pointer);
+
   if (sym->attr.elemental && sym->result
-      && (sym->result->attr.allocatable || sym->result->attr.pointer))
+      && sym->result->ts.type != BT_CLASS
+      && allocatable_or_pointer)
     {
       gfc_error ("Function result variable %qs at %L of elemental "
 		 "function %qs shall not have an ALLOCATABLE or POINTER "
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index c346183e129..c6725659093 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -1167,8 +1167,11 @@  get_class_info_from_ss (stmtblock_t * pre, gfc_ss *ss, tree *eltype)
       && rhs_ss->info->expr->ts.type == BT_CLASS
       && rhs_ss->info->data.array.descriptor)
     {
-      rhs_class_expr
-	= gfc_get_class_from_expr (rhs_ss->info->data.array.descriptor);
+      if (rhs_ss->info->expr->expr_type != EXPR_VARIABLE)
+	rhs_class_expr
+	  = gfc_get_class_from_expr (rhs_ss->info->data.array.descriptor);
+      else
+	rhs_class_expr = gfc_get_class_from_gfc_expr (rhs_ss->info->expr);
       unlimited_rhs = UNLIMITED_POLY (rhs_ss->info->expr);
       if (rhs_ss->info->expr->expr_type == EXPR_FUNCTION)
 	rhs_function = true;
diff --git a/gcc/testsuite/gfortran.dg/class_assign_4.f90 b/gcc/testsuite/gfortran.dg/class_assign_4.f90
index 517e3121cc8..c6c54bbaed2 100644
--- a/gcc/testsuite/gfortran.dg/class_assign_4.f90
+++ b/gcc/testsuite/gfortran.dg/class_assign_4.f90
@@ -11,17 +11,21 @@  module m
   type :: t1
     integer :: i
   CONTAINS
-    PROCEDURE :: add_t1
-    GENERIC :: OPERATOR(+) => add_t1
+!    PROCEDURE :: add_t1
+!    GENERIC :: OPERATOR(+) => add_t1
   end type
   type, extends(t1) :: t2
     real :: r
   end type
 
+  interface operator(+)
+    module procedure add_t1
+  end interface
+
 contains
-  impure elemental function add_t1 (a, b) result (c)
-    class(t1), intent(in) :: a, b
-    class(t1), allocatable :: c
+  function add_t1 (a, b) result (c)
+    class(t1), intent(in) :: a(:), b(:)
+    class(t1), allocatable :: c(:)
     allocate (c, source = a)
     c%i = a%i + b%i
     select type (c)