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 <[email protected]> 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.
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)
class_defined_operator_2.f03
Description: Binary data
