[J3] surprisingly PURE

Malcolm Cohen malcolm at nag-j.co.jp
Wed Apr 22 01:04:48 EDT 2020

Hi Van,


I agree that it’s likely that there are problems with polymorphism, but it might be better to see if we can fix the straightforward problems first.


Your example actually makes it straightforward to write to a global variable, as it passes a pointer to one in. You need to put something like


before the call to avoid passing in a bad pointer.


(I think we’re all agreed that if a bad pointer is passed in, the fault is the user who did that, not the author of the routine?)


I don’t offhand see a way to constrain the creation of bad pointers via MOLD= in this case, though one could constrain against SELECT TYPE having a type guard that has a dodgy type. I don’t think that would fly, but I thought I should mention it. (It also doesn’t prevent subversion by type-bound procedure invocation, and I don’t think that is doable at all, so a different kind of solution is probably warranted.)


Probably, though I’d need to spend a lot longer thinking about it to be sure, it looks impossible to constrain against all the polymorphic examples, but we can certainly put in a requirement, and we should do so! Something like the MOLD= expression shall not have a type with a default-initialised pointer component with a target outside the subprogram. (Not actual suggested wording there.)


As polymorphic looks harder, and any fix might be more controversial, it might be worth asking as a separate question.


Anyway, lots more to think about here. Thanks for bringing it up.




..............Malcolm Cohen, NAG Oxford/Tokyo.


From: J3 <j3-bounces at mailman.j3-fortran.org> On Behalf Of Van Snyder via J3
Sent: Tuesday, April 21, 2020 12:04 PM
To: General J3 interest list <j3 at mailman.j3-fortran.org>
Cc: Van Snyder <van.snyder at jpl.nasa.gov>
Subject: Re: [J3] surprisingly PURE


On Mon, 2020-04-20 at 21:18 -0400, Vipul Parekh via J3 wrote:

C1589a A local variable of a pure subprogram, or of a BLOCK construct within a pure subprogram, shall not be used in a variable-definition context (19.6.7) if the variable is a derived type where the type has a default-initialized ultimate component at any level of component selection that is a data pointer component and such a data pointer component has an initial-data-target that is not a local variable of the subprogram. 

I don't think this can catch problems related to polymorphism.


program P
  real, target :: X = 1.0
  type :: T1
  end type T1
  type, extends(t1) :: T2
    real, pointer :: P => X
  end type T2
  type(t2) :: V
  print *, 'X =', x
  call s ( v )
  print *, 'X =', x
  pure subroutine S ( A )
    class(T1), intent(in) :: A
    class(T1), allocatable :: Y
    allocate ( Y, mold=A )
    select type ( Y )
    type is ( T2 )
      Y%P = 42.0
    end select
  end subroutine S
end program P

Subroutine S doesn't "have" a local variable of type T2, but it nevertheless assigns a value to X other than by way of its dummy argument, unless you consider it got access to X by way of its dummy argument by default initialization during allocation with MOLD=.

More hammering is maybe necessary. Maybe prohibiting an <associate-name> of such a type to appear in a variable-definition context, if the <selector> is not a dummy argument or subobject thereof, is enough. But even that might not cover all the bases. Or maybe we decide it's OK for S to assign to X by way of Y because Y%P got a pointer to X by way of default initialization during allocation using the dummy argument as the mold.

I tried some things, running on Scientific Linux 6.10 (Carbon):

ifort Build 20190416 gets ICE 101003_17. If I comment out S and the call to it, it doesn't complain,
  but it doesn't do anything interesting.
nagfor 7.0(Yurakucho) Build 7005 says line 6 is invalid
  line 6: X is not permitted in a constant expression
  even with S and the call to it commented out.

Removing the default initialization, adding
  v%p => x
before the first print statement, and changing MOLD= to SOURCE=

nagfor 7.0(Yurakucho) Build 7005 prints
X =   1.0000000
X =  42.0000000

using Y=A instead of allocation with SOURCE= works the same way.

Maybe prohibiting a variable-definition context for a local variable or <selector> of a type with default pointer initialization to a verboten variable isn't enough.  Unless we thing it's OK that S can change X other than by way of A if it got a pointer that is associated with X by way of A, even by way of default initialization during allocation with SOURCE=. If we think that's OK, then maybe there's no problem related to polymorphism. Maybe, or maybe not.

gfortran 8.3.0 on Debian 4.19.98-1 apparently didn't like the type definition:
     real, pointer :: P => X
Error: Bad target in pointer assignment in PURE procedure at (1)
     real, pointer :: P => X
Error: Invalid expression in the structure constructor for pointer component âpâ

It doesn't complain if S is not PURE.

Maybe it saw the type T2 in the select type, and somehow decided it ought to complain about the definition of T2 (which isn't inside the PURE procedure), not the use of it at line 18 (which is inside the PURE procedure).

But there's not a problem with "type is ( T2 )" if the pointer component of the <associate-name> doesn't appear in a variable-definition context.


The Numerical Algorithms Group Ltd is a company registered in England and Wales with company number 1249803. The registered office is: Wilkinson House, Jordan Hill Road, Oxford OX2 8DR, United Kingdom. Please see our  <https://www.nag.co.uk/content/privacy-notice> Privacy Notice for information on how we process personal data and for details of how to stop or limit communications from us.

This e-mail has been scanned for all viruses and malware, and may have been automatically archived by Mimecast Ltd, an innovator in Software as a Service (SaaS) for business.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.j3-fortran.org/pipermail/j3/attachments/20200422/27a89335/attachment-0001.htm>

More information about the J3 mailing list