gfortran question about optional subroutine arguments

Tobias Burnus burnus@net-b.de
Thu Mar 14 12:30:00 GMT 2013


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.)


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 ",".


>        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".

Tobias



More information about the Gcc-help mailing list