How lfortran finds subroutine in another file?

Hi,

I am playing with lFortran (ver 0.60) on an android phone within termux.

Here is a simple code trying to call a sub in another file from the main file. But the main can’t find it.

!lmain.f90

integer a,b,c

a=1
b=2
call subadd(a,b,c)
print *,'c =',c

end
!lsub.f90
subroutine subadd(a,b,c)

integer,intent(in) :: a,b
integer,intent(out) :: c

c=a+b

end subroutine subadd

The compile line is:

lfortran lmain.f90 lsub.f90

I can make it work to put the sub inside a module. But how to find the sub without using module? gFortran has no problem with this.

Thanks for help.

Regards,

Cean

lmain.f90 (69 Bytes)

lsub.f90 (117 Bytes)

On macOS (but I think any platform) the behavior is:

$ lfortran lmain.f90 lsub.f90
semantic error: Function 'subadd' not found (not user defined nor intrinsic)
 --> lmain.f90:7:1
  |
7 | call subadd(a,b,c)
  | ^^^^^^^^^^^^^^^^^^

You should either put it into a module, or create an interface. If you want implicit interface, you can do so like this:

$ lfortran lmain.f90 lsub.f90 --implicit-interface
c =    3
1 Like

Thank you very much.

Is it possible the compiler by default uses implicit-interface? So I don’t need to do any changes. I have a lot of these kind of old sources. Like the old nastran code, if I change them into modules, it will be a lot more complicated and may be into a use loop.

Other things about lFortran, it warns on endif and enddo. Need to change to end if and end do. Also warning on .le. etc. suggest to change to <= etc. Is it possible by default, not warning on these. Since the code works, I don’t want to see the warning and it is too much to change thousand of files.

Another one is warning on integer :: a=1. Need to change to two lines. Integer :: a and a=1. Would be nice no change.

Wouldn’t an EXTERNAL subadd be sufficient?

The code, as is, might produce strange results on a compiler that has an intrinsic called SUBADD.

Not equivalent in all cases.

That would probably upset others.

You can use the option --no-style-suggestions to switch off the above style warnings, and the option --no-warnings if you don’t want any warnings whatsoever. You don’t need to change any files. Just use the above compiler options on legacy code.

Opinions on whether all of this should be the default behavior vary, and hinge on the question whether users should be actively encouraged (or not) to write modern Fortran, instead of FORTRAN 77, code.

I learnt Fortran 77 at uni, even module is too modern to me. Maybe I shouldn’t say by default, instead asking some tolerance on old code. Gfortran doesn’t need these switches. Why lFortran needs them? Both enddo and end do works, why distinguish them? They all work, that’s all.

Adding two extra switches is fine this time, but think it will be easily forget next time I run into an old code. Just hoping switching from gfortran to lFortran doesn’t need too much change on code or compile command.

It’s just an example.

I think for intrinsic, you use it directly. For your own sub, you call it. So the name may be the same. Never thought of this. Always try to name the sub a bit unique. There maybe problem when you link to code by other. If the name too general, more chance to have same name.

I think the external is for C sub.

Everything you have said so far is consistent with an impression that you have learned “folk-Fortran” which is not a well-specified language that has ever been implemented. “Old code” frequently contains constructs that have no interpretation in standard (that is, well-specified) Fortran, are not properly documented by the compiler that “supports” them, are almost always misunderstood by users, and would manifest strange bugs as soon as someone modifies the source slightly. But people keep saying that “it works”. The only sense in which that might be true is if you are willing to stay forever with that one compiler than once compiled it for a platform that does not exist anymore.

It is my understanding that LFortran’s developers wish to actively promote both sound programming practices in, and further development of, the language. Which are both required in order to attract new users to Fortran (at the cost of possibly having to compile legacy code with some additional compiler options).

If this is something that does not appeal to you, or that you don’t care about, then I’d recommend that you stay with GFortran. GFortran is a more traditional compiler that will run your codes well (but won’t run most codes that conform to the Fortran 2003 or later standards).

Edit: @themos is, of course, right in that what you wish to be writing without getting warnings (i.e. enddo, endif, no modules, etc.) is actually not a subset of some specific Fortran standard, but a mixture of features from different “epochs”. So I stand corrected in calling this FORTRAN 77.

As it happens, enddo and endif are perfectly acceptable standard Fortran, in either fixed or free form source formats and have the same interpretation as end do and end if, respectively.

FORTRAN/Fortran evolved through many decades. On the way, mistakes were made and lessons were learned. Some mistakes have been allowed to persist, in the interests of backward compatibility (allowing code once considered well-formed to continue to be so considered). Some communities of developers have come up with style guidelines to always express relationships in a consistent way. One such guideline is to always mark subprograms defined elsewhere by the programmer as EXTERNAL, and if functions, to always declare the type of the result as well. Another is to always use IMPLICIT NONE. Another is to clearly comment and declare parameters, common blocks, USE statements, derived types, dummy arguments, equivalences, externals, etc in separate, delineated source sections.

