1

I use some scientific computing code which calls Fortran routines from C++, which has suddenly started giving a warning under gcc 6. Here is the barebones issue:

Consider a Fortran subroutine mult defined in mult.f90:

subroutine mult(c)
  complex*16 c
  c = c * c
  return
end

I call this from a C++ file test.cpp:

#include <complex>
#include <iostream>

extern "C" void mult_(std::complex<double> *);

int main() {
  std::complex<double> z (1,0);
  mult_(&z);

  std::cout << z << "\n";
  return 0;
}

When I compile the files using g++-6 I get the following warning:

$ g++-6 -O3 -W -Wall test.cpp mult.f90 -flto -o test2

test.cpp:4:17: warning: type of ‘mult_’ does not match original declaration [-Wlto-type-mismatch]
 extern "C" void mult_(std::complex<double> *);
                 ^
mult.f90:1:1: note: ‘mult’ was previously declared here
 subroutine mult(c)
 ^
mult.f90:1:1: note: code may be misoptimized unless -fno-strict-aliasing is used

The warning goes away if I do any of the following:

  • Replace g++-6 (version I have is 6.2.0) with g++-5 (version 5.4.1)
  • Compile without the -flto flag
  • Use double (instead of std::complex) and real*8 (instead of complex*16)

Should I be concerned, or is this a warning that I can ignore? In the former case, how can I solve the issue?

Raziman T V
  • 480
  • 1
  • 4
  • 12
  • 1
    For interoperability with C/C++, you probably want to look at `iso_c_binding`. Then you can change the non-standard `complex*16` to `complex(c_double_complex)` and use `bind(C)`. This has the added benefit of not having to simulate the Fortran name-mangling in your C++ code (i.e. you can just refer to `mult` instead of `mult_`). – Yossarian Dec 08 '16 at 15:40
  • That does not seem to help, I get the same warning when ISO C binding is used. – Raziman T V Dec 08 '16 at 15:55

1 Answers1

1

The closest related issue I could find is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78562#c6

It seems like the compilers warning is not relevant.

I compiled the following code in C++ and compared the generated assembler with the fortran code

extern "C" 
{
  void mult_(std::complex<double> *z)
  {
      *z = *z * *z; 
  }
}

See the results : The implementation is slightly different (fortran seems to not use even a single GP register, whereas C++ uses RBX) but the calling convention etc are exactly same, so you need not worry

rep ~ $ g++ -S -O3 -Wall test2.cpp
rep ~ $ g++ -S -O3 mult.f90
rep ~ $ cat mult.s

-----------------------------Snip----------------------------

.LFB0:
        .cfi_startproc
        movsd   (%rdi), %xmm0
        movsd   8(%rdi), %xmm1
        movapd  %xmm0, %xmm2
        movapd  %xmm1, %xmm3
        mulsd   %xmm0, %xmm2
        mulsd   %xmm1, %xmm3
        mulsd   %xmm1, %xmm0
        subsd   %xmm3, %xmm2
        addsd   %xmm0, %xmm0
        movsd   %xmm2, (%rdi)
        movsd   %xmm0, 8(%rdi)
        ret
        .cfi_endproc

-----------------------------Snip----------------------------

rep ~ $ cat test2.s

-----------------------------Snip----------------------------

.LFB1991:
        .cfi_startproc
        movsd   8(%rdi), %xmm3
        pushq   %rbx
        .cfi_def_cfa_offset 16
        .cfi_offset 3, -16
        movsd   (%rdi), %xmm2
        movq    %rdi, %rbx
        movapd  %xmm3, %xmm1
        movapd  %xmm2, %xmm0
        call    __muldc3
        movsd   %xmm0, (%rbx)
        movsd   %xmm1, 8(%rbx)
        popq    %rbx
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc

-----------------------------Snip----------------------------
rep ~ $
rep_movsd
  • 6,675
  • 4
  • 30
  • 34