I am compiling a program (that I did not write) using gfortran. The make file specified f77 as the compiler, but I do not have it.
I have run into an error related to the OPEN command.
Error: The STATUS specified in OPEN statement at (1) is 'NEW' and no FILE specifier is present
I looked into Fortran 77 OPEN, and according to the Oracle language reference there is a default behaviour when 'FILE=name' is not specified.
http://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vnaf/index.html
'NEW' -- The file doesn't exist (existence is an error). If 'FILE=name' is not specified, then a file named 'fort.n' is opened, where n is the specified logical unit.
Is there a way to force the compiler to use the language specified default behaviour. Alternatively, can I modify the code to perform the expected default behaviour?
The document you cite is not a language specification, it is a description of one particular compiler. The behaviour regarding the file fort.n is compiler specific. For actual standard documents see https://stackoverflow.com/tags/fortran/info
Specifically, the Fortran 2008 says:
9.5.6.10 FILE= specifier in the OPEN statement
1 The value of the FILE= specifier is the name of the file to be connected to the
specified unit. Any trailing blanks are ignored. The file-name-expr
shall be a name that is allowed by the processor. If this specifier is
omitted and the unit is not connected to a file, the STATUS= specifier
shall be specified with a value of SCRATCH; in this case, the
connection is made to a processor-dependent file. The interpretation
of case is processor dependent.
That means that your program is not conforming, because when FILE= is omited, the only permissible value of STATUS= is "SCRATCH".
Gfortran also does create the fort.n files when you write to a unit which you did not open, but not when you execute the open statement with status="new". It should be easy for you to add the file= specifier to the code. You can even use the fort.N names if you insist on them. See Convert integers to strings to create output filenames at run time for the way how to get the integer into the file name.
Another option is to download the Oracle Solaris Studio, it contains the f77 command and is likely to follow the compiler specific document you have cited. It is actually quite a good compiler (if lacking some modern Fortran features) with very good visual debugging and profiling utilities. However, I recommend you to make your code portable and standard conforming first.
Related
Could C++ standards gurus please enlighten me:
Since which C++ standard version has this statement failed because (v) seems to be equivalent to (*&v)?
I.e. for example the code:
#define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
...{...
register int v=1;
int r = DEC(v) ;
...}...
This now produces warnings under -std=c++17 like:
cannot take address of register variable
left hand side of operand must be lvalue
Many C macros enclose ALL macro parameters in parentheses, of which the above is meant only to be a representative example.
The actual macros that produce warnings are for instance
the RTA_* macros in /usr/include/linux/rtnetlink.h.
Short of not using/redefining these macros in C++, is there any workaround?
If you look at the revision summary of the latest C++1z draft, you'd see this in [diff.cpp14.dcl.dcl]
[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future
revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register
storage-class-specifier is ill-formed in this International Standard.
The specifier can simply be removed to retain the original meaning.
The warning may be due to that.
register is no longer a storage class specifier, you should remove it. Compilers may not be issuing the right error or warnings but your code should not have register to begin with
The following is a quote from the standard informing people about what they should do with regards to register in their code (relevant part emphasized), you probably have an old version of that file
C.1.6 Clause 10: declarations [diff.dcl]
Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Common.
Your worry is unwarranted since the file in question does not actually contain the register keyword:
grep "register" /usr/include/linux/rtnetlink.h
outputs nothing. Either way, you shouldn't be receiving the warning since:
System headers don't emit warnings by default, at least in GCC
It isn't wise to try to compile a file that belongs to a systems project like the linux kernel in C++ mode, as there may be subtle and nasty breaking changes
Just include the file normally or link the C code to your C++ binary. Report a bug if you really are getting a warning that should normally be suppressed to your compiler vendor.
Is an implementation allowed to issue a diagnostic message for a well-formed program?
For example some compilers issue a warning about unused expression result when compiling the following well-formed program:
int main() { 0; }
Are such compilers allowed to consider that warning a diagnostic message?
It's perfectly fine to issue a diagnostic, as long as the rules below are met in any corresponding scenario. §1.4/2:
Although this International Standard states only requirements on C ++
implementations, those requirements are often easier to understand if
they are phrased as requirements on programs, parts of programs, or
execution of programs. Such requirements have the following meaning:
If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within
its resource limits, accept and correctly execute that program.
If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as
“conditionally-supported” when the implementation does not support
that construct, a conforming implementation shall issue at least one
diagnostic message.
If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on
implementations with respect to that program.
"Accepting" solely addresses the acknowledgment of the implementation that this is a well-formed program, not the absence of any diagnostics. After all, despite any warnings issued in the process, implementations still yield the object file you asked for.
However, there is one rule concerning templates that does require that there be no diagnostic issued; §14.6/8:
No diagnostic shall be issued for a template for which a valid
specialization can be generated.
An implementation can issue (1)any number of diagnostics it wants, as long as it does issue the required diagnostics.
It must accept correct programs, to the degree that it's able to,
C++14 §1.4/2:
” If a program contains no violations of the rules in this International Standard, a conforming imple-
mentation shall, within its resource limits, accept and correctly execute that program"
but it can issue diagnostics about it.
The C++ standard does not differentiate between error messages and warning messages, but this is a de facto standard. An error message means (by convention) that no binary is produced, because the problem is too severe. A warning message means (by convention) that there is a potential problem, but not a direct violation of language rules, and so a binary is produced unless there are also errors.
Sometimes the lines are a bit blurred, where implementations incorrectly but for pragmatic reasons accept invalid code, with only warnings or even no diagnostics. For new code one may therefore ask the compiler to treat every warning as an error, and aim for completely clean compiles. And as I understand it that's now absolutely not uncommon.
With some compilers, e.g. Visual C++, it can however be problematic, because the compiler issues too many silly-warnings, warnings about perfectly legitimate and non-problematic constructs. Then one has to somehow suppress those warnings. E.g. via #pragma directives, if possible, or by code rewrites.
Happily for Visual C++ there exists a header with such #pragma directives that turn off sillywarnings, compiled about five years ago from a community effort in the comp.lang.c++ Usenet group. And happily, for the community edition of Visual Studio 2015 there is an extension that provides a project template with that header included. These are both by me.
For the code in question,
int main() { 0; }
… instead of suppressing the warning, which generally is a useful one, you should rewrite the code to express your intent explicitly:
int main() { (void)0; }
The (void) cast tells the compiler that it's your intent to discard the value of that expression.
In the case of using this construct for an otherwise unused function argument, you can additionally declare an incomplete class of the same name, to prevent inadvertent use of the name:
(void)arg_name; struct arg_name;
But since it's unconventional it may trip up other programmers – with the compilers I use the error message for later use of the name is not exactly intuitive.
(1) Except as noted by Columbo in his answer, C++14 §14.6/8 “No diagnostic shall be issued for a template for which a valid specialization can be generated.”.
I often see people using the OPEN statement without explicitly specifying a STATUS. In the Fortran 90 and 2008 standards, this is said regarding STATUS:
If UNKNOWN is specified, the status is processor dependent. If this specifier is omitted, the default value is UNKNOWN.
I interpret this to mean, if STATUS is omitted, anything can happen, depending what machine you're using.
Yet, from doing some tests, it seems the default behavior (when STATUS is omitted), is REPLACE. But I cannot find this behavior documented in the gfortran compiler manual (from https://gcc.gnu.org/onlinedocs/).
Question: Is this REPLACE indeed the default behavior in popular compilers like gfortran and ifort? If so, is this actually documented (but I just happened to not find it)?
In common compilers the UNKNOWN behaves quite similarly in all of them. But it definitely is not equivalent to REPLACE! That choice would overwrite your data you want to read!
The IBM XL Fortran manual specifies this:
UNKNOWN, to connect an existing file, or to create and connect a new
file. If the file exists, it is connected as OLD. If the file does not
exist, it is connected as NEW.
UNKNOWN means create the file if not yet existing, then open it.
Is it possible to stop or abort a fortran program with an error code/message in a variable? It seems it's not possible with the intrinsic STOP:
integer :: status = 1
character(len=3) :: err_msg = "err"
stop status
stop err_msg
Both stop calls throw syntax errors on compilation. Am I missing something, or do I have to call stop 1 directly, for example? Or write my own wrapper?
Up to Fortran 2003 the stop code can be either a scalar-char-constant or a sequence of up to 5 digits. A scalar-char-constant means what others might call a string, eg your "err" but not your err_msg.
In Fortran 2008 the stop code can be an expression which returns either a scalar-default-char-constant-expr or a scalar-int-constant-expr. If you had a Fortran 2008 compliant compiler then you could use a parameter (eg something declared as character(len=3), parameter :: err_msg = "err") as a stop code
Of course, the state of implementation of features introduced in the 2003 and 2008 standards varies from compiler to compiler and version to version. It looks as if your compiler version doesn't go beyond the Fortran 2003 standard.
And what your operating system does with the stop code is another matter.
Beyond requiring F2008 - no - not in a variable. In F2008 the stop code must be an integer or character constant expression. Variables are not constants - an expression that relies on the value of a variable is not a constant expression.
If you added the parameter attribute to the declarations of status and err_msg then they would be [named] constants, and could be used as a primary in the constant expression for a stop or error stop statement.
The current standards make no allowances for variables in stop codes. However, they have become more and more flexible as High Performance Mark already stated.
In the upcoming Fortran 2015 standard (working document from 2016/05/01, section 8.4) the stop code can be either a scalar-default-char-expr or a scalar-int-expr. So your code will work with a compliant compiler.
This feature of Fortran 2015 was added in version 7 of GCC.
[NOTE: contains repetition of previous question but posted separately as separate issues]
I am compiling a program which is known to compile with ifort using gfortran. However the compiler fails on the line
PARAMETER (POS='^')
with the compile error:
conv_prof.mac:9.21:
Included at conv_prof.f:811:
PARAMETER (POS='^')
1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)
make: *** [conv_prof.o] Error 1
As it turns out the POS parameter is not used (it is likely a legacy parameter) so I may simply uncomment this line to compile, but I would like to know if anyone might have any idea why this is an issue in gfortran and not ifort?
Cheers,
Derek
The Intel compiler is the descendant of a long line of Fortran compilers. Its ancestors implemented all sorts of non-standard behaviour and, in the true spirit of Fortran, the latest versions of the compiler ought to compile the most ancient codes. You can often tell ifort to warn of non-standard features in your codes by judicious use of compiler flags.
gfortran, on the other hand, does not (by default) accept much in the way of non-standard syntax, other than those forms of non-standard syntax which have been so widely used that many unsuspecting programmers think that they are standard forms (eg real*4 and the like).
Your snippet looks to me to come from the days prior to FORTRAN77 when the language didn't really acknowledge the existence of such new-fangled ideas as non-numeric variables. In this case I recommend that you follow gfortran in disallowing this code, rather than Intel Fortran.
The specific extension here is that ifort allows a program to "assign" a character value into a real object. Perhaps it was intended to use this extension - but a more likely explanation is that a type declaration statement for the parameter pos is missing prior to the PARAMETER statement.
Technically I don't think the standard requires a diagnostic in this case (this isn't a violation of the syntax rules or constraints of the standard - it is a violation of the requirements placed on the program in the body text), but you'll get a diagnostic from ifort if you turn on standards checking (/stand or -stand, depending on your platform).