Yes, I recommend using --std=f23 then. It will do all the things you asked for. It will also enable implicit typing and other things, and not warn about anything that is standards conforming.

My current philosophy is that I want LFortran by default to work with modern Fortran and guide users (especially new users) to use Fortran “correctly”. What does that mean? Well, most people would agree not to use implicit typing nor implicit interfaces for new codes, and probably <= instead of .le. and many things like that. For old codes we have a simple option --std=f23 that turns all this off, so it will just work. Part of this is to get good error messages, for example I don’t want to see linker errors “missing symbol” with some obscure name or something, rather I want to see in the source code what is missing with a nice error message. We are not completely there yet, but we will eventually. Also, I want each such error or warning to tell you how to turn it off, we currently don’t always do that either yet. That’s why we are still in “alpha”. :slight_smile:

Second, by default I want user’s code to never segfault or have other undefined behavior, so we have bounds checking and other runtime checking on by default. It should behave just like Python, completely safe.

Third, I want by default for LFortran to guide users and to make it super simple to obtain high-performance code. For that we are still figuring out the right line, for example we are going to relax some of the errors into warnings (#10331, #10422). Overall the contract is: if your code compiles and runs without any compile-time nor runtime warnings or errors, then you can enable fast optimizations (with a single compiler flag) and you will get correct results with maximum performance. The idea is to “block” some features which are hard to optimize with warnings (so you can still use them, but your code might not run at maximum speed).

Fourth, all of the above must be easy to configure, ideally just one simple option to get most people exactly what they want. For example I think it’s possible to create such options to get everybody in this thread exactly what they want.

Fifth, I want LFortran to also work with old codes easily. @rwmsu sent me this nice book FORTRAN Programming by Fredric Stuart from 1968 which has a lot of FORTRAN II and IV examples and I plan to get them all working, ideally in the browser so that we can all play with that. However likely one will have to use some compiler options to enable some of the old features (perhaps the option can be as simple as just --legacy).

1 Like

Even GNU compilers after version 10 (if I remember correctly) shifted from warning to error many features which would be accepted by F77 and are considered as bad practices today. Which to enable again one would need flags such as -std=legacy for Fortran (and -fpermissive for C/C++)

Most compilers that I’m aware of try to push developers to adopt safer practices by adopting standard conforming syntax. It might seem painful but it is the right path forward.

Intel LLVM compilers have also become much more stringent with code that would have considered non-standard or unsafe.

1 Like

I don’t understand this assertion.

One of the major things that Fortran 2003 introduced is object-oriented programming.

More than two decades after the release of this standard, GFortran is still so buggy that it is incapable of running codes that make any serious use of these (Fortran 2003 standard) object-oriented features.

WoW … I couldn’t disagree more… I don’t know which version do you use but despite the criticism one might have and some features like PDT missing. Gfortran is rather robust.

Having tested myself intel classic, intel llvm, GNU, flang, Lfortran, nvfortran+nvcc … the GNU and Intel families are the ones capable of handling most code bases I’ve seen, at least until f2008 and many of f2018 features.

2 Likes

It really depends on your code. For my codes GFortran has been robust (I don’t recall ever discovering a compiler bug even), but I don’t use OO much. For @kkifonidis, @rouson, and many other people’s codes, GFortran has been having a hard time compiling and running them correctly. Both are true statements. @hkvzjal I am guessing your codes fall more into the category of most of my codes and those indeed work great with GFortran.

1 Like

@hzgzh a lot depends on the features of interest so discussing compiler robustness is very much a your-mileage-may-vary situation. I heavily exercise features from recent standards, including features that I rarely see in other codes. I’ve broken every compiler I’ve touched, which includes at least 7 compilers over the past few years. The most robust compilers that I currently use are LLVM flang and lfortran by a very long shot. I wish I could underline the word “very” 10 times in the previous sentence. I’ve averaged about one bug report per week since the beginning of 2024 so that’s well over 100 bug reports. In all that time, I’ve only found 1 bug in LLVM flang and I just found that one about 2 months ago. In the case of LFortran, what has been most amazing is how fast features can be added and bugs can be fixed. LFortran recently went from only being able to build 1 of my projects to being able to build 5 projects in the span of about 1 month. In one case, LFortran went from only passing 3 of 14 tests on the smart-pointers library to 5 hours later passing 14 of 14.

I wrote my first Fortran code in the summer of 1979 and I’ve been reporting compiler bugs frequently since at least 2004. In all that time, I have never seen a compiler as robust as LLVM flang and I’ve never seen a vendor that can add features or fix bugs as fast as LFortran – not even close.

2 Likes

Thank you @rouson for the encouraging words!

I should mention LFortran is still in alpha and GFortran can still compile more codes than we do (but we can now compile and run correctly some codes that GFortran cannot). My guess is that we are about where Flang was 1.5 years ago, just taking third-party codes and fixing bugs to compile them. It’s a lot of fun! For each code we fix a few bugs and bang – it fully runs and passes all tests. It’s beautiful.

1 Like