Hi all,

after committing my recent patch for PR 64209, I realized that the
accompanying test case is actually invalid in one aspect and that
there is already a PR (and patch) for that problem: PR 54756. It's
about F08 forbidding polymorphic INTENT(OUT) arguments in pure
procedures. The reason for this restriction is essentially that a
finalizer (if present) would need to be called for such an argument,
and the finalizer could be impure (which in general can not be checked
at compile time). The constraint technically only exists in F08 and
not in F03, but my patch unconditionally rejects such code.

In fact the patch uncovered a good number of cases in the testsuite,
which are invalid in this respect. I fixed all of them by making the
encompassing procedure impure. After that the patch regtests cleanly.
Ok for trunk?

Cheers,
Janus


2014-12-19  Janus Weil  <ja...@gcc.gnu.org>

    PR fortran/54756
    * resolve.c (resolve_formal_arglist): Reject polymorphic INTENT(OUT)
    arguments of pure procedures.

2014-12-19  Janus Weil  <ja...@gcc.gnu.org>

    PR fortran/54756
    * gfortran.dg/class_array_3.f03: Fixed invalid test case.
    * gfortran.dg/class_array_7.f03: Ditto.
    * gfortran.dg/class_dummy_4.f03: Ditto.
    * gfortran.dg/defined_assignment_3.f90: Ditto.
    * gfortran.dg/defined_assignment_5.f90: Ditto.
    * gfortran.dg/elemental_subroutine_10.f90: Ditto.
    * gfortran.dg/typebound_operator_4.f03: Ditto.
    * gfortran.dg/typebound_proc_16.f03: Ditto.
    * gfortran.dg/unlimited_polymorphic_19.f90: Ditto.
    * gfortran.dg/class_dummy_5.f90: New test.
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c       (Revision 218978)
+++ gcc/fortran/resolve.c       (Arbeitskopie)
@@ -414,6 +414,15 @@ resolve_formal_arglist (gfc_symbol *proc)
                               &sym->declared_at);
                }
            }
+
+         /* F08:C1278a.  */
+         if (sym->ts.type == BT_CLASS && sym->attr.intent == INTENT_OUT)
+           {
+             gfc_error ("INTENT(OUT) argument '%s' of pure procedure %qs at %L"
+                        " may not be polymorphic", sym->name, proc->name,
+                        &sym->declared_at);
+             continue;
+           }
        }
 
       if (proc->attr.implicit_pure)
Index: gcc/testsuite/gfortran.dg/class_array_3.f03
===================================================================
--- gcc/testsuite/gfortran.dg/class_array_3.f03 (Revision 218978)
+++ gcc/testsuite/gfortran.dg/class_array_3.f03 (Arbeitskopie)
@@ -29,7 +29,7 @@ module m_qsort
    end function lt_cmp
  end interface
  interface
-   elemental subroutine assign(a,b)
+   impure elemental subroutine assign(a,b)
      import
      class(sort_t), intent(out) :: a
      class(sort_t), intent(in) :: b
@@ -100,7 +100,7 @@ contains
      class(sort_int_t), intent(in) :: a
      disp_int = a%i
  end function disp_int
- elemental subroutine assign_int (a, b)
+ impure elemental subroutine assign_int (a, b)
    class(sort_int_t), intent(out) :: a
    class(sort_t), intent(in) :: b         ! TODO: gfortran does not throw 
'class(sort_int_t)'
    select type (b)
Index: gcc/testsuite/gfortran.dg/class_array_7.f03
===================================================================
--- gcc/testsuite/gfortran.dg/class_array_7.f03 (Revision 218978)
+++ gcc/testsuite/gfortran.dg/class_array_7.f03 (Arbeitskopie)
@@ -19,7 +19,7 @@ module realloc
 
 contains
 
-  elemental subroutine assign (a, b)
+  impure elemental subroutine assign (a, b)
     class(base_type), intent(out) :: a
     type(base_type), intent(in) :: b
     a%i = b%i
Index: gcc/testsuite/gfortran.dg/class_dummy_4.f03
===================================================================
--- gcc/testsuite/gfortran.dg/class_dummy_4.f03 (Revision 218978)
+++ gcc/testsuite/gfortran.dg/class_dummy_4.f03 (Arbeitskopie)
@@ -11,7 +11,7 @@ module m1
   procedure, pass(x) :: source
  end type c_stv
 contains
- pure subroutine source(y,x)
+ subroutine source(y,x)
   class(c_stv), intent(in)               :: x
   class(c_stv), allocatable, intent(out) :: y
  end subroutine source
Index: gcc/testsuite/gfortran.dg/defined_assignment_3.f90
===================================================================
--- gcc/testsuite/gfortran.dg/defined_assignment_3.f90  (Revision 218978)
+++ gcc/testsuite/gfortran.dg/defined_assignment_3.f90  (Arbeitskopie)
@@ -17,7 +17,7 @@ module m0
     integer :: j
   end type
 contains
-  elemental subroutine assign0(lhs,rhs)
+  impure elemental subroutine assign0(lhs,rhs)
     class(component), intent(out) :: lhs
     class(component), intent(in) :: rhs
     lhs%i = 20
