* Overriding intrinsic operators @ 2021-01-01 16:14 Paul Richard Thomas [not found] ` <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com> 0 siblings, 1 reply; 4+ messages in thread From: Paul Richard Thomas @ 2021-01-01 16:14 UTC (permalink / raw) To: fortran; +Cc: Steve Lionel [-- Attachment #1: Type: text/plain, Size: 1829 bytes --] Hi All, Happy New Year! I took an interest in a recent clf thread, entitled "comparison between class(*) instances", and submitted an example of a possible implementation. I have attached a reduced version of it. gfortran, back as far as version 7.4.1, gives the expected output: a & b are type pvar T a & b are type pvar F ifort (IFORT) 2021.1 Beta 20201112 gives: a & b are type pvar class default: returning false class default: returning false F a & b are type pvar class default: returning false class default: returning false F This comes about because ifort is using the defined operation to override the intrinsic uses of the operator as defined in 10.1.5 of the standard. I believe that gfortran has this one right, since the first paragraph of 15.4.3.4.2 Defined operations has: "...If the operator is an intrinsic-operator (R608), the number of dummy arguments shall be consistent with the intrinsic uses of that operator, and the types, kind type parameters, or ranks of the dummy arguments shall differ from those required for the intrinsic operation (10.1.5)." ifort gives the expected result if the interface is moved to the main program. Steve, I would be grateful if you would pass this on because my Intel uid seems to have expired. Of course, your thoughts would be welcome. The second attachment does away with the select type constructs by transferring the unlimited polymorphic payloads to deferred length characters and comparing them. The use of unlimited polymorphic actual arguments is leading to invalid reads and the loss of 8 bytes in two blocks because realloc is being finickity about the casting of the arguments. Also, when u and v carry strings, both storage_size and transfer fail because the _len field is not used. I will raise PRs on these issues tomorrow. Regards Paul [-- Attachment #2: equals4.f90 --] [-- Type: text/x-fortran, Size: 1086 bytes --] MODULE mytypes IMPLICIT none TYPE pvar character(len=20) :: name integer :: level end TYPE pvar interface operator (==) module procedure pvar_eq end interface contains function pvar_eq(a,b) implicit none class(*), intent(in) ::a,b logical ::pvar_eq if (.not. same_type_as (a, b)) then pvar_eq = .false. return end if select type (a) type is (pvar) select type (b) type is (pvar) print *, "a & b are type pvar" if((a%level.eq. b%level) .and. (a%name .eq. b%name)) then pvar_eq = .true. else pvar_eq = .false. end if end select class default print *, "class default: returning false" pvar_eq = .false. end select end function pvar_eq end MODULE mytypes program test_eq use mytypes implicit none type(pvar) x, y x = pvar('test 1', 100) y = pvar('test 1', 100) write(*, *) x == y x = pvar('test 1', 100) y = pvar('test 2', 100) write(*, *) x == y end program test_eq [-- Attachment #3: equals5.f90 --] [-- Type: text/x-fortran, Size: 1156 bytes --] MODULE mytypes IMPLICIT none TYPE pvar character(len=20) :: name integer :: level end TYPE pvar interface operator (==) module procedure star_eq end interface contains function star_eq(a,b) implicit none class(*), intent(in) ::a,b character(len=:), allocatable :: c1, c2 logical ::star_eq integer(8) :: sza, szb star_eq = same_type_as (a, b) if (.not. star_eq) return sza = storage_size (a)/8 szb = storage_size (b)/8 if (sza .ne. szb) then star_eq = .false. else allocate(character(len = sza) :: c1) allocate(character(len = szb) :: c2) c1 = transfer (a, c1) c2 = transfer (b, c2) star_eq = c1 .eq. c2 end if end function star_eq end MODULE mytypes program test_eq use mytypes implicit none type(pvar) :: x, y class(*), allocatable :: u, v x = pvar('test 1', 100) y = pvar('test 1', 100) write(*, *) x == y u = pvar('test 1', 100) v = pvar('test 2', 100) write(*, *) u == v u = 1.0_4 v = 2.0_4 write(*, *) u == v v = 1.0_4 write(*, *) u == v deallocate (u,v) end program test_eq ^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com>]
* Re: Overriding intrinsic operators [not found] ` <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com> @ 2021-01-01 18:31 ` Paul Richard Thomas 2021-01-02 9:45 ` Paul Richard Thomas 2021-01-03 12:22 ` Paul Richard Thomas 2 siblings, 0 replies; 4+ messages in thread From: Paul Richard Thomas @ 2021-01-01 18:31 UTC (permalink / raw) To: Steve Lionel; +Cc: fortran Hi Steve, Thanks for coming back so promptly. Yes, I was aware of the rules of generic interfaces and thought for a while that your diagnosis is correct. I started digging through our interface handling to understand what I would have to do to fix it. However, my interpretation is that 15.4.3.4.2 overrides the generic interface rules since it says that the table in 10.1.5 stands no matter what. In fact, there is a practical consideration here in that the version of the testcase posted to clf leads to a stack overflow because of the infinite recursion that is caused. Let's indeed go for an interpretation request. IMHO even if gfortran is wrong, it leads to a more usable implementation. Cheers Paul On Fri, 1 Jan 2021 at 18:20, Steve Lionel <steve@stevelionel.com> wrote: > On 1/1/2021 11:14 AM, Paul Richard Thomas wrote: > > This comes about because ifort is using the defined operation to override > the intrinsic uses of the operator as defined in 10.1.5 of the standard. > > I believe that gfortran has this one right, since the first paragraph of > 15.4.3.4.2 Defined operations has: > "...If the operator is an intrinsic-operator (R608), the number of dummy > arguments shall be consistent with the intrinsic uses of that operator, and > the types, kind type parameters, or ranks of the dummy arguments shall > differ from those required for the intrinsic operation (10.1.5)." > > This is a fascinating issue, but I am afraid I must be the bearer of bad > news - I believe ifort is more right here than gfortran; but I also think > there is need for an interpretation. > > > Look at this in terms of the rules for generic interfaces that specify > whether signatures are distinguishable (15.4.3.4.5). We'll start with: > > C1511 Within the scope of a generic operator, if two procedures with that > identifier have the same number of arguments, one shall have a dummy > argument that corresponds by position in the argument list to a dummy > argument of the other that is distinguishable from it. > > In equals4.f90, you have a defined operator for == with class(*) dummy > arguments. The text in 15.4.3.4.2 that says [TKR] "shall differ" really > wants to say "is distinguishable from". class(*) objects have no type and > they are type compatible with EVERYTHING! So ifort is not wrong to call the > defined operator procedure for comparing integers (or in equals5, character > strings.) I think the standard needs to use different wording than "shall > differ" and I'll write up an interp about it. Intrinsic operations should > be considered built-in generic interfaces that can be "extended", and that > the rules for distinguishing generics should apply to defined operators. > > > The reason that equals4 works when the defined operator declaration is > moved to the main program is that it no longer applies to pvar_eq. > > > In support of my position, I observe that NAG Fortran 7.0.7036 behaves > identically here to ifort, including, for equals5, having star_eq > recursively call itself until it runs out of stack. I believe that the > correct resolution is that declaring a defined operator with class(*) dummy > arguments is a violation of C1511 and should be diagnosed by compilers. I > know this is not the answer the c.l.f poster wants to hear. > > > ifort DOES have a bug exposed by equals5.f90, in that it complains that > star_eq is called recursively. As a claimed F18-conforming compiler, > star_eq is RECURSIVE by default. I will report that to Intel. > > > Steve > -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Overriding intrinsic operators [not found] ` <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com> 2021-01-01 18:31 ` Paul Richard Thomas @ 2021-01-02 9:45 ` Paul Richard Thomas 2021-01-03 12:22 ` Paul Richard Thomas 2 siblings, 0 replies; 4+ messages in thread From: Paul Richard Thomas @ 2021-01-02 9:45 UTC (permalink / raw) To: fortran; +Cc: Steve Lionel This is now PR98498. I have set its status to "waiting", pending an interpretation request. Paul On Fri, 1 Jan 2021 at 18:20, Steve Lionel <steve@stevelionel.com> wrote: > On 1/1/2021 11:14 AM, Paul Richard Thomas wrote: > > This comes about because ifort is using the defined operation to override > the intrinsic uses of the operator as defined in 10.1.5 of the standard. > > I believe that gfortran has this one right, since the first paragraph of > 15.4.3.4.2 Defined operations has: > "...If the operator is an intrinsic-operator (R608), the number of dummy > arguments shall be consistent with the intrinsic uses of that operator, and > the types, kind type parameters, or ranks of the dummy arguments shall > differ from those required for the intrinsic operation (10.1.5)." > > This is a fascinating issue, but I am afraid I must be the bearer of bad > news - I believe ifort is more right here than gfortran; but I also think > there is need for an interpretation. > > > Look at this in terms of the rules for generic interfaces that specify > whether signatures are distinguishable (15.4.3.4.5). We'll start with: > > C1511 Within the scope of a generic operator, if two procedures with that > identifier have the same number of arguments, one shall have a dummy > argument that corresponds by position in the argument list to a dummy > argument of the other that is distinguishable from it. > > In equals4.f90, you have a defined operator for == with class(*) dummy > arguments. The text in 15.4.3.4.2 that says [TKR] "shall differ" really > wants to say "is distinguishable from". class(*) objects have no type and > they are type compatible with EVERYTHING! So ifort is not wrong to call the > defined operator procedure for comparing integers (or in equals5, character > strings.) I think the standard needs to use different wording than "shall > differ" and I'll write up an interp about it. Intrinsic operations should > be considered built-in generic interfaces that can be "extended", and that > the rules for distinguishing generics should apply to defined operators. > > > The reason that equals4 works when the defined operator declaration is > moved to the main program is that it no longer applies to pvar_eq. > > > In support of my position, I observe that NAG Fortran 7.0.7036 behaves > identically here to ifort, including, for equals5, having star_eq > recursively call itself until it runs out of stack. I believe that the > correct resolution is that declaring a defined operator with class(*) dummy > arguments is a violation of C1511 and should be diagnosed by compilers. I > know this is not the answer the c.l.f poster wants to hear. > > > ifort DOES have a bug exposed by equals5.f90, in that it complains that > star_eq is called recursively. As a claimed F18-conforming compiler, > star_eq is RECURSIVE by default. I will report that to Intel. > > > Steve > -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Overriding intrinsic operators [not found] ` <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com> 2021-01-01 18:31 ` Paul Richard Thomas 2021-01-02 9:45 ` Paul Richard Thomas @ 2021-01-03 12:22 ` Paul Richard Thomas 2 siblings, 0 replies; 4+ messages in thread From: Paul Richard Thomas @ 2021-01-03 12:22 UTC (permalink / raw) To: Steve Lionel; +Cc: fortran Hi Steve, > ifort DOES have a bug exposed by equals5.f90, in that it complains that > star_eq is called recursively. As a claimed F18-conforming compiler, > star_eq is RECURSIVE by default. I will report that to Intel. > Oddly enough, when I patch gfortran to comply with ifort and NAG, it exposes exactly the same error:-) (The patch is attached to PR98498.) Cheers Paul ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-01-03 12:23 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-01-01 16:14 Overriding intrinsic operators Paul Richard Thomas [not found] ` <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com> 2021-01-01 18:31 ` Paul Richard Thomas 2021-01-02 9:45 ` Paul Richard Thomas 2021-01-03 12:22 ` Paul Richard Thomas
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).