Bug 43207 - [OOP] invalid pointer assignment => type%parent
Summary: [OOP] invalid pointer assignment => type%parent
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2010-02-28 08:09 UTC by Tobias Burnus
Modified: 2012-11-08 09:25 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-05-14 17:59:08


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2010-02-28 08:09:17 UTC
gfortran
fff.f90: In function 'foo_child':
fff.f90:26:0: internal compiler error: in gfc_conv_structure, at fortran/trans-expr.c:4390

NAG:
Error: fff.f90, line 29: THIS is neither a POINTER nor a TARGET
       detected at PARENT@<end-of-statement>

IBM:
"Final_test.F90", line 27.20: 1514-648 (S) A structure component
reference must be polymorphic if the rightmost component name is of
abstract type.


 module parent_module
  implicit none

  type ,abstract :: parent
  contains
    procedure :: foo
  end type

contains
  subroutine foo(this)
    class(parent) :: this
    print *,'Inside parent foo'
  end subroutine
end module

module child_module
  use parent_module
  implicit none

  type ,extends(parent) :: child
  contains
    procedure :: foo => foo_child
  end type

contains
  subroutine foo_child(this)
    class(child) :: this
    class(parent) ,pointer :: this_parent=>null()
    this_parent => this%parent  ! <<<<<<<<<<<<
    print *,'Inside child foo'
    call this_parent%foo()
  end subroutine
end module
Comment 1 Tobias Burnus 2010-02-28 10:18:31 UTC
Possibly related:
  implicit none
  type, abstract :: parent
    integer :: i
  end type

  type, extends(parent) :: child
  end type
  type(child) :: c1, c1a
  class(child), allocatable :: c2
  print *, c1%parent%i
  print *, c2%parent%i
  c1a%parent = c1%parent !<<< LHS & RHS invalid
  c1a%parent = c2%parent !<<< LHS invalid
end

Here, c1a%parent and c1%parent is clearly invalid according to C613; for the rest - I don't know. See also PR 43193. It boils down to understand what makes data-ref polymorphic - maybe my renewed interpretation of PR 43193 is wrong and the patch in PR 43193 is still correct?!?

R612  data-ref  is  part-ref % part-ref
R613  part-ref  is  part-name [ ( section-subscript-list ) ]
C611  (R612) If the rightmost part-name is of abstract type, data-ref shall be polymorphic.

