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.
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.
So, I have to admit upfront I already know the answer. I'm asking so others who happen to run into the same problem can find a solution to the problem caused by incorrect documentation.
My environment is VS 2015 C++, wxWidgets 3.0.2, developing on Windows 7.
In some legacy code, calls to wxMkDir were not being checked for success. According to wxWidgets documentation, wxMkDir has a return type of bool, and returns true if successful. However, it returns 0 when successful.
Why?
The answer is two-fold: there are two functions with similar names, wxMkdir and wxMkDir, with the former being documented and the latter not documented. The second part is that the seemingly valid presumption that they will behave the same is not a valid assumption.
The undocumented function wxMkDir maps to wxCRT_MkDir, which in turn maps to wxCRT_MkDirA, then to wxPOSIX_IDENT(mkdir), which creates a platform dependent name for the mentioned POSIX function, mkdir. According to the POSIX documentation for mkdir
Upon successful completion, mkdir() shall return 0. Otherwise, -1 shall be returned, no directory shall be created, and errno shall be set to indicate the error.
So, conditionals like:
if (!wxMkDir(newDir)) {
// handle the error here
}
will fail, but:
if (wxMkDir(newDir) != 0) {
// handle the error here
}
will work as anticipated based on whether the directory was created or not.
The documented function wxMkdir is implemented in wx source file filefn.cpp, and utilizes mkdir, but with conditionals like the above to map to the appropriate bool return value.
wxMkdir() and wxMkDir() are the unfortunate and ugly exceptions to the general rule that wxWidgets provides wxFoo() wrapper for all standard (meaning either ANSI C or POSIX as, in practice, the latter is about as standard and more so than C99) functions foo() existing in both narrow (char*) and wide (wchar_t*) versions.
So, according to this general rule, you'd expect wxMkdir() to behave as std::mkdir() but unfortunately wxMkdir() predated, by quite a few years, Unicode-ification of wxWidgets and so this rule couldn't be implemented for it because of backwards compatibility and another function had to be invented to be just a wrapper for std::mkdir().
And by now, of course, the weight of backwards compatibility is even heavier and there really doesn't seem to be anything reasonable to do here -- other than advising people to use wxFileName::Mkdir() which is unambiguous.
</sad-story>
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.
[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).
I want to find out storage type of variables in a function block. How to check if compiler has elevated auto variable storage to register storage or if variables declared with register storage are honored by compiler? I am assuming by seeing the assembly code of the obj file after optimization would give us an idea. Please list the switch that I need to use with gcc or cl.exe to get this information?
The -S switch in gcc is the one you are looking for.
See ยง3.2 Options Controlling the Kind of Output (GCC manual)
You can look at the generated assembly, but there's no way to programmatically determine this from within your program. Generally be aware that GCC ignores the register keyword except to issue errors if you try to take the address of a register-storage variable, and when used in common with GCC-specific extensions to force a variable into a particular register for use in conjunction with inline asm. No idea what MSVC does.