Search code examples
c++linuxmacoscomplextype

identifier "creal" is undefined - seen on Mac but not on Linux


Question

Is the following code wrong or is there an issue with the headers on Mac? The error does not appear on Linux, which leads me to conclude it is not incorrect code, although successful compilation on Linux is not a particularly rigorous test for ISO compliance.

Source Code (MCVE)

#include <stdio.h>
#include <complex.h>

void foo(const double *A, int *size){
   for(int i=0;i < size[0]; ++i){
      for(int j=0;j < size[1]; ++j){
         printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]]));
      }
   }
}

Mac

System Info

$ uname -a
Darwin redacted 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64

Intel compiler

$ icpc -v
icpc version 16.0.2 (gcc version 4.9.0 compatibility)
$ icpc -c ttc-creal.cpp 
ttc-creal.cpp(7): error: identifier "creal" is undefined
           printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]]));
                                  ^

ttc-creal.cpp(7): error: identifier "cimag" is undefined
           printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]]));
                                                             ^

compilation aborted for ttc-creal.cpp (code 2)

LLVM compiler

$ clang++ -v
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$ clang++ -c ttc-creal.cpp 
ttc-creal.cpp:7:33: error: use of undeclared identifier 'creal'
         printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]]));
                                ^
ttc-creal.cpp:7:60: error: use of undeclared identifier 'cimag'
         printf("(%.2e,%.2e) ", creal(A[i + j * size[0]]), cimag(A[i + j * size[0]]));
                                                           ^
2 errors generated.

Linux

System Info

$ uname -a
Linux redacted 2.6.32-573.18.1.el6.centos.plus.x86_64 #1 SMP Wed Feb 10 18:09:24 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

GNU compiler

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/gcc/5.3.0/libexec/gcc/x86_64-unknown-linux-gnu/5.3.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /home/redacted/Work/GCC/gcc-5.3.0/configure --prefix=/opt/gcc/5.3.0 --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --enable-languages=c,c++,fortran --with-tune=native --enable-bootstrap --enable-lto --with-mpfr --with-isl --with-gmp --with-mpc --with-cloog --enable-gold --enable-ld --disable-multilib
Thread model: posix
gcc version 5.3.0 (GCC) 
$ g++ -c ttc-creal.cpp
<no error>

Intel compiler

$ icpc -v
icpc version 17.0.0 Beta (gcc version 5.3.0 compatibility)
$ icpc -c ttc-creal.cpp
<no error>

LLVM compiler

$ clang++ -v
clang version 3.4.2 (tags/RELEASE_34/dot2-final)
Target: x86_64-redhat-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.4.4
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.4.7
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.4.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.4.7
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-redhat-linux/4.4.7
$ clang++ -c ttc-creal.cpp 
<no error>

Investigation

I have read through all of the relevant complex.h, ccomplex and complex headers on my Mac, but cannot see an obvious reason for this issue.


Solution

  • This is just Clang's read of the C++ standard - see that answer - which to me appears to be the correct one. Basically, you are not supposed to use the C99 complex type and the associated functions in C++ and should use std::complex<T> instead. Both complex types should be layout-compatible and you should be able to pass complex data between C and C++ code.

    g++'s complex.h includes both <ccomplex> (in C++11 mode) and the C <complex.h> and therefore the code compiles with GCC (from Homebrew in my case). I don't have the Intel compiler for OS X, but you could check what it does with icpc -E ttc-creal.cpp | grep complex and observe the sequence of include file expansions.

    Clang:

    $ clang++ -E ttc-creal.cpp | grep "^# 1 " | grep complex
    # 1 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/complex.h" 1 3
    # 1 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ccomplex" 1 3
    # 1 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/complex" 1 3
    

    GCC:

    $ g++-5 -E ttc-creal.cpp | grep "^# 1 " | grep complex
    # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/complex.h" 1 3
    # 1 "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/complex.h" 1 3 4
    
    $ g++-5 -std=c++11 -E ttc-creal.cpp | grep "^# 1 " | grep complex
    # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/complex.h" 1 3
    # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/ccomplex" 1 3
    # 1 "/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/complex" 1 3
    # 1 "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/complex.h" 1 3 4
    

    You can force Clang to include <path to SDK>/usr/include/complex.h by e.g.:

    #include "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/complex.h"
    

    and your MCVE will compile, but doing so is probably a very Bad Idea (tm).

    By the way, the same behaviour is observed on FreeBSD 10.2-RELEASE with Clang 3.4.1 (error) and GCC 4.8.5 (success).

    All credit goes to Potatoswatter - the author of the the answer referenced at the top.