Re: gfortran question about optional subroutine arguments

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 03/14/2013 08:30 AM, Tobias Burnus wrote:
Mark Hounschell wrote:
 From what I read, what I need to do is doable in f90/f95 using optional
arguments? But I am porting some very old fortran77 stuff and am using
the -std=legacy switch. I'm basically trying to figure out how to call a
subroutine with fewer arguments than the subroutine was declared with.

Pre-remark:-std=legacy by itself should be fine: -std=f95 -> f2003 ->
f2008 -> f2008ts -> gnu (= default) -> legacy  (with very few
exceptions) just enables more features. Thus, code valid with -std=f95
should give the same result with -std=legacy.

That's in line with the Fortran standard: Fortran is downward
compatible, i.e. a valid Fortran 77 code is also a valid Fortran 2008
code. (With very few exceptions: Fortran 95 did delete some rarely used
Fortran 77 features, but compilers continue to support them.)


When I use -std=f95 this fortran77 code will not compile. Many different complaints but the most serious are normal variable declarations:

        INTEGER*8 TOTTIME(0:MAXTASK)            ! Task total exec time (
                 1
Error: Nonstandard type declaration INTEGER*8 at (1)

????

Using the default "gnu" mostly just lots of warnings show up. Is "if(present(arg2)) arg2 = 0" available when using gnu? Maybe my warnings can be suppressed with other switches.



Regarding OPTIONAL arguments: The compiler needs to know about optional
arguments. For an absent optional argument, it passes a NULL pointer -
but to do so, the compiler has to know about it.

Hence, the Fortran standard requires an explicit interface. The best
Fortran 90+ way is to place the the procedure with optional arguments
into a MODULE and USE is in all the callers. (That has also the benefit
of giving argument checking.)

Alternatively, you can also create an INTERFACE block for those - either
in a MODULE, which you USE. Or in a separate file which you INCLUDE.

The call works but in the code below I get a segfault when the
subroutine attempts to access the unpassed argument. The old fortan77
had no problems with this, I assume because even when not passed in, the
subroutine declaration gave the argument a valid address??

How should the compiler know? I assume it only worked by chance.
Arguments are passed on the stack – and when the absent optional
argument is last and not used, it is likely to work. But it is not
really good practice and it might break.

In any case, you need somehow to tell the program to only access the
"optional" argument if it has been passed. If you don't use OPTIONAL,
you are on your own - the compiler doesn't help you. (You have to pass
this information, e.g., in the other arguments or via COMMON blocks or
...) Additionally, the absent arguments have to be last in the list.
Then it should work but it is outside of the spec.


c    the old fortran77 call would have been
c    call sub1(arg1,)

Hmm, I have not seen the ",)" syntax before. I assume that that is some
vendor extension, where the compiler does something - or a typo and it
should be "arg1)" without ",".


No, the "," is how this old compiler knows I'm not passing that arg.
The same could be done as

             call (arg1,,arg3)

Indicating arg2 was not passed. Also, the very last arg can always be left out without using the ",".


       subroutine sub1(arg1, arg2)
       implicit none

       integer*4 arg1
       integer*4 arg2

       arg2 = 0     ! causes segfault in gfortran

Well, that is not surprising. You shall not access an absent argument.
In the Fortran 77 pray & works approach, you are modifying some other
content on the stack, e.g. some locally declared variable in the caller.
That's definitely not something what you want to do. In the context of
arguments, Fortran by default regards them as pointers (arguments are
passed by reference by default). A locally defined variable such as
"real r" will not contain a pointer but directly the value. Hence, if
you regard the content as pointer address, dereferencing the value will
very likely result in an invalid memory access and a crash.

Actually, with Fortran 90's OPTIONAL the same will happen, if you simply
write to the optional argument. If the argument is absent, the compiler
passes a NULL pointer - and dereferencing null pointers also doesn't
work. However, with OPTIONAL you can check whether the argument is
present using  "if(present(arg2)) arg2 = 0".


Yes, I would like to be able to use "if(present(arg2)) arg2 = 0" but can't if specifying -std=legacy. Without -std=legacy thousands of lines of code would seemingly have to change as I show above when using -std=f95???

Regards
Marl


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux