A type declaration statement like
real func
declares that there exists an entity with name func. This may be either:
- a function with real result; or
- a variable of type real
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:
- giving
func some attribute a only variable may have
- using it as a variable in an assignment statement1
- providing explicit initialization
- using its name when a reference is required
- etc.
real :: 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.