I found this error! How can I resolve it?
Compiling the source code....
$gfortran -std=f95 main.f95 -o demo 2>&1
main.f95:14:
f(x)=exp(x)
1
Error: Unclassifiable statement at (1)
If
f(x)=exp(x)
is a valid Fortran expression then it might be a statement function. This is a now-obsolescent feature that is best avoided. I'm not very familiar with gfortran, it seems possible that the compilation option std=f95 is saving you from yourself by not letting you use the feature.
It's possible that it assigns the value of exp(x) to the x-th element of an array called f but that suggests that x is an integer.
It's also possible that that is not the cause of the compilation error. It's possible that the statement function is in the wrong place within the source unit. Fortran is very particular about the ordering of statements in source unit. Statement functions must appear before any executable statements in a source unit.
Related
The Code
The following MWE describes what I want to use (note that I did not design this, I am merely trying to use someones code, I would not usually use global variables).
PROGRAM MAIN
IMPLICIT NONE
integer :: N
real(8), allocatable :: a(:,:)
N=3
allocate(a(N,3))
a=initialize_array()
CONTAINS
function initialize_array() result(a)
IMPLICIT NONE
real(8) :: a(N,3)
a=1
end function initialize_array
END PROGRAM MAIN
The Problem
gfortran gives an error which reads Error: Variable 'n' cannot appear in the expression at (1), pointing to to the real(8) :: a(N,3) inside the function.
In a subroutine it would work, so what might be the problem here?
The question
Why does ifort (v. 15.0.3) compile this, while gfortran (v. 4.8.4) does not?
As has been commented by others, it is hard to say whether something is clearly allowed: the language is mostly based on rules and constraints giving restrictions.
So, I won't prove that the code is not erroneous (and that gfortran is not allowed to reject it), but let's look at what's going on.
First, I'll object to one thing given by High Performance Mark as this is slightly relevant:
The declaration of an array with a dimension dependent on the value of a variable, such as a(N,3), requires that the value of the variable be known (or at least knowable) at compile time.
The bounds of an explicit shape array need not always be given by constant expressions (what we loosely define as "known/knowable at compile time"): in some circumstances an explicit shape array can have bounds given by variables. These are known as automatic objects (and the bounds given by specification expressions).
A function result is one such place where an automatic object is allowed. In the question's example for the declaration of the function result, N is host associated and forms a specification expression.
Rather than exhausting all other constraints to see that the declaration of a truly is allowed, let's look at how gfortran responds to small modifications of the program.
First, a trimmed down version of the question's code to which gfortran objects.
integer n
contains
function f() result(g)
real g(n)
end function f
end program
The function result for f has the name g. It doesn't matter what we call the function result, so what happens when we call it f?
integer n
contains
function f()
real f(n)
end function f
end program
This compiles happily for me.
What if we frame this first lump in a module instead of a main program?
module mod
integer n
contains
function f() result(g)
real g(n)
end function f
end module
That also compiles.
The natural conclusion: even if gfortran is correct (we've missed some well-hidden constraint) to reject the first code it's either horribly inconsistent in not rejecting the others, or the constraint is really quite strange.
I think this might be an explanation, though like #VladimirF I can't actually either recall or find the relevant section (if there is one) of the standard.
This line
real(8) :: a(N,3)
declares that the result of the function is an array called a. This masks the possibility of the same name referring to the array a by host association. The a inside the function scope is not the a in the program scope.
The declaration of an array with a dimension dependent on the value of a variable, such as a(N,3), requires that the value of the variable be known (or at least knowable) at compile time. In this case giving n in the host scope the attribute parameter fixes the problem. Though it doesn't fix the poor design -- but OP's hands seem tied on that point.
It doesn't surprise me that the Intel compiler compiles this, it compiles all sorts of oddities that its ancestors have compiled over the years for the sake of backwards compatibility.
I only offer this half-baked explanation because experience has taught me that as soon as I do one of the real Fortran experts (IanH, francescalus, (usually) VladimirF) will get so outraged as to post a correction and we'll all learn something.
When I run my code I get the following error for all the statements that have the following format. Is there any problem with the type statement? If yes kindly provide me with a solution. I running my code on a Ubuntu 14.10 system. The program is very long hence I am not posting it now however if required I can surely send it.
recfunk_ascii.f:622.12:
type *,'enter back-azimuth limits ib1,ib2 (integers!)'
1
Error: Invalid character in name at (1)
Type is an obsolete and completely non-standard statement (see http://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vnbi/index.html). It is not portable because many compilers do not recognize it. It should be changed to a PRINT statement, as #francescalus suggest in the comment.
print *,'enter back-azimuth limits ib1,ib2 (integers!)'
Am working with some legacy FORTRAN code. The author defined a function (not a subroutine, but a function -- that's going to be important) called REDUCE_VEC(). It accepts a 1D array and returns a scalar real*8. So, if you want to "reduce" your vector, you make a call to the function
RV = REDUCE_VEC(V1)
and everything is fine. But occasionally, he has lines that look like
CALL REDUCE_VEC(V2)
So, two questions: 1) What the heck would this second form of the call do? (Note that there is no way to return data.) 2) This won't even compile under gfortran, even though it did with PGI, so is this even legal FORTRAN?
Thanks.
This will compile with many processors if the interface is implicit, because the compiler cannot check that, it just calls some symbol. Consider the following:
function f(a)
dimension a(*)
f = 0
do i=1,10
f = f + a(i)
end do
end function
program p
call f([1.,2.,3.,4.,5.,6.,7.,8.,9.,10.])
end program
Compiles and does not even crash immediately with ifort, whereas sunf90 and gfortran will compile that only if it is in separate source files and then the result also does not crash on my machine. If the return value is placed in register, it may cause no harm to the rest of the program, but a stack corruption is quite likely otherwise.
It is not legal Fortran. As presented it is more than likely a programming error (it is possible for the same name in different scopes to refer to different things, but that's not what is implied by the question). If the Fortran processor happens to support an extension to the language that allows this, then what happens is up to the Fortran processor. Otherwise, "anything" could happen, where "anything" could include (but is not limited to) "nothing", or "very, very bad things".
I have a code like this
const int Value = 123 * 2 + GetOffset();
GetOffset is a constexpr function returning int.
How can I make sure this expression is indeed evaluated at compile time?
Why don't you use constexpr for Value too? I think it will ask the compiler to evaluate it,
constexpr int Value = 123 * 2 + GetOffset();
if the function GetOffset() is simple and meet the requirements of constexpr.
The requirements are
the function must have a non-void return type.
the function body cannot declare variables or define new types.
the body may contain only declarations, null statements and a single return
statement.
Since Getoffset() returns int, it meets the first one.
You can't ensure the compiler does this. You generally need to enable optimization, including some level of function inlining. What these options are depend on your compiler and its version.
You can check the generated assembly to see if it contains a call to GetOffset or just uses a constant determined by the compiler.
what if you declare 'Value' as constexpr too? Actually you can probalby never be sure if something is evaluated at compilation time, however in this case there is no reason why it could not be evaluated.
One possibility is to use std::ratio. From section 20.10.1 of the C++11 standard:
This subclause describes the ratio library. It provides a class template ratio which exactly represents any finite rational number with a numerator and denominator representable by compile-time constants of type intmax_t.
So according to the standard, this would only be valid for a compile-time constant:
const int value = std::ratio<123 * 2 + GetOffset()>::num;
So this would guarantee that the expression is evaluated at compile time. However, it doesn't also guarantee that the expression is not evaluated at run time.
You can't be absolutely sure; the compiler is only required to generate code with the specified behaviour, and calculating it at compile- or run-time would not change the behaviour.
However, the compiler is required to be able to evaluate this at compile time, since it can be used where only compile-time constants are allowed such as array sizes and template arguments; so there's no reason why a sane compiler shouldn't perform that obvious optimisation. If the compiler doesn't (at least with optimisations enabled), throw it away and find a better one.
You can check the assembly produced by the compiler to see whether it calculates the value; but this in itself doesn't guarantee that future builds will do the same.
Considering that I have not used C++ in over half a decade now, the chances of the suggestion being way of the mark are quite high, but what about using inline for the function.
If the function returns a certain predefined value, available at the compile time, then the compiler should be able to make use of that value.
Create a separate source file with the expression. Evaluate printf("#define MyExpression %d.\n", expression);. When building your project, compile this source file for the native system and execute it. Include the resulting output as a header in your regular sources.
If you want to confirm that the initializer is a constant expression than you can use the constexpr specifier:
constexpr int Value = 123 * 2 + GetOffset();
It will fail to compile if it isn't a constant expression.
It is theoretically unspecified whether a constexpr variable Value is actually calculated during translation - but in practice you can be sure it is.
Just assert it: static_assert(Value == 123 * 2 + GetOffset(), "constexpr");
Doesn't get any simpler than that.
I am compiling a program which is known to compile with ifort using gfortran. However, the compiler fails on the line
WRITE (11,1325) ((IFILE,FILENAME(IFILE)),IFILE=1,IFILES)
with the compile error:
main_file.f:205.32:
WRITE (11,1325) ((IFILE,FILENAME(IFILE)),IFILE=1,IFILES)
1
Error: Expected PARAMETER symbol in complex constant at (1)
make: *** [main_file.o] Error 1
Changing this line to (note removal of '(' and ')')
WRITE (11,1480) (IFILE,FILENAME(IFILE),IFILE=1,IFILES)
to match the subsequent line
1480 FORMAT (1X,I1,' ',A40)
solves the problem, but I was wondering if anyone may know why is this mistake not captured by the Intel compiler. In this instance, it seems to be gfortran which is giving the correct behaviour. My compile flags are:
gfortran -fno-automatic -mcmodel=medium -O2 -ffast-math main_file.o -o main_file
As others have posted in the similar recent questions, due to its heritage the Intel compiler allows a number of extensions by default. The compiler will emit a diagnostic if you supply the appropriate standard check option (/stand on Windows, for example).
I'm not sure of the specific source of this particular extension, but it covers a somewhat occasional syntax misunderstanding, where people would put the "arguments" to the write or read "function" in parentheses...
READ (*,*) (not_valid_syntax)
(In a write statement an expression in parentheses is itself an expression, and that is a valid output list item - a few years back the Intel compiler would get a bit confused about that.)
Quite an interesting issue. It works only for arrays:
print *, ((1,["a","b"]),i=1,10)
end
works, but
print *, ((1,"a"),i=1,10)
end
fails with ifort:
: error #6063: An INTEGER or REAL data type is required in this context. ['a']
print *, ((1,"a"),i=1,10)
God knows what the parser thinks it is in the first working case, maybe an incomplete nested implied do? For sure it is not legal Fortran syntax and should by refused by compiler which requires standard Fortran. Intel may have reasons to accept this syntax.