I have inherited some old code where each function is defined as an individual file. I am attempting to write a simple program to test this. I have written test.f a program that at its base calls the function in func.f and then reports the result.
Using ifort -c func.f I created the object file for func.f and then attempted to compile using ifort test.f func.o -o test. This gives me the error that func is not defined as a function or array. Any thoughts?
test.f is
PROGRAM test
REAL :: X,Y
REAL :: FUNC
X = 1.0
Y = func(X)
WRITE(6,*) X
END
and func.f is
FUNCTION func(X)
func = X
RETURN
END
A type declaration statement like
real func
declares that there exists an entity with name func. This may be either:
In isolation, from just this declaration, it is not possible to determine which type of entity func is.
If func is not declared an array and there is no other use of func in the scope which is inconsistent with it being a function, then func is taken to be a function by any reference where it can be a function, such as
real func
print *, func(1)
end
In the absence of an array declaration for func, any use of func in the scope which is inconsistent with func a function will be an error. ifort will generally issue an error message in such case looking like
error #6410: This name has not been declared as an array or a function.
What uses of func in a scope would be inconsistent with func a function? Just about anything that doesn't look like f(...) in an expression. For example:
func some attribute a only variable may havereal :: func ! Function or variable?
save func ! Function can't be SAVEd
func = 1 ! Function name can't be on the left-hand side
print *, func ! Function name can't be used in an expression
print *, func(1) ! Oops, func isn't a function.
end
(All of these uses are consistent with being an array, we just haven't declared it as such.)
Some type declaration statements make it obvious the entity must be a variable:
real :: not_func = 1.
real, allocatable :: definitely_variable
real :: definitely_array(5)
end
That's all to say: if you intend to use real func to declare an external function func with implicit interface and real result, but you get a warning about "not an array or function" when you try to reference it then you've got something somewhere which means func isn't a function and you haven't said it's an array.
It could be quite boring to check for all cases where func could be misused, so let's make our life easier:
real, external :: func
Although without the external attribute specification the EXTERNAL attribute is applied if func is a function, there's certainly no harm it using it. Indeed, it's good: this way we've told the compiler that func really is a function. Which means that any use of func inconsistent with being a function is an error, instead of the function reference.
Try the previous example with external added.
You can also be precise about func being an external function using an interface block (good practice) or a procedure declaration statement.
1 Although a function reference can be a variable, like in
func(1) = 12 ! func a function not an array
this is only the case when the function result is a pointer. A function with implicit interface cannot have a pointer result so this use is not consistent with func a function. We should also avoid confusion with the statement function
real :: func
func(i) = i+1
This is consistent with func a function, but it's not an external function defined elsewhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With