Message ID | CAKwh3qgMxH74fKko6gQd3Y79iAdctWWmTdWYRws6K2=u1eXcPQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | [Fortran,F08] PR 85537: Invalid memory reference at runtime when calling subroutine through procedure pointer | expand |
On Wed, Mar 27, 2019 at 10:35:33PM +0100, Janus Weil wrote: > > the attached patch implements some missing constraints from Fortran > 2008 concerning procedure pointer initialization (cf. the standard > quote in comment #18), thus fixing two accepts-invalid and > ICE-on-invalid problems. > > It regtests cleanly on x86_64-linux-gnu. Ok for trunk? Looks OK to me. Just minor comment. If there are numbered constraints in either F2008 or F2018 for each of the if() conditionals, can you add a comment. Perhaps, something like. /* F2008:C1089. */ > + if (attr.proc == PROC_INTERNAL) > + { > + gfc_error ("Internal procedure %qs is invalid in " > + "procedure pointer initialization at %L", > + rvalue->symtree->name, &rvalue->where); > + return false; > + } /* F2008:C1142. */ > + if (attr.dummy) > + { > + gfc_error ("Dummy procedure %qs is invalid in " > + "procedure pointer initialization at %L", > + rvalue->symtree->name, &rvalue->where); > + return false; > + } > }
Hi Janus, > the attached patch implements some missing constraints from Fortran > 2008 concerning procedure pointer initialization (cf. the standard > quote in comment #18), thus fixing two accepts-invalid and > ICE-on-invalid problems. I do not think this is correct. F2008: # 12.2.2.4 Procedure pointers # A procedure pointer is a procedure that has the EXTERNAL and POINTER # attributes; it may be pointer associated with an external procedure, # # an internal procedure, [...] So a procedure pointer can be associated with an internal procedure. Comment#18 from the PR does not quote anything that says that a procedure pointer cannot be associated with an internal procedure. Also, for clarification, see Note 12.8, which states # An internal procedure cannot be invoked using a procedure pointer from # either Fortran or C after the host instance completes execution, # because the pointer is then undefined. While the host instance is # active, however, the internal procedure may be invoked from outside of # the host procedure scoping unit if that internal procedure was passed # as an actual argument or is the target of a procedure pointer. So, we have to support this. Regards Thomas
Hi Steve, > > the attached patch implements some missing constraints from Fortran > > 2008 concerning procedure pointer initialization (cf. the standard > > quote in comment #18), thus fixing two accepts-invalid and > > ICE-on-invalid problems. > > > > It regtests cleanly on x86_64-linux-gnu. Ok for trunk? > > Looks OK to me. Just minor comment. If there are numbered > constraints in either F2008 or F2018 for each of the if() > conditionals, can you add a comment. I fully agree. Luckily the reference to F08:C1220 is already present in gfc_check_assign_symbol (but unfortunately not visible in the diff), and it applies in the same way to the one IF clause that is already there as well as the two new ones I'm adding, which is why I'm not putting in an additional reference. Cheers, Janus
Hi Thomas, > > the attached patch implements some missing constraints from Fortran > > 2008 concerning procedure pointer initialization (cf. the standard > > quote in comment #18), thus fixing two accepts-invalid and > > ICE-on-invalid problems. > > I do not think this is correct. > > F2008: > > # 12.2.2.4 Procedure pointers > > # A procedure pointer is a procedure that has the EXTERNAL and POINTER > # attributes; it may be pointer associated with an external procedure, # > # an internal procedure, [...] > > So a procedure pointer can be associated with an internal procedure. > > Comment#18 from the PR does not quote anything that says that > a procedure pointer cannot be associated with an internal procedure. Absolutely, a procedure pointer can in principle be associated with an internal procedure, and my patch does not change that. What the patch rejects is the ('static' in the C sense) pointer initialization of a procedure pointer with an internal procedure, which is forbidden per F2008:C1220. procedure(..), pointer :: pp => internal_proc A normal pointer assignment is still allowed per F2008:C729: pp => internal_proc Hope you agree (and sorry for not being more verbose in my explanation in the first place). Cheers, Janus
On Wed, Mar 27, 2019 at 11:12:38PM +0100, Janus Weil wrote: > Hi Steve, > > > > the attached patch implements some missing constraints from Fortran > > > 2008 concerning procedure pointer initialization (cf. the standard > > > quote in comment #18), thus fixing two accepts-invalid and > > > ICE-on-invalid problems. > > > > > > It regtests cleanly on x86_64-linux-gnu. Ok for trunk? > > > > Looks OK to me. Just minor comment. If there are numbered > > constraints in either F2008 or F2018 for each of the if() > > conditionals, can you add a comment. > > I fully agree. Luckily the reference to F08:C1220 is already present > in gfc_check_assign_symbol (but unfortunately not visible in the > diff), and it applies in the same way to the one IF clause that is > already there as well as the two new ones I'm adding, which is why I'm > not putting in an additional reference. > Ah, ok. Thanks for the reply.
On Wed, Mar 27, 2019 at 11:22:49PM +0100, Janus Weil wrote: > > > > the attached patch implements some missing constraints from Fortran > > > 2008 concerning procedure pointer initialization (cf. the standard > > > quote in comment #18), thus fixing two accepts-invalid and > > > ICE-on-invalid problems. > > > > I do not think this is correct. > > > > F2008: > > > > # 12.2.2.4 Procedure pointers > > > > # A procedure pointer is a procedure that has the EXTERNAL and POINTER > > # attributes; it may be pointer associated with an external procedure, # > > # an internal procedure, [...] > > > > So a procedure pointer can be associated with an internal procedure. > > > > Comment#18 from the PR does not quote anything that says that > > a procedure pointer cannot be associated with an internal procedure. > > Absolutely, a procedure pointer can in principle be associated with an > internal procedure, and my patch does not change that. What the patch > rejects is the ('static' in the C sense) pointer initialization of a > procedure pointer with an internal procedure, which is forbidden per > F2008:C1220. > > procedure(..), pointer :: pp => internal_proc > > A normal pointer assignment is still allowed per F2008:C729: > > pp => internal_proc > > Hope you agree (and sorry for not being more verbose in my explanation > in the first place). > Just to add to the confusion/clarification. Janus's patch is concerned with an initial-proc-target, which is has restriction that do not apply to a proc-target.
Am 27.03.19 um 22:54 schrieb Thomas Koenig:
> I do not think this is correct.
... and I missed the point that this was specifically about
initializations.
So, OK from my side. Thanks!
Regards
Thomas
Am Mi., 27. März 2019 um 23:32 Uhr schrieb Thomas Koenig <tkoenig@netcologne.de>: > > Am 27.03.19 um 22:54 schrieb Thomas Koenig: > > I do not think this is correct. > > ... and I missed the point that this was specifically about > initializations. > > So, OK from my side. Thanks! Great. Thanks for the reviews, everyone! Committed to trunk as r269980. Cheers, Janus
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e1fdb93f3d0..372c517487f 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2019-03-27 Janus Weil <janus@gcc.gnu.org> + + PR fortran/85537 + * expr.c (gfc_check_assign_symbol): Reject internal and dummy procedures + in procedure pointer initialization. + 2019-03-27 Paul Thomas <pault@gcc.gnu.org> PR fortran/88247 diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index f54affae18d..478a5557723 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -4407,6 +4407,20 @@ gfc_check_assign_symbol (gfc_symbol *sym, gfc_component *comp, gfc_expr *rvalue) "may not be a procedure pointer", &rvalue->where); return false; } + if (attr.proc == PROC_INTERNAL) + { + gfc_error ("Internal procedure %qs is invalid in " + "procedure pointer initialization at %L", + rvalue->symtree->name, &rvalue->where); + return false; + } + if (attr.dummy) + { + gfc_error ("Dummy procedure %qs is invalid in " + "procedure pointer initialization at %L", + rvalue->symtree->name, &rvalue->where); + return false; + } } return true; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0679cb72e52..f6df0b1281c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-03-27 Janus Weil <janus@gcc.gnu.org> + + PR fortran/85537 + * gfortran.dg/dummy_procedure_11.f90: Fix test case. + * gfortran.dg/pointer_init_11.f90: New test case. + 2019-03-27 Richard Biener <rguenther@suse.de> * gcc.dg/torture/20190327-1.c: New testcase. diff --git a/gcc/testsuite/gfortran.dg/dummy_procedure_11.f90 b/gcc/testsuite/gfortran.dg/dummy_procedure_11.f90 index f51c5455c05..3e4b2b1d6f0 100644 --- a/gcc/testsuite/gfortran.dg/dummy_procedure_11.f90 +++ b/gcc/testsuite/gfortran.dg/dummy_procedure_11.f90 @@ -5,16 +5,18 @@ ! Contributed by Vladimir Fuka <vladimir.fuka@gmail.com> type :: t - procedure(g), pointer, nopass :: ppc => g + procedure(g), pointer, nopass :: ppc end type -procedure(g), pointer :: pp => g +procedure(g), pointer :: pp type(t)::x print *, f(g) print *, f(g()) ! { dg-error "Expected a procedure for argument" } +pp => g print *, f(pp) print *, f(pp()) ! { dg-error "Expected a procedure for argument" } +x%ppc => g print *, f(x%ppc) print *, f(x%ppc()) ! { dg-error "Expected a procedure for argument" } diff --git a/gcc/testsuite/gfortran.dg/pointer_init_11.f90 b/gcc/testsuite/gfortran.dg/pointer_init_11.f90 new file mode 100644 index 00000000000..3113e157687 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pointer_init_11.f90 @@ -0,0 +1,44 @@ +! { dg-do compile } +! +! PR 85537: [F08] Invalid memory reference at runtime when calling subroutine through procedure pointer +! +! Contributed by Tiziano Müller <dev-zero@gentoo.org> + +module m1 + implicit none +contains + subroutine foo() + integer :: a + + abstract interface + subroutine ibar() + end subroutine + end interface + + procedure(ibar), pointer :: bar_ptr => bar_impl ! { dg-error "invalid in procedure pointer initialization" } + + contains + subroutine bar_impl() + write (*,*) "foo" + a = a + 1 + end subroutine + + end subroutine +end module + + +module m2 + implicit none +contains + subroutine foo(dbar) + interface + subroutine dbar() + end subroutine + end interface + + procedure(dbar), pointer :: bar_ptr => dbar ! { dg-error "invalid in procedure pointer initialization" } + + call bar_ptr() + + end subroutine +end module