How lfortran finds subroutine in another file?

I need some warnings. But not this style suggestions.

What switch for this:

integer :: i=1

–std=f23 and --no-style-suggestions together can’t stop it.

The suggestion here to ‘initialize in a separate statement’ doesn’t make sense for me. Do it in one line is what I preferred.

I would try

Integer, Save :: i=1

Thanks. No warning for save. But I don’t want to change the code, just want to use a switch to stop the warning.

One very good reason to not supply a warning suppression method for implicit SAVE attribute is that it is explicitly mentioned in the Language Vulnerabilities document for Fortran.

I would argue that LFortran doing things different from GFortran in this instance is a step forward.

Without minimizing the tremendous work around lfortran, having a high rate of bug fixes in the early development phase is something that is expected.

Now, about gfortran: despite all the criticism it may legitimately draw, during years it was (AFAIK) the only free Fortran compiler in active development, and it contributed to maintain Fortran alive. And we should give credit to the people involved in gfortran for that.

LFortran already works with fpm. But you can wait till beta until you officially support it.

I think we don’t have a fine grained enough options yet. You can turn off all warnings with --no-warnings. It’s on our TODO list to make any warning configurable, so that you can setup the options to only warn about things you want.

I never used ‘save’ option. Don’t know what advantage it has. If it is better, it should be automatic. No save in specific occasion.

For the initialisation, suggesting use two lines is really weird. It is hard for programer, maybe easy for compiler? If it is a standard, then the standard is a bad one.

Many fortran programmers do in fact believe that implicit save is a bad idea in the language. But it has been standard for a couple of decades, and code has been written that depends on it, so it is unlikely to change. However, even with implicit save, a programmer can always add the save statement to make it explicit, even if it is redundant. That is what the style suggestion being discussed was suggesting, to make it explicit (and clear to the programmer) rather than implicit.

This has been considered unsafe practice because this doesn’t mean your variable i will be equal to 1 every time you enter the procedure. This means: the variable i is implicitly saved and initialized the first time it’s seen, but then you could mess up the value and it won’t be 1 the next time.

The following, extremely simplified snipped shows the issue (you can play with it here Compiler Explorer):

real :: z

z = 1.0
print *, myfun(z)
print *, myfun(z)

contains

real function myfun(x) result(y)
    real :: x
    integer :: a = 1

    y = a * x
    a = 2 !> if you change the value of a, this will be its value at the next invocation
end function

end

stdout:

   1.00000000    
   2.00000000  

Many of the evolutions in the language (and this also goes for other programming languages) comes from learning from the mistakes of the past. Many of such compiler warnings/errors are there to help the future you, to avoid that you shut yourself on the foot with something that has been known for decades can cause havoc in your applications and you’ll might expend days/weeks trying to identify why, when it could have been avoidable.

This actually makes me think a lot about the current trend and fame of Rust, it’s popularity comes from the compiler being an extremely severe supervisor, who will point out to you every single mistake, to make sure you’ll write things safely from the beginning.

ˋSAVEˋ is neither better nor worse. It has use cases, that’s all. The only issue is when it is implicit, because it can be misleading. But inconsistencies or design mistakes are to be expected in a 70 years old language.

Indeed. There are many more footguns in Fortran, such as:

real(dp) :: x
x = 1.3

We still need to add a warning for this one (#10614). Just like implied save, it is perfectly well defined by the standard, but it does something different than most people would expect and even if you know about this, it’s easy to make this mistake.

I got NASTRAN95 to compile correctly with ifort several years ago. Haven’t tried it with ifx, nvfortran, or AMD flang yet. For ifort, I had to make the following mods.

  1. In the file mds/PAKBLK.COM there is a strange non-printing character at the end of the file (probably an old eof mark of some kind) that caused ifort to gag.
  2. In /mis/random.f and mis/xsem00.f I changed the name for SUBROUTINE RANDOM to RANDOM2 to avoid any potential conflict with the intrinsic RANDOM routine. Other than these changes, everything else compiled correctly.

Thank you very much for the demo.

I don’t understand why provide the function to care about the next call. When the function is finished, all change should be dropped.

It is an error here. Indeed an easy mistake.

I am wondering if the compiler could change the number into dp number to avoid this mistakes.

Yes ifort could. Haven’t tried ifx to compiler it.

The fortran language standard defines how a compiler interprets the statement. This is so all compilers will produce the same results and so that programmers can rely on how the statement is evaluated. So no, a compiler is not allowed to promote the literal to a different precision. Some programmers want a warning for these types of statements, where the LHS is a different type and/or kind than the RHS to ensure that the language specification agrees with the programmer’s intentions. Also, other languages have different promotion rules, so it is easy for a programmer to get confused about how an expression is evaluated, and the compiler warning acts as a reminder or as a confirmation.

integer :: i=1 has been considered unsafe but when one wants a subprogram to do different things at its first and later calls, it is convenient to put this in its specification part:

   logical,save:: first = .true.

and this at a suitable point in its executable part:

   first = .false.

That is ‘today think’. Back in 1960, almost all Fortran compilers used static allocation of local variables. It was fast and easy to implement. Some machines back then didn’t even have index registers - making stack allocation somewhat tedious in terms of machine instructions. A few compilers dared to implement stack-like allocation of local variables in the '60s and '70s. Moreso in the '80s and '90s. Until recently, the Fortran standards never specified what should happen - unless ‘save’ is used.

When you combine the type declaration with the initialization, the Standard states that the variable has the ‘save’ (static) attribute. Yes, the Fortran 90 committee chose wrong.

There are lots of modern day uses for this feature. For example, something like

integer, save :: count = 0
...
count = count + 1

is a common idiom. The variable might be used somehow in expressions, or it might be used to index some related data associated with the function reference, or it might be used to count operations in order to model the scaling behavior, or it might end up just in a print statement.

Yes, we are working on it. Update: I see you meant to cast it automatically — we can’t do that, as that would not be backwards compatible. We have to be really careful with backwards compatibility. We could in principle do that and enable it with a compiler options. But I think a warning is better in this case.