[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2016-11-16 Thread janus at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261

janus at gcc dot gnu.org changed:

   What|Removed |Added

   Target Milestone|--- |4.9.0

[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-04-12 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



janus at gcc dot gnu.org changed:



   What|Removed |Added



 Status|ASSIGNED|RESOLVED

 Resolution||FIXED



--- Comment #14 from janus at gcc dot gnu.org 2013-04-12 14:32:30 UTC ---

Fixed with r197922, which rejects the test cases in comment 0 and 1:



http://gcc.gnu.org/viewcvs/gcc?view=revision&revision=197922





Author: janus

Date: Fri Apr 12 14:21:39 2013 UTC

Changed paths: 23

Log Message: 



2013-04-12  Janus Weil  



PR fortran/56261

* gfortran.h (gfc_explicit_interface_required): New prototype.

* expr.c (gfc_check_pointer_assign): Check if an explicit interface is

required in a proc-ptr assignment.

* interface.c (check_result_characteristics): Extra check.

* resolve.c (gfc_explicit_interface_required): New function.

(resolve_global_procedure): Use new function

'gfc_explicit_interface_required'. Do a full interface check.





2013-04-12  Janus Weil  



PR fortran/56261

* gfortran.dg/auto_char_len_4.f90: Add -pedantic. Changed error.

* gfortran.dg/assumed_rank_4.f90: Modified error wording.

* gfortran.dg/block_11.f90: Fix invalid test case.

* gfortran.dg/function_types_3.f90: Add new error message.

* gfortran.dg/global_references_1.f90: Ditto.

* gfortran.dg/import2.f90: Remove unneeded parts.

* gfortran.dg/import6.f90: Fix invalid test case.

* gfortran.dg/proc_decl_2.f90: Ditto.

* gfortran.dg/proc_decl_9.f90: Ditto.

* gfortran.dg/proc_decl_18.f90: Ditto.

* gfortran.dg/proc_ptr_40.f90: New.

* gfortran.dg/whole_file_7.f90: Modified error wording.

* gfortran.dg/whole_file_16.f90: Ditto.

* gfortran.dg/whole_file_17.f90: Add -pedantic.

* gfortran.dg/whole_file_18.f90: Modified error wording.

* gfortran.dg/whole_file_20.f03: Ditto.

* gfortran.fortran-torture/execute/intrinsic_associated.f90: Fix

invalid test case.





Closing as fixed. Thanks for the report.


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-04-08 Thread burnus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



Tobias Burnus  changed:



   What|Removed |Added



 CC||burnus at gcc dot gnu.org



--- Comment #13 from Tobias Burnus  2013-04-08 
08:11:44 UTC ---

(See also thread ending with

http://gcc.gnu.org/ml/fortran/2013-04/msg00048.html)



Regarding comment 1, using



  procedure(  ), pointer :: f => ff



as well as something like



  external :: ggg

  procedure(ff), pointer :: f => ggg



is invalid as "ff" has a class dummy argument, which mandates an explicit

interface (F2008, 12.4.2.2, (2)(a); cf. comment 6) and Fortran 2008 demands:



"If the characteristics of the pointer object or the pointer target are such

that an explicit interface is required, both the pointer object and the pointer

target shall have an explicit interface." (para 4 of "7.2.2.4 Procedure pointer

assignment")





[Those aren't constraints, hence, the compiler is not required to diagnose it -

nor can it do so in general. However, if the explicit interface of "ff" is

available, as comment 1, it can. Thus, a diagnostic would be nice.]


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #12 from janus at gcc dot gnu.org 2013-02-09 18:25:33 UTC ---

I just noticed that there is already related diagnostics in resolve.c

(resolve_global_procedure):



/* F2003, 12.3.1.1 (2d); F2008, 12.4.2.2 (2e)   */

else if (arg->sym->ts.type == BT_CLASS)

  {

gfc_error ("Procedure '%s' at %L with polymorphic dummy "

   "argument '%s' must have an explicit interface",

   sym->name, &sym->declared_at, arg->sym->name);

break;

  }



As a consequnce, whole_file_20.f03 now fails (due to a double error message).



Further, abstract_type_6.f03 fails, which is fixed by this:



Index: abstract_type_6.f03

===

--- abstract_type_6.f03 (revision 195915)

+++ abstract_type_6.f03 (working copy)

@@ -46,7 +46,7 @@



 SUBROUTINE bottom_c(obj)

CLASS(Bottom) :: obj

-   CALL top_c(obj)

+   CALL top_c(obj)   ! { dg-error "requires an explicit interface" }

! other stuff

 END SUBROUTINE bottom_c 

 end module


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread abensonca at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #11 from Andrew Benson  2013-02-09 
17:06:18 UTC ---

Thanks for figuring out the problem here. When I specify an interface for the

procedure pointer in the original code that I derived the test case from,

everything works OK.


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread abensonca at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #10 from Andrew Benson  2013-02-09 
17:01:22 UTC ---

You're right - comment 1.


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #9 from janus at gcc dot gnu.org 2013-02-09 16:58:54 UTC ---

(In reply to comment #8)

> On the test case in comment 2,



comment 1?





> ifort v11.1 reports:

> 

> > ifort -o bug.exe bug.F90 

> bug.F90(23): error #6592: This symbol must be a defined parameter, an

> enumerator, or an argument of an inquiry function that evaluates to a

> compile-time constant.   [FF]

>   procedure(  ), pointer   :: f => ff

> ---^

> bug.F90(23): error #6973: This is not a valid initialization expression.   
> [FF]

>   procedure(  ), pointer   :: f => ff

> ---^

> compilation aborted for bug.F90 (code 1)

> 

> Same for the scalar case.



Thanks for checking. Probably ifort does not support pointer initialization yet

(which is a F08 feature).





> Interestingly, the workaround doesn't work under ifort - it seems not to like:

> 

>   procedure(ff), pointer :: f => ff

> 

> but instead needs:

> 

>   procedure(ff), pointer :: f

>   f => ff



Again, pointer initialization.





> In fact, if I use:

> 

>   procedure(), pointer :: f

>   f => ff

> 

> then it compiles without any warnings/errors but segfaults at runtime.

> 

> With:

> 

> 

>   procedure(ff), pointer :: f

>   f => ff

> 

> it compiles and runs as expected.



Good, that's compatible with gfortran's behavior (which is fine, since the test

case is invalid). Apparently ifort also lacks diagnostics for this.


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread abensonca at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #8 from Andrew Benson  2013-02-09 
16:50:54 UTC ---

On the test case in comment 2, ifort v11.1 reports:



> ifort -o bug.exe bug.F90 

bug.F90(23): error #6592: This symbol must be a defined parameter, an

enumerator, or an argument of an inquiry function that evaluates to a

compile-time constant.   [FF]

  procedure(  ), pointer   :: f => ff

---^

bug.F90(23): error #6973: This is not a valid initialization expression.   [FF]

  procedure(  ), pointer   :: f => ff

---^

compilation aborted for bug.F90 (code 1)



Same for the scalar case.



Interestingly, the workaround doesn't work under ifort - it seems not to like:



  procedure(ff), pointer :: f => ff



but instead needs:



  procedure(ff), pointer :: f

  f => ff



In fact, if I use:



  procedure(), pointer :: f

  f => ff



then it compiles without any warnings/errors but segfaults at runtime.



With:





  procedure(ff), pointer :: f

  f => ff



it compiles and runs as expected.


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



janus at gcc dot gnu.org changed:



   What|Removed |Added



 Status|NEW |ASSIGNED

 AssignedTo|unassigned at gcc dot   |janus at gcc dot gnu.org

   |gnu.org |



--- Comment #7 from janus at gcc dot gnu.org 2013-02-09 15:52:55 UTC ---

Here is a patch which rejects comment 0 and 1:



Index: gcc/fortran/interface.c

===

--- gcc/fortran/interface.c(revision 195915)

+++ gcc/fortran/interface.c(working copy)

@@ -3202,6 +3202,13 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arg

  "at %L", &a->expr->where);

   return FAILURE;

 }

+

+  if (a->expr && a->expr->ts.type == BT_CLASS)

+{

+  gfc_error ("Polymorphic argument requires an explicit interface "

+ "at %L", &a->expr->where);

+  return FAILURE;

+}

 }



   return SUCCESS;





I think it's ok to throw an error (and not just a warning), because a

polymorphic actual arg can only be passed to a polymorphic formal arg, which is

invalid in connection with an implicit interface.


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



janus at gcc dot gnu.org changed:



   What|Removed |Added



 Status|UNCONFIRMED |NEW

   Last reconfirmed||2013-02-09

 Ever Confirmed|0   |1



--- Comment #6 from janus at gcc dot gnu.org 2013-02-09 15:30:13 UTC ---

(In reply to comment #5)

> I sincerely hope that all the test cases in this PR are invalud. One should

> check the standard!



Whew, good luck:



F08, chapter 12.4.2.2:

A procedure other than a statement function shall have an explicit interface if

it is referenced and

(1) a reference to the procedure appears

(a) with an argument keyword (12.5.2), or

(b) in a context that requires it to be pure,

(2) the procedure has a dummy argument that

(a) has the ALLOCATABLE, [...] attribute,

(b) is an assumed-shape array,

(c) is a coarray,

(d) is of a parameterized derived type, or

(e) is polymorphic,





It seems this is not something that the compiler is required to diagnose

(probably because that can be hard or impossible in certain cases), but the

programmer is responsible for checking this.



For comment 1, we should probably throw a warning (at least), but for comment 4

and 5 there is not much we can do, I guess.



In general I would advise against using procedure pointers without interface

(and EXTERNAL declarations), in particular in OOP code (but also in other

cases, because the compiler cannot do any type checking of the arguments, etc).





In summary: All test cases shown here are invalid, the compiler is not strictly

required to detect this, but we should at least throw a warning where possible

(e.g. comment 0 and 1).


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #5 from janus at gcc dot gnu.org 2013-02-09 10:17:16 UTC ---

One can play the same game with scalars, where the situation is even more

severe:



module t



  type :: nc

 integer :: n = 1

  end type nc



contains



  subroutine ff(self)

implicit none

class(nc), intent(in) :: self

write (0,*) '  --> content of self%n) is ',self%n

  end subroutine



end module t



program p

  use t

  implicit none

  type(nc) :: c

  procedure(), pointer   :: f => ff



  call ff(c)

  call f(c)



end program p





The dump shows:



  {

struct __class_t_Nc class.1;



class.1._vptr = (struct __vtype_t_Nc * {ref-all}) &__vtab_t_Nc;

class.1._data = &c;

ff (&class.1);

  }

  f (&c);



i.e. we set up a polymorphic temporary for the 'ff' call, which we don't do for

'f' since we don't know that it expects a CLASS argument.



Fixing this for the array case would be possible, if we just use the

'polymorphic' version of the array descriptor everywhere.



In the scalar case, we would have to set up a class container, for every call

to a procedure pointer without interface, which is passed a TYPE or CLASS

argument. This would then in turn mean we have to wrap the argument of the

original function 'ff' in a class container, even if it is TYPE. AFAICS, this

could even mean we need an class container (or array descriptor) for *every*

TYPE(t) variable, which would be a rather dramatic change in implementation

(and in principle also affects pure F95 code).



I sincerely hope that all the test cases in this PR are invalud. One should

check the standard!



Btw, do other compilers handle this stuff?


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #4 from janus at gcc dot gnu.org 2013-02-09 10:08:23 UTC ---

Actually I wonder whether the test case is really valid. The problem is: When

declaring the procedure pointer without an interface, we don't know which kind

of argument it expects. Here is a slightly modified variant:



module t



  type :: nc

 integer :: n = 1

  end type nc



contains



  subroutine ff(self)

implicit none

class(nc), intent(in), dimension(:) :: self

write (0,*) '  --> content of self(1)%n) is ',self(1)%n

  end subroutine



end module t



program p

  use t

  implicit none

  type(nc), dimension(1:10) :: c

  procedure(), pointer   :: f => ff



  call ff(c)

  call f(c)



end program p





As the dump shows, we set up a different array descriptor for both cases, since

we don't know that the procedure pointer expects a polymorphic argument:



  {

struct array1_nc parm.2;

struct __class_t_Nc_1_0 class.1;



class.1._vptr = (struct __vtype_t_Nc * {ref-all}) &__vtab_t_Nc;

parm.2.dtype = 297;

parm.2.dim[0].lbound = 1;

parm.2.dim[0].ubound = 10;

parm.2.dim[0].stride = 1;

parm.2.data = (void *) &c[0];

parm.2.offset = -1;

class.1._data = parm.2;

ff (&class.1);

  }

  {

struct array1_nc parm.3;



parm.3.dtype = 297;

parm.3.dim[0].lbound = 1;

parm.3.dim[0].ubound = 10;

parm.3.dim[0].stride = 1;

parm.3.data = (void *) &c[0];

parm.3.offset = -1;

f ((struct nc[0:] *) parm.3.data);

  }


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



--- Comment #3 from janus at gcc dot gnu.org 2013-02-09 10:03:06 UTC ---

Fortunately there is a simple workaround: Declaring the procedure pointer as



  procedure(ff), pointer   :: f => ff



makes the segfault go away. The call is then done in the same way as the direct

call to 'ff':



{

  struct __class_t_Nc_1_0 class.2;



  class.2._data = VIEW_CONVERT_EXPR(c._data);

  class.2._vptr = c._vptr;

  f (&class.2);

}


[Bug fortran/56261] [OOP] seg fault call procedure pointer on polymorphic array

2013-02-09 Thread janus at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56261



janus at gcc dot gnu.org changed:



   What|Removed |Added



   Keywords||wrong-code

 CC||janus at gcc dot gnu.org

Summary|seg fault call procedure|[OOP] seg fault call

   |pointer on polymorphic  |procedure pointer on

   |array   |polymorphic array



--- Comment #2 from janus at gcc dot gnu.org 2013-02-09 09:52:54 UTC ---

(In reply to comment #1)

>   allocate(c(10))

>   call f(c)



Adding in here a call to "ff(c)", the dump reveals the difference between the

two calls:





  static struct __class_t_Nc_1_0a c = {};

  static void (*) () f = ff;



[..]

__builtin_memset (c._data.data, 0, 40);

c._data.dtype = 297;

c._data.dim[0].lbound = 1;

c._data.dim[0].ubound = 10;

c._data.dim[0].stride = 1;

c._data.offset = -1;

(struct __vtype_t_Nc *) c._vptr = &__vtab_t_Nc;



{

  struct __class_t_Nc_1_0 class.2;



  class.2._data = VIEW_CONVERT_EXPR(c._data);

  class.2._vptr = c._vptr;

  ff (&class.2);

}



f ((struct nc[0:] * restrict) c._data.data);





The first part simply sets up the array descriptor for c after the allocation.

Then comes the call to 'ff' (in curly brackets), which is done correctly

(although I'm not quite sure why the temporary 'class.2' is needed). In the

call to 'f', we wrongly pass c._data.data, while we should rather pass 'c' as a

whole (or with a temporary as in the 'ff' case?).