Index: gcc/testsuite/gfortran.dg/defined_assignment_5.f90
===================================================================
--- gcc/testsuite/gfortran.dg/defined_assignment_5.f90  (Revision 218978)
+++ gcc/testsuite/gfortran.dg/defined_assignment_5.f90  (Arbeitskopie)
@@ -38,7 +38,7 @@ module m1
     integer :: j = 7
   end type
 contains
-  elemental subroutine assign1(lhs,rhs)
+  impure elemental subroutine assign1(lhs,rhs)
     class(component1), intent(out) :: lhs
     class(component1), intent(in) :: rhs
     lhs%i = 30
Index: gcc/testsuite/gfortran.dg/elemental_subroutine_10.f90
===================================================================
--- gcc/testsuite/gfortran.dg/elemental_subroutine_10.f90       (Revision 
218978)
+++ gcc/testsuite/gfortran.dg/elemental_subroutine_10.f90       (Arbeitskopie)
@@ -15,7 +15,7 @@ module m_assertion_character
     procedure :: write => assertion_array_write
   end type t_assertion_character
 contains
-  elemental subroutine assertion_character( ast, name )
+  impure elemental subroutine assertion_character( ast, name )
     class(t_assertion_character), intent(out) :: ast
     character(len=*), intent(in) :: name
     ast%name = name
@@ -37,7 +37,7 @@ module m_assertion_array_character
     procedure :: write => assertion_array_character_write
   end type t_assertion_array_character
 contains
-  pure subroutine assertion_array_character( ast, name, nast )
+  subroutine assertion_array_character( ast, name, nast )
     class(t_assertion_array_character), intent(out) :: ast
     character(len=*), intent(in) :: name
     integer, intent(in) :: nast
Index: gcc/testsuite/gfortran.dg/typebound_operator_4.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_operator_4.f03  (Revision 218978)
+++ gcc/testsuite/gfortran.dg/typebound_operator_4.f03  (Arbeitskopie)
@@ -34,7 +34,7 @@ CONTAINS
     add_int = myint (a%value + b)
   END FUNCTION add_int
 
-  PURE SUBROUTINE assign_int (dest, from)
+  SUBROUTINE assign_int (dest, from)
     CLASS(myint), INTENT(OUT) :: dest
     INTEGER, INTENT(IN) :: from
     dest%value = from
@@ -62,7 +62,6 @@ CONTAINS
   PURE SUBROUTINE iampure ()
     TYPE(myint) :: x
 
-    x = 0 ! { dg-bogus "is not PURE" }
     x = x + 42 ! { dg-bogus "to a impure procedure" }
     x = x .PLUS. 5 ! { dg-bogus "to a impure procedure" }
   END SUBROUTINE iampure
Index: gcc/testsuite/gfortran.dg/typebound_proc_16.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_proc_16.f03     (Revision 218978)
+++ gcc/testsuite/gfortran.dg/typebound_proc_16.f03     (Arbeitskopie)
@@ -27,7 +27,7 @@ MODULE rational_numbers
       r = REAL(this%n)/this%d
     END FUNCTION
 
-    ELEMENTAL SUBROUTINE rat_asgn_i(a,b)
+    impure ELEMENTAL SUBROUTINE rat_asgn_i(a,b)
       CLASS(rational),INTENT(OUT) :: a
       INTEGER,INTENT(IN) :: b
       a%n = b
Index: gcc/testsuite/gfortran.dg/unlimited_polymorphic_19.f90
===================================================================
--- gcc/testsuite/gfortran.dg/unlimited_polymorphic_19.f90      (Revision 
218978)
+++ gcc/testsuite/gfortran.dg/unlimited_polymorphic_19.f90      (Arbeitskopie)
@@ -12,7 +12,7 @@ MODULE m
     PROCEDURE :: copy
   END TYPE t
   INTERFACE 
-    PURE SUBROUTINE copy_proc_intr(a,b)
+    SUBROUTINE copy_proc_intr(a,b)
       CLASS(*), INTENT(IN) :: a
       CLASS(*), INTENT(OUT) :: b
     END SUBROUTINE copy_proc_intr
@@ -40,7 +40,7 @@ PROGRAM main
   CALL test%copy(copy_int,copy_x)
 !   PRINT '(*(I0,:2X))', copy_x
 CONTAINS
-  PURE SUBROUTINE copy_int(a,b)
+  SUBROUTINE copy_int(a,b)
     CLASS(*), INTENT(IN) :: a
     CLASS(*), INTENT(OUT) :: b
     SELECT TYPE(a); TYPE IS(integer) 
! { dg-do compile }
!
! PR 54756: [OOP] [F08] Should reject CLASS, intent(out) in PURE procedures
!
! Contributed by Tobias Burnus <bur...@gcc.gnu.org>

module m
  type t
  contains
    final :: fnl   ! impure finalizer
  end type t
contains
  impure subroutine fnl(x)
    type(t) :: x
    print *,"finalized!"
  end subroutine
end

program test
  use m
  type(t) :: x
  call foo(x)
contains
  pure subroutine foo(x)  ! { dg-error "may not be polymorphic" }
    ! pure subroutine would call impure finalizer
    class(t), intent(out) :: x
  end subroutine
end

! { dg-final { cleanup-modules "m" } }

Reply via email to