1

I am currently testing a Fortran module on two different compilers (ifort on a linux machine, gfortran on a mac), and I've run into a strange problem I cannot explain.

I have a simple module with one public subroutine and two functions it calls which are private. It looks something like this:

module test
implicit none
private
public :: publicsub

contains

subroutine publicsub(x,y,arg)
implicit none
integer(kind=4), intent(in):: x,y
real(kind=8),   intent(out):: arg

arg = func1(x)*10. / func2(y)

end subroutine publicsub

integer(kind=4) function func1(x)
implicit none
integer(kind=4), intent(in):: x

func1 = x*x;

end function func1

integer(kind=4) function func2(x)
implicit none
integer(kind=4),intent(in):: x

func2 = x*x*x

end function func2
end module test

Here is the main program to test:

program sgtest

use test

implicit none  
integer(kind=4) :: a,b
real(kind=8) :: output

a = 3
b = 4

call publicsub(a,b,output)

write *, output

end program sgtest 

I can get the module to compile using ok by itself. When I compile the main program it will not compile under the ifort compiler on my linux box unless I also declare the function calls as integers in the main subroutine publicsub, I.E., I add this code to publicsub:

integer(kind=4) :: func1,func2

And then it works just fine. However, when I compile this on gfortran on my mac, I got these error messages:

Undefined symbols for architecture x86_64:

 "_func1_", referenced from:
     ___test_MOD_publicsub in ccnj2Zt6.o
 "_func2_", referenced from:
     ___test_MOD_publicsub in ccnj2Zt6.o

ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status

But then when I comment this declaration out, everything compiles and runs as expected with gfortran. Ironically, I get a similar error message from ifort on the linux box without these declarations.

So what's going on here? Is this a Fortran90/95 vs GNU Fortran extensions issue, or have I done something structurally that is a no-no with the module?

Fortranner
  • 2,525
  • 2
  • 22
  • 25
txpaulm
  • 161
  • 6
  • 1
    Show your main program. Do you `USE` the module correctly? You definitely should not add that line. See also http://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind-4 why not to use `(kind=4)`. – Vladimir F Героям слава Mar 21 '15 at 09:40
  • Also do not use tag `fortran90`, without the generic tag `fortran`. `fortran90` is only for specific questions about this somewhat old revision. – Vladimir F Героям слава Mar 21 '15 at 09:46
  • Vladimir, I'll add the main program. Sorry I did not include that earlier. – txpaulm Mar 21 '15 at 15:15
  • is the single colon in your public statement a typo? – agentp Mar 22 '15 at 12:19
  • @Vladimir F: Thank you for the tip on (kind=4). I work with a lot of legacy code ported from f77 and there is a huge mixture of integer*4 and (kind=4) (along with other types). – txpaulm Mar 23 '15 at 14:15
  • `integer*4` is safe, but non-standard. `kind=4` may turn up to be different from `*4`, so it is better to use `kind=some_constant` and set the constant in a single place. You can even set it to `4` if you feel so. – Vladimir F Героям слава Mar 23 '15 at 14:19
  • verified your code works just fine with ifort under windows (after fixing `write *,` to `write(*,*)` ) Adding the extra declaration for `func1,func2` throws an `unresolved symbol` error You should probably take this up with intel support. – agentp Mar 23 '15 at 17:06
  • @agentp: thank you for the confirmation. I think I figured out what was wrong. What I also should have included (which I did not) was the compiler command. So in the future, it's useful to include that as well as the error messages and the code! – txpaulm Mar 24 '15 at 13:28

1 Answers1

1

We cannot ay what you do wrong in your original code, because you do not show your main program. But to answer the question from the title:

When you do this:

subroutine publicsub(x,y,arg)
  integer(kind=...), intent(in):: x,y
  real(kind=...),   intent(out):: arg
  !!
  integer(kind=...) :: func1,func2
  !!

  arg = func1(x) * 10 / func2(y)

end subroutine publicsub

You are declaring, that func1 and func2 are external function distinct from the func1 and func2 in the module.

And because you have no such external functions outside of the module, the linker cannot find them and the linking ends with an error.

The added line should definitely not be there.