If one finally understands what exactly is meant by this, one should add a proper error message to  gfc_match_varspec, which saves one of having the check all over the place.
Comment 2 Tobias Burnus 2010-02-28 22:29:54 UTC
(In reply to comment #1)
> It boils down to understand what makes data-ref polymorphic

Answer: "A polymorphic entity is a data entity that is able to be of differing types during program execution." (F2003, "5.1.1.2 CLASS")

Thus "somethings%class" is valid as this entity can have different types; by contrast, "class%non_class" is not polymorphic as the last part-ref is always of the type of non_class.

 * * *

Thus, one needs to reject:
  ptr => abstract_non_polymorph
  abstract_non_polymorph = something
  something = abstract_non_polymorph
  call fooBar(abstract_non_polymorph)
which can presumably best be done in gfc_match_varspec.
Comment 3 janus 2010-05-13 14:47:02 UTC
(In reply to comment #0)
> fff.f90:26:0: internal compiler error: in gfc_conv_structure, at
> fortran/trans-expr.c:4390

It turns out this ICE is actually due to the NULL() initialization of the class pointer and has nothing to do with the invalid pointer assignment.

Here is a simpler test case:

  implicit none
  type :: parent
  end type
  class(parent) ,pointer :: this => null()
  call foo(this)

contains

  subroutine foo(this)
    class(parent) :: this
  end subroutine

end
Comment 4 janus 2010-05-13 14:55:08 UTC
When removing the NULL initialization in comment #3, the dump shows:

  static struct .class.parent.p this = {.$data=0B};

Zeroing the $data pointer is probably not needed without NULL initialization.

With NULL initialization, both the $data and the $vptr components should be zeroed.
Comment 5 Salvatore Filippone 2010-05-15 07:19:30 UTC
(In reply to comment #4)
> When removing the NULL initialization in comment #3, the dump shows:
> 
>   static struct .class.parent.p this = {.$data=0B};
> 
> Zeroing the $data pointer is probably not needed without NULL initialization.
> 
> With NULL initialization, both the $data and the $vptr components should be
> zeroed.
> 
Wild shot: has this anything to do with 43969? 

Comment 6 janus 2010-05-15 10:21:03 UTC
(In reply to comment #5)
> Wild shot: has this anything to do with 43969? 

Actually I don't think so. At least the patch I posted yesterday does not fix PR43969:

http://gcc.gnu.org/ml/fortran/2010-05/msg00155.html
Comment 7 janus 2010-05-15 13:52:52 UTC
Subject: Bug 43207

Author: janus
Date: Sat May 15 13:52:33 2010
New Revision: 159431

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=159431
Log:
2010-05-15  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/43207
	PR fortran/43969
	* gfortran.h (gfc_class_null_initializer): New prototype.
	* expr.c (gfc_class_null_initializer): New function to build a NULL
	initializer for CLASS pointers.
	* symbol.c (gfc_build_class_symbol): Modify internal naming of class
	containers. Remove default NULL initialization of $data component.
	* trans.c (gfc_allocate_array_with_status): Fix wording of an error 
	message.
	* trans-expr.c (gfc_conv_initializer,gfc_trans_subcomponent_assign):
	Use new function 'gfc_class_null_initializer'.
	* trans-intrinsic.c (gfc_conv_allocated): Handle allocatable scalar
	class variables.


2010-05-15  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/43207
	PR fortran/43969
	* gfortran.dg/class_18.f03: New.
	* gfortran.dg/class_19.f03: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/class_18.f03
    trunk/gcc/testsuite/gfortran.dg/class_19.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/symbol.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/fortran/trans.c
    trunk/gcc/testsuite/ChangeLog

Comment 8 janus 2010-05-15 14:08:17 UTC
r159431 fixes the ICE. Comment #0 is now accepted without an error message.
Comment 9 janus 2012-11-07 22:00:40 UTC
(In reply to comment #8)
> r159431 fixes the ICE. Comment #0 is now accepted without an error message.

With 4.7 and trunk, comment #0 is rejected with:

    this_parent => this%parent  ! <<<<<<<<<<<<
                   1
Error: Pointer assignment target is neither TARGET nor POINTER at (1)


However, comment #1 is still accepted without error message.
Comment 10 janus 2012-11-07 22:26:18 UTC
Here is a draft patch which rejects comment #1:

Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(revision 193296)
+++ gcc/fortran/primary.c	(working copy)
@@ -2104,6 +2104,13 @@ check_substring:
 	}
     }
 
+  /* F03:C611.  */
+  if (primary->ts.type == BT_DERIVED && primary->ts.u.derived->attr.abstract)
+    {
+      gfc_error ("Nonpolymorphic reference to abstract type at %C");
+      return MATCH_ERROR;
+    }
+
   /* F2008, C727.  */
   if (primary->expr_type == EXPR_PPC && gfc_is_coindexed (primary))
     {
Comment 11 janus 2012-11-08 09:25:39 UTC
(In reply to comment #10)
> Here is a draft patch which rejects comment #1:


This shows one testsuite failure:

FAIL: gfortran.dg/abstract_type_3.f03  -O   (test for errors, line 44)
FAIL: gfortran.dg/abstract_type_3.f03  -O  (test for excess errors)


where it correctly triggers on this line:

    arg = again_abst_t () ! { dg-error "Can't construct ABSTRACT type 'again_ab
        1
Error: Nonpolymorphic reference to abstract type at (1)