c++ - C++ 中的 std::complex<double> 与具有链接时优化的 gcc 6 下 Fortran 中的 complex*16 之间的类型不匹配

标签 c++ fortran type-mismatch lto gcc6

我使用了一些从 C++ 调用 Fortran 例程的科学计算代码,它突然开始在 gcc 6 下发出警告。这是准系统问题:

考虑 mult.f90 中定义的 Fortran 子例程 mult:

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

我从 C++ 文件 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;
}

当我使用 g++-6 编译文件时,我收到以下警告:

$ 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

如果我执行以下任一操作,警告就会消失:

  • 用g++-5(版本5.4.1)替换g++-6(我的版本是6.2.0)
  • 在没有-flto 标志的情况下编译
  • 使用 double(而不是 std::complex)和 real*8(而不是 complex*16)

我应该担心吗,或者这是一个我可以忽略的警告?如果是前一种情况,如何解决?

最佳答案

我能找到的最接近的相关问题是 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78562#c6

似乎编译器警告不相关。

我用 C++ 编译了以下代码,并将生成的汇编程序与 fortran 代码进行了比较

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

查看结果:实现略有不同(fortran 似乎甚至不使用单个 GP 寄存器,而 C++ 使用 RBX)但调用约定等完全相同,因此您不必担心

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 ~ $

关于c++ - C++ 中的 std::complex<double> 与具有链接时优化的 gcc 6 下 Fortran 中的 complex*16 之间的类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41041434/

相关文章:

fortran - 对不同形状的数组使用单个虚拟参数

c++ - 函数中的堆栈指针会是形参吗?

python - 将参数从 python 解析为 C++

compilation - Fortran:f 和 F 扩展名之间的区别

c - Windows 中的混合编程

sql - 递归 CTE 错误 : Types do not match

rust - 错误 : type mismatch: expected `usize` , 发现 `i64` 与 `Vec<i64>`

javascript - 类型不匹配;发现 : Some[String] required: play. api.templates.Html

c++ - 点积/w Neon Intrinsics

c++ - 非确定性输出的 CUDA 调试程序