gfortran question about optional subroutine arguments
Mark Hounschell
markh@compro.net
Thu Mar 14 13:40:00 GMT 2013
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
More information about the Gcc-help
mailing list