|
From: bill on 4 Apr 2008 23:49 The code below invokes the subroutine wrapcall with an actual procedure argument, bar, whose interface differs from the associated dummy argument, sub, because bar has an explicit-shape argument declared as x(2) whereas sub has an assumed-shape argument x(:). module foo contains subroutine bar(x) real, intent(in) :: x(2) print *, "In bar: x = ", x end subroutine bar end module foo program runfoo use foo real :: x(2) = [1, 2] call wrapcall(x, bar) contains subroutine wrapcall(x, sub) real, intent(in) :: x(:) interface subroutine sub(x) real, intent(in) :: x(:) end subroutine sub end interface print *, "In wrapcall: x = ", x call sub(x) end subroutine wrapcall end program runfoo Compiling with gfortran we get the output In wrapcall: x = 1.000000 2.000000 In bar: x = 8.8215270E-39 0.000000 presumably because wrapcall passes a descriptor of x but bar expects to get the address of x(1). The same happens with g95, but ifort flags a compilation error: The characteristics of dummy argument 1 of the associated actual procedure differ from the characteristics of dummy argument 1 of the dummy procedure. (12.2) [BAR] call wrapcall(x, bar) --------------^ compilation aborted for runfoo.f90 (code 1) The curious thing is that if we replace the interface block in wrapcall by procedure(sarg) :: sub where sarg has the same (abstract) interface subroutine sarg(x) real, intent(in) :: x(:) end subroutine sarg then, compiling with g95, everything works fine: In wrapcall: x = 1. 2. In bar: x = 1. 2. It seems perverse that we get a different outcome replacing the interface block by the procedure statement in this way. Is this really what the standard says should happen?
From: Richard Maine on 5 Apr 2008 01:03 bill <w.mclean(a)unsw.edu.au> wrote: > The code below invokes the subroutine wrapcall with an actual > procedure argument, bar, whose interface differs from the associated > dummy argument, sub, because bar has an explicit-shape argument > declared as x(2) whereas sub has an assumed-shape argument x(:). Presumably you know this is invalid, as ifort reports. > The curious thing is that if we replace the interface block in > wrapcall by > > procedure(sarg) :: sub > > where sarg has the same (abstract) interface > > subroutine sarg(x) > real, intent(in) :: x(:) > end subroutine sarg > > then, compiling with g95, everything works fine: > > In wrapcall: x = 1. 2. > In bar: x = 1. 2. > > It seems perverse that we get a different outcome replacing > the interface block by the procedure statement in this way. > Is this really what the standard says should happen? The standard says the code is invalid. That's pretty much the end of the story. This is not a case of invalid code that a compiler is required to be able to diagnose. The compiler is allowed to do anything with it. I agree that it is a bit curious that the case with a procedure statement gives a different result from the case with an interface body. Sounds like there might be a compiler bug buried in there somewhere. But even if so, this doesn't demonstrate a compiler bug in conformance to the standard. It just might make me suspicious that, if the two cases are treated differently, one might be able to come up with valid code that doesn't work. But you don't have that. You have invalid code that does "work"; that's not directly a compiler bug in this case. -- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
From: James Van Buskirk on 5 Apr 2008 21:56 "bill" <w.mclean(a)unsw.edu.au> wrote in message news:e450c51d-fbaf-4c18-afc6-16665227e0f8(a)s13g2000prd.googlegroups.com... > The characteristics of dummy argument 1 of the associated actual > procedure differ from the characteristics of dummy argument 1 of the > dummy procedure. (12.2) [BAR] > call wrapcall(x, bar) > --------------^ > compilation aborted for runfoo.f90 (code 1) Yeah, ifort has done this since the cvf or even dvf days. It behaves as though it were building data structures corresponding to dummy procedures and passing them around via the *.mod files. You get spoiled by this extra degree of interface checking if dvf/cvf/ifort is all you ever used, and when you try other compilers generally you find that they can't distinguish between a function and a subroutine dummy argument, much less check the whole signature of the procedure. The reason for this lies in the possibility for a dummy argument to simply be declared EXTERNAL and impicitly typed so there is no way for the caller to check its interface. And you can't require explicit interfaces for everything: what if a RECURSIVE procedure could be passes itself as an actual argument? Well, maybe there is no possible useful code where that happens, but there is no linguistic prohibition either, so you have to take into account dummies being declared EXTERNAL and implicitly typed, hence being total wild cards. There is a good reason for Intel and predecessors to check procedure arguments possibly to the extent of building data structures containing their interfaces: mismatched procedure interfaces are ugly to debug because everything is OK in both the caller and the callee, it's just the interaction between the two that's a bug. There is good reason for other vendors not to do so, however: it's always possible to subvert any procedure interface checking mechanism, whether intentionally or through code that is just complicated. Also any feature like this can be tripped up to the extent of causing errors or ICE. Did anyone suspect an example was coming? C:\gfortran\clf\ambinterf>type ambinterf.f90 ! File: ambinterf.f90 ! Public domain 2008 James Van Buskirk module interfs implicit none contains subroutine callthru(qsub, option) implicit logical(q) integer, intent(in) :: option external qsub if(option == 1) then write(*,'(a)') 'Calling subroutine A' call A(qsub, 2) else if(option == 2) then write(*,'(a)') 'Calling subroutine B' call B(qsub, 2) else if(option == 3) then write(*,'(a)') 'Calling subroutine C' call C(qsub, 2) end if end subroutine callthru subroutine A(sub, n) integer, intent(in) :: n interface subroutine sub(x) implicit none real, intent(in) :: x(:) end subroutine sub end interface real x(n) integer i x = [(i,i=1,n)] call sub(x) end subroutine A subroutine subA(x) real, intent(in) :: x(:) write(*,*) 'In subA, x = ', x end subroutine subA subroutine B(sub, n) integer, intent(in) :: n interface function sub(x) implicit none integer, intent(in) :: x logical sub(x) end function sub end interface write(*,*) 'Result of subB = ', sub(n) end subroutine B function subB(x) integer, intent(in) :: x logical subB(x) integer i subB = [(modulo(i,2) == 0,i=1,x)] end function subB subroutine C(sub, n) integer, intent(in) :: n interface function sub(n) implicit none integer, intent(in) :: n integer sub end function sub end interface if(n /= 2) then write(*,*) 'In subroutine C, result of subC = ', sub(n) else write(*,*) 'Nothing to do in subroutine C' end if end subroutine C subroutine subC(n) integer, intent(in) :: n write(*,*) 'Shouldn''t have reached this statement' end subroutine subC end module interfs program ambiguous use interfs implicit none integer n n = 1 call callthru(subA, n) n = 2 call callthru(subB, n) n = 3 call callthru(subC, n) end program ambiguous ! End of file: ambinterf.f90 C:\gfortran\clf\ambinterf>c:\gcc_equation\bin\x86_64-pc-mingw32-gfortran ambinte rf.f90 -oambinterf ambinterf.f90:16.19: call B(qsub, 2) 1 Error: Type/rank mismatch in argument 'sub' at (1) ambinterf.f90:19.19: call C(qsub, 2) 1 Error: Type/rank mismatch in argument 'sub' at (1) ambinterf.f90:90.14: use interfs 1 Fatal Error: Can't open module file 'interfs.mod' for reading at (1): No such fi le or directory x86_64-pc-mingw32-gfortran: Internal error: Aborted (program f951) Please submit a full bug report. See <http://gcc.gnu.org/bugs.html> for instructions. C:\gfortran\clf\ambinterf>ifort ambinterf.f90 Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1 Build 20061104 Copyright (C) 1985-2006 Intel Corporation. All rights reserved. ambinterf.f90(97) : Error: The shape matching rules of actual arguments and dumm y arguments have been violated. [SUBB] call callthru(subB, n) -----------------^ compilation aborted for ambinterf.f90 (code 1) Jeez, I thought gfortran would pass this and ifort reject it but they are both abusing me here! Is there something really wrong with the above code? -- write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & 6.0134700243160014d-154/),(/'x'/)); end
From: Tobias Burnus on 6 Apr 2008 18:02 On Apr 6, 3:56 am, "James Van Buskirk" <not_va...(a)comcast.net> wrote: > subroutine callthru(qsub, option) > implicit logical(q) > integer, intent(in) :: option > external qsub > > if(option == 1) then > write(*,'(a)') 'Calling subroutine A' > call A(qsub, 2) "A" takes a subroutine as argument. > else if(option == 2) then > write(*,'(a)') 'Calling subroutine B' > call B(qsub, 2) While "B" takes a function as argument. I believe the program is invalid. Quoting the Fortran 2003 standard: "12.4.1.3 Actual arguments associated with dummy procedure entities" [...] "If the interface of the dummy argument is implicit and either the name of the dummy argument is explicitly typed or it is referenced as a function, the dummy argument shall not be referenced as a subroutine" As you once reference "qsub" as function and once as subroutine (by using them as actual argument), the program is invalid and the compiler is free to reject it. Interestingly, most compiler accept a reduced version which contains such calls. For the most reduced version which uses implicit typing, of my compilers, only gfortran rejects it. For the full program, most of my compilers reject it. In conclusion, I think gfortran is right and your program is invalid. > subroutine A(sub, n) > integer, intent(in) :: n > interface > subroutine sub(x) > implicit none > real, intent(in) :: x(:) > end subroutine sub > end interface > subroutine B(sub, n) > integer, intent(in) :: n > interface > function sub(x) > implicit none > integer, intent(in) :: x > logical sub(x) > end function sub > end interface Tobias
From: glen herrmannsfeldt on 6 Apr 2008 19:53 Tobias Burnus wrote: (snip) > I believe the program is invalid. Quoting the Fortran 2003 standard: > > "12.4.1.3 Actual arguments associated with dummy procedure entities" > [...] > "If the interface of the dummy argument is implicit and either the > name of the dummy argument is explicitly typed or it is referenced > as a function, the dummy argument shall not be referenced > as a subroutine" I once did something like: external sub,fun call test(sub,.true.,x) call test(fun,.false.,y) write(*,*) x,y end subroutine test(f,select,xy) logical select if(select) call f(xy) if(.not.select) xy=f(1.23) return end subroutine sub(x) x=3.4 return end function fun(x) fun=4.5 return end Note that sub is always called as a subroutine and fun always as a function, yet some (most) compiler would refuse it. It seems that the part of the standard quoted supports the refusal to compile it. Error: Unclassifiable statement following IF-clause at (1) That is, in: if(.not.select) xy=f(1.23) Commenting out the previous statement allows it to compile. I do believe a better message could be expected in this case. -- glen
|
Next
|
Last
Pages: 1 2 Prev: The structure contains one or more misaligned fields Next: Using Modules |