When writing and calling pure subroutines in Fortran 90 using gfortran, how do I find out why the compiler emits this error?
Error: Subroutine call to XXXX at (1) is not PURE
I'll try to pose my question as specifically as I can while at the same time being general enough to be useful to others, so I'll avoid pasting in my actual code and instead will sketch what happened.
I understand there are various rules about pure procedures in Fortran 90, which I think basically boil down to not permitting side-effects in either functions or subroutines, and not permitting changes to subroutine parameters declared with intent(in). I've a series of subroutines which initially were not declared to be pure, and whose parameters didn't have declared intent, but which nevertheless didn't perform side-effects. First, I changed all parameter declarations to have explicitly-declared intent, either in, out, or inout. Then, I declared all the subroutines to be PURE. Naturally, many errors occurred on the first attempt, but the compiler told me what the errors were (such-and-such parameter with intent(in) is being modified, for example), so one-by-one I fixed them all.
There are calls among these procedures, however, and so now I still get many errors of the form shown above: Subroutine call to XXXX at (1) is not PURE. What I don't understand is why the call is not pure. I've done everything I can think of to make XXXX pure, but the compiler still thinks it isn't.
So my question --rephrased-- is: how do I get gfortran to tell me WHY it thinks XXXX is not pure?
"Placed all the PURE subroutines in the library I'm working on, into a MODULE (which my client code then USEd). ...... Not sure why ....., but after doing this more useful error messages appeared which allowed me to track down the remaining impurities."
Placing the subroutines into a module and then using them makes the interface explicit. This allows the compiler to check agreement between the call and the subroutine and generate error messages if there is a discrepancy. Very useful, so placing subroutines and functions into modules good practice.
The other way of making an interface explicit is to write an interface, but that is extra work and an extra step to get wrong.
There is a long list of requirements on pure subroutines/functions. If you have Fortran 95/2003 Explained by Metcalf, Reid and Cohen, see section 6.10. For example, no "save" variables, no stop statement, no IO on external file, ...
You can also try other compilers to see if their error message is more helpful. Other free ones, depending on OS, include g95 and Sun Studio.
I'll try to be more clear about my question in my answer. I was reluctant to post my code for these reasons.
I don't expect other people to debug my code for me. That's way too much to ask.
I wanted my question and its answer(s) to be more general.
It seemed gfortran was telling me my subroutines were not PURE, but it wasn't telling me WHY it considered them not to be pure.
So I hoped to find out, not how to fix my code and make the procedures PURE, but rather to find out how to coax more useful information from gfortran, in order to help me fix my code.
Two things that I did helped fulfill these goals. Of course, your results may vary.
Added this flag to the gfortran command-line: -fmax-errors=100
Of course, I'd done that earlier, but it still seemed not to tell me what I needed to know.
Placed all the PURE subroutines in the library I'm working on, into a MODULE (which my client code then USEd). Since this library's ancestry is as Fortran77, originally, this was not the case. Not sure why (which is why I stress that "your results may vary"), but after doing this more useful error messages appeared which allowed me to track down the remaining impurities.
It's kind of a nebulous question, I know, and I'm not sure how useful it will be. Still, thanks to everyone who read, commented on, and added answer(s).
Probably because it's not marked as PURE. The fact that a subroutine is pure is not related to what it does or not with its arguments, but to the fact that it's declared as PURE. (Of course, once declared as pure, what you do with the arguments comes into play and is checked.)
I am Fortran beginner and last week I reached chapter about Fortran procedures in my book. May be I'm not right but... So if you will excuse my English there are some remarks:
It's not good style to declare subroutines pure. It's advisable for functions.
Pure procedures were introduced in Fortran 95 standard. Not in Fortran 90.
You problem probably arises from item C1270 in (Fortran 2003 Standard) which read as follows:
If a procedure that is neither an intrinsic procedure nor a statement function is used in a context that requires it to be pure, then its interface shall be explicit in the scope of that use. The interface shall specify that the procedure is pure.
I hope that it is useful information.
Related
I'm helping renovate a legacy code base in Fortran which has interface definitions for functions / subroutines.
The issue I am facing is that some of those interfaces are out of sync with the actual function definitions and the compiler (silverfrost) is not catching these at compile time. This leads to run time errors.
Ignoring the specific compiler I am using for now, does Fortran have a method for handling this without repeating the function definition? For example, in C#, Java etc. I can declare a function and call it from elsewhere in the project and the compiler makes sure the caller and target function are compatible.
Does GNU Fortran or the Intel Fortran compiler make this any less fragile?
If you put procedures in MODULEs and USE the MODULEs, the compiler will check that procedures are called with the correct arguments.
Our current solution is a mixed C++ Fortran application in Visual Studio 2013, with approximately 40 projects of each.
Although we can build the solution just fine, we are getting about 6000 warnings - a vast majority of which are LNK4006 warnings, where a function is being "duplicated":
warning LNK4006: _XXXXXXXXXXX#8 already defined in project1.lib(module1.obj); second definition ignored project2.lib(module1.obj)
The common thread is that the functions that are being duplicated are defined in Fortran modules - many of which are just interfaces to C++ functions:
MODULE mINTERFACES
USE ISO_C_BINDING
INTERFACE
INTEGER(4) FUNCTION GetLastErrorCode [C, ALIAS: '_GetLastErrorCode'] (index)
USE ISO_C_BINDING
INTEGER(C_SIZE_T), INTENT(IN) :: index
END FUNCTION GetLastErrorCode
END INTERFACE
END
Since these modules are used across many Fortran projects, each project has an independent version of the interface function - hence the duplication.
This all makes perfect sense, but my question is: can I just ignore the warnings (i.e. exclude them in the project configuration)? I can't see any obvious way to restructure our code to remove the warnings, and I was under the impression that putting these interfaces in a module was good practice...
My thanks to all those who've commented constructively in this thread - but also to #IanH and Steve Lionel who have helped in the Intel forum thread at https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/628995.
In Short
(And this is my own judgement and nobody else's) In this particular case the warnings were superfluous BUT if you disable them you would miss any new warnings which could be important. IMHO this means that you shouldn't disable the warning.
The Long Answer
The warnings were coming from two sources:
A convention had grown up to use a module to contain "global" data, but to access this through "accessor functions" which were defined in the same files as the modules. This meant that when the modules were included in many different projects, the accessor functions were compiled multiple times.
Several of these modules contained C interface blocks (which is good practice), but for functions which returned strings, the paradigm was used as described in Creating a FORTRAN interface to a C function that returns a char*. Although the interface blocks themselves didn't raise a duplication warning, the secondary functions which converted the C pointer to a Fortran string did.
A solution could have been to extract all of these accessor functions and secondary interface routines into separate files and only compile them once BUT this would have taken weeks.
Thanks to #IanH, he pointed out that you could obviate this by defining all of the modules in a separate project, and then (in Visual Studio) just sett all of the projects to to depend on this new "shared modules" project (using Build Dependencies-->Project Dependencies). This now compiles without the warnings; VS's "Entire Solution" search now only finds each routine once; and it probably compiles a lot faster! All in all, a win.
I need some pointers to solve a problem that I can describe only in a limited way. I got a code written in f77 from a senior scientist. I can't give the code on a public forum for ownership issues. It's not big (750 lines) but given implicit declarations and gotos statements, it is very unreadable. Hence I am having trouble finding out the source of error. Here is the problem:
When I compile the code with ifort, it runs fine and gives me sensible numbers but when I compile it with gfortran, it compiles fine but does not give me the right answer. The code is a numerical root finder for a complex plasma physics problem. The ifort compiled version finds the root but the gfortran compiled version fails to find the root.
Any ideas on how to proceed looking for a solution? I will update the question to reflect the actual problem when I find one.
Some things to investigate, not necessarily in the order I would try them:
Use your compiler(s) to check everything that your compiler(s) are capable of checking including and especially array-bounds (for run-time confidence) and subroutine argument matching.
Use of uninitialised variables.
The kinds of real, complex and integer variables; the compilers (or your compilation options) may default to different kinds.
Common blocks, equivalences, entry, ... other now deprecated or obsolete features.
Finally, perhaps not a matter for immediate investigation but something you ought to do sooner (right choice) or later (wrong choice), make the effort to declare IMPLICIT NONE in all scopes and to write explicit declarations for all entities.
I've few questions about C++ compilers
Are C++ compilers required to be one-pass compiler? Does the Standard talk about it anywhere?
In particular, is GCC one-pass compiler? If it is, then why does it generate the following error twice in this example (though the template argument is different in each error message)?
error: declaration of ‘adder<T> item’ shadows a parameter
error: declaration of ‘adder<char [21]> item’ shadows a parameter
A more general question
What are the advantages and disadvantages of one-pass compiler and multi-pass compiler?
Useful links:
A List of C/C++ compilers (wikipedia)
An incomplete list of C++ compilers (Bjarne Stroustrup's site)
The standard sets no requirements what so ever with regards to
how a compiler is implemented. But what do you mean by
"one-pass"? Most compilers today do only read the input file
once. They create an in memory representation (often in the
form of some sort of parse tree), and may make multiple passes
over that. And almost certainly make multiple passes over parts
of it. The compiler must make a "pass" over the internal
representation of a template each time it is instantiated, for
example; there's no way of avoiding that. G++ also makes
a "pass" over the template when it is defined, before any
instantiation, and reports some errors then. (The standard
committee expressedly designed templates to allow a maximum of
error detection at the point of definition. This is the
motivation behind the requirement for typename in certain
places, for example.) Even without templates, a compiler will
generally have to make two passes over a class definition if
there are functions defined in it.
With regards to the more general question, again, I think you'd
have to define exactly what you mean by "one-pass". I don't
know of any compiler today which reads the source file several
times, but almost all will visit some or all of the nodes in the
parse tree more than once. Is this one-pass or multi-pass? The
distinction was more significant in the past, when memory wasn't
sufficient to maintain much of the source code in an internal
representation. Languages like Pascal and, to a lesser degree
C, were sometimes designed to be easy to implement with a single
pass compiler, since a single pass compiler would be
significantly faster. Today, this issue is largely irrelevant,
and modern languages, including C++, tend to ignore it; where
C++ seems to conform to the needs of a one-pass compiler, it's
largely for reasons of C compatibility, and where
C compatibility is not an issue (e.g. in a class definition), it
often makes order of declaration irrelevant.
From what I know, 30 years ago it was important for a compiler to be one-pass, because reads and writes to disk (or magnetic tape) were very slow and there was not enough memory to hold whole code (thanks James Kanze). Also, a single-pass is a requirement for scripting/interactive languages.
Nowdays compilers are usually not one-pass, there are several intermediate representations (e.g Abstract Syntax Tree or Static Single Assignment Form) that the code is transformed into and then analised/optimised.
Some elements in C++ cannot be solved without some intermediate steps, e.g. in a class you can reference members which are defined only later in the class body. Also, all templates need to be somehow remembered for further access during instantiation.
What does not happen usually, is that the source code is not parsed several times --- there is no need for that. So you should not experience same syntactic error being reported several times.
No, I would be surprised if you found a heavily used C++ single pass compiler.
No, it does multiple passes and even different optimizations based on the flags you pass it.
Advantages (single-pass): fast! Since all the source only needs to be examined once the compilation phase (and thus beginning of execution) can happen very quickly. It is also a model that is attractive because it makes the compiler easy to understand and often times "easier" to implement. (I worked on a single pass Pascal compiler once, but don't encounter them often, whereas single pass interpreters are common)
Disadvantages (sinlge-pass): Optimization, semantic/syntactic analysis. Sometimes a single code look lets things through that are easily caught by simple mechanisms in multiple passes. (kind of why we have things like JSLint)
Advantages (multi-pass): optimizations, semantic/syntactic analysis. Even pseudo interpreted languages like "JRuby" go through a pipeline compilation process to get to java/jvm bytecode before execution, you could consider this multi-pass and the multiple looks at the varying representations (and consequently the resulting optimizations) of code can make it very fast.
Disadvantages (multi-pass): complexity, sometimes time (depending on if AOT/JIT is being used as your compilation method)
Also, single-pass is pretty common in academia to help learn the aspects of compiler design.
Walter Bright, the developer of the first C++ compiler, has stated that he believes it is not possible to compile C++ without at least 3 passes. And, yes, that means 3 full text-transforming passes over the source, not just traversals through an internal tree representation. See his Dr. Dobb's magazine article, "Why is C++ compilation so slow?" So any hope of finding a true one-pass compiler seems doomed. (I think this was part of the motivation Bright had to develop D, his C++ alternative.)
The compiler only needs to look at the sources once top down, but that does not mean that it does not have to process the parsed contents more than once. In particular with templates, it has to instantiate the templated code with the type, and that cannot happen until the template is used (or explicitly instantiated by the user), which is the reason for your duplicate errors:
When the template is defined, the compiler detects an error and at that point the type has not been substituted. When the actual instantiation occurs it substitutes the template arguments and processes the result, which is what triggers the second error. Note that if the template was specialized after the first definition, and before the instantiation, for that particular type, the second error need not occur.
I always assumed that fortran passed entities "by reference" to a dummy argument. Then I got this answer (the actual argument of the answer was related, but not on this)
The standard never specifies that and,
indeed goes quite a lot out of its way
to avoid such specification. Although
yours is a common misconception, it
was not strictly accurate even in most
older compilers, particularly with
optimization turned on. A strict
pass-by-reference would kill many
common optimizations.
With recent standards,
pass-by-reference is all but
disallowed in some cases. The standard
doesn't use those words in its
normative text, but there are things
that would be impractical to implement
with pass-by-reference.
When you start getting into things
like pointers, the error of assuming
that everything is pass-by-reference
will start making itself more evident
than before. You'll have to drop that
misconception or many things wil
confuse you.
I think other people have answered the
rest of the post adequately. Some also
addressed the above point, but I
wanted to emphasize it.
See here for attribution.
According to this answer, then, there's nothing in the standard specifying how data are shipped from the caller to the callee. In practical terms, how this should be interpreted in terms of actually working with it (regardless of the practical effects resulting from how compilers implement the standard) in particular when it comes to intent() specification?
Edit: I'd like to clarify my question. What I am trying to understand is how the standard expects you to work when you are performing calls. Given that the actual compiler strategy used to pass entities is undefined by the standard, you cannot in principle (according to the standard) expect that passing an argument to a function will actually behave as a "pass-by-reference", with all its related side-effects, because this behavior is compiler and optimization dependent. I assume therefore the standard imposes you a programming style you have to follow to work regardless of the actual implementation strategy.
Yes, that's true. Fortran standard doesn't specify the exact evaluation strategy for different INTENT attributes. For example, for a dummy argument with INTENT(OUT) some Fortran compiler can use call-by-reference or call-by-copy-restore evaluation.
But I do not understand why do you really need to know which evaluation strategy is used? What is the reason? I think Fortran do it right. Humans concern is (high-level) argument intent, and computers concern is (low-level) evaluation strategy. "Render unto man the things which are man’s and unto the computer the things which are the computer’s." N. Wiener
I think the standard contains enough information on the usage of different INTENT attributes. Section "5.1.2.7 INTENT attribute" of Final Committee Draft of Fortran 2003 standard (PDF, 5 MB) is a good starting point.
As the others have said, you don't have to know how the compiler works, as long as it works correctly. Fortran >=90 allows you to specify the purpose of an argument: input, output or both, and then the compiler takes care of passing the argument. As long as the compiler is correctly implemented so that both sides (caller and callee) use the same mechanism, why should the programmer care? So the Fortran standard tries not to limit how compiler writers implement their compilers, allowing them to design and optimize as they wish.
In terms of programming style, decide the purpose of your procedure arguments, and declare them with the appropriate intent. Then, for example, if you accidentally try to modify an intent(in) argument in a procedure, the compiler will issue an error message, preventing you from making this mistake. It might even do this before emitting object code, so the actual argument passing mechanism has nothing to do with enforcing this requirement of the language.
C is a lower-level language and the programmer needs to choose between passing by value or by reference for various reasons. But for problems such as scientific programming this is an unnecessary aspect to have to control. It can be essential in embedded or device driver programming.
If there is a reason that you must control of the argument passing mechanism, such as interfacing to another language, Fortran 2003 provides the ISO C Binding (which is already widely implemented). With this you can match the C method of argument passing.
I'm not sure I understand your question, but one way of seeing things is that as long as one writes standard-conforming code, one does not need to be concerned with how argument passing is implemented. The compiler makes sure (well, barring compiler bugs, of course) that arguments are passed in a way that conforms to the standard.
Now, if you play tricks e.g. with C interop or such, say by comparing argument addresses you might be able to determine whether the compiler uses pass by reference, copy-in/copy-out or something else in some particular case. But generally speaking, at that point you're outside the scope of the standard and all bets are off.