GNU C++ how to check when -std=c++0x is in effect? - c++

My system compiler (gcc42) works fine with the TR1 features that I want, but trying to support newer compiler versions other than the systems, trying to accessing TR1 headers an #error demanding the -std=c++0x option because of how it interfaces with library or some hub bub like that.
/usr/local/lib/gcc45/include/c++/bits/c++0x_warning.h:31:2: error: #error This file requires compiler and library support for the upcoming ISO C++ standard, C++0x. This support is currently experimental, and must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
Having to supply an extra switch is no problem, to support GCC 4.4 and 4.5 under this system (FreeBSD), but obviously it changes the picture!
Using my system compiler (g++ 4.2 default dialect):
#include <tr1/foo>
using std::tr1::foo;
Using newer (4.5) versions of the compiler with -std=c++0x:
#include <foo>
using std::foo;
Is there anyway using the pre processor, that I can tell if g++ is running with C++0x features enabled?
Something like this is what I'm looking for:
#ifdef __CXX0X_MODE__
#endif
but I have not found anything in the manual or off the web.
At this rate, I'm starting to think that life would just be easier, to use Boost as a dependency, and not worry about a new language standard arriving before TR4... hehe.

There seems, with gcc 4.4.4, to be only one predefined macro hinting that -std=c++0x is in effect:
#define __GXX_EXPERIMENTAL_CXX0X__ 1
I don't have access to gcc 4.5.0 , but you can check that one yourself:
[16:13:41 0 ~] $ g++ -E -dM -std=c++0x -x c++ /dev/null >b
[16:13:44 0 ~] $ g++ -E -dM -std=c++98 -x c++ /dev/null >a
[16:13:50 0 ~] $ diff -u a b
--- a 2010-06-02 16:13:50.200787591 +0200
+++ b 2010-06-02 16:13:44.456912378 +0200
## -20,6 +20,7 ##
#define __linux 1
#define __DEC32_EPSILON__ 1E-6DF
#define __unix 1
+#define __GXX_EXPERIMENTAL_CXX0X__ 1
#define __LDBL_MAX_EXP__ 16384
#define __linux__ 1
#define __SCHAR_MAX__ 127
For one-line command do,
g++ -E -dM -std=c++98 -x c++ /dev/null > std1 && g++ -E -dM -std=c++0x -x c++ /dev/null > std2 && diff -u std1 std2 | grep '[+|-]^*#define' && rm std1 std2
gives you something like:
+#define __GXX_EXPERIMENTAL_CXX0X__ 1

If you compile with -std=c++0x, then __GXX_EXPERIMENTAL_CXX0X__ will be defined.

Well, from gcc-4.7 onwards you'll be able to check __cplusplus:
"G++ now sets the predefined macro __cplusplus to the correct value, 199711L for C++98/03, and 201103L for C++11"
This should be the correct, standard-compliant way to do it. Unfortunately, it doesn't work for most gcc installed in the wild.

Related

How do I distinguish -std=c++17 and -std=gnu++17 at compile time? checking macros?

I am using the __int128 extension of g++. The problem with -std=c++17 is that some of the C++ library does not have all the support for that extension (i.e. std::make_unsigned<> fails). When using -std=gnu++17 it works fine.
I've added a header file that allows for the <limit> to work with __int128 when using -std=c++17 and I'd like to keep it for now, but when using -std=gnu++17 it breaks (because it is already defined). So I was thinking to add a condition like so:
#if !(<something>)
...
#endif
if the compiler already supports the limits with __int128.
My question is: what is that <something> I could check to distinguish between the standard and the GNU c++17 libraries?
I did this:
$ diff <(g++-11 -std=c++17 -E -dM -x c++ /dev/null|LC_ALL=C sort) \
<(g++-11 -std=gnu++17 -E -dM -x c++ /dev/null|LC_ALL=C sort)
And the output was:
180a181,182
> #define __GLIBCXX_BITSIZE_INT_N_0 128
> #define __GLIBCXX_TYPE_INT_N_0 __int128
315d316
< #define __STRICT_ANSI__ 1
424a426,427
> #define linux 1
> #define unix 1
That's not definitive, of course, but it's maybe a start.
So you could check for __STRICT_ANSI__ (indicating that there are no Gnu extensions), but perhaps the undocumentable __GLIBCXX_BITSIZE_INT_N_0 is more direct.

warning: 'assume_aligned' attribute directive ignored

I just started with C++ and i think the best way is to look at source codes. I have code as follows in the header file.
#ifdef _MSC_VER
#define MYAPP_CACHE_ALIGNED_RETURN /* not supported */
#else
#define MYAPP_CACHE_ALIGNED_RETURN __attribute__((assume_aligned(64)))
#endif
I am using gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) and its quite old. I get this warning during compilation:
warning: 'assume_aligned' attribute directiv e ignored [-Wattributes] –
How can I make the if statement more specific to fix the the warning during compilation?
It seems that assume_aligned is not supported in RHEL's GCC (it hasn't been backported to upstream gcc-4_8-branch and also not available in Ubuntu 14.04's GCC 4.8.4 so that wouldn't be surprising).
To emit a more user-friendly diagnostics you can do an explicit check for GCC version in one of your headers:
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9)
# warning "Your version of GCC does not support 'assume_aligned' attribute"
#endif
But this may not work if your distro vendor has back-ported assume_aligned from upstream (which is not the case for RedHat and Ubuntu but who knows about other distros). The most robust way to check this would be to do a build-time test in configure script or in Makefile:
CFLAGS += $(shell echo 'void* my_alloc1() __attribute__((assume_aligned(16)));' | gcc -x c - -c -o /dev/null -Werror && echo -DHAS_ASSUME_ALIGNED)
This will add HAS_ASSUME_ALIGNED to predefined macro if the attribute is supported by compiler.
Note that you can achieve similar effect with __builtin_assume_aligned function:
void foo() {
double *p = func_that_misses_assume_align();
p = __builtin_assume_aligned(p, 128);
...
}

Use CXX to query preprocessor defines?

I have a GNUmakefile that respects CXX and CXXFLAGS. It also performs some platform and architecture tests. Currently, the makefile assumes the host and target are the same:
IS_X86 = $(shell uname -m | $(EGREP) -c "i.86|x86|i86|amd64")
In an effort to improve robustness, I want to ask the tools what it is compiling for. I've come up with the following, but I'm not sure it is correct.
$ export CXX=clang++
$ export CXXFLAGS="-DNDEBUG -g2 -O3 -m32"
$ $CXX $CXXFLAGS -dM -E - < /dev/null | egrep "(i386|x86_64)"
#define __i386 1
#define __i386__ 1
#define i386 1
$ export CXX=clang++
$ export CXXFLAGS="-DNDEBUG -g2 -O3"
$ $CXX $CXXFLAGS -dM -E - < /dev/null | egrep "(i386|x86_64)"
#define __x86_64 1
#define __x86_64__ 1
My question is, will the above - with CXX and CXXFLAGS - work reliably to detect a target? Or do I need something else?
Here's the two reasons I ask. First, my experience with Autotools indicates something different. When Autotools performs a test like above, they test CPP, and sometimes CPP or CXX needs to include --isysroot (or other hacks) to get things configured properly.
Second, some toolchains, like Clang, integrate other components (like a preprocessor or assembler), so I can't use CPP directly under all circumstances.
In fact, doing something as simple as $CXX -Wa,-v - </dev/null (ask assembler for its version) results in an "unsupported option" error under Clang when using its integrated assembler. (Cf., With integrated assembler enabled, fail to fetch version string of assembler).
And just in case: this is not an Autools or Cmake project. It does not use Boost or any other libraries. Its a stand alone C++03 project.
My question is, will the above - with CXX and CXXFLAGS - work reliably to detect a target?
The answer is Yes, it will. The preprocessor or compielr driver (passing down to preprocessor) will mostly yield expected target defines with all else being equal. Notable exception is GCC and ARMv8/Aarch64, which is missing a slew of expected defines.
The thing to avoid is uname -m (and friends). Uname reports information on the host, and not the target.

How can I reliably detect the version of clang at preprocessing time?

Apparently, the clang bundled with Xcode doesn't respect the upstream __clang_major__ and __clang_minor__ values, and instead reports an Xcode user-facing version of some sort.
Here are, for reference, the values for the various MacPorts installs of clang. They seem to respect the upstream release identifiers. I get similar values when testing on Linux.
➜ prohibit-clang-3.2 /opt/local/bin/clang++-mp-3.2 -dM -E -x c /dev/null |
grep __clang_m
#define __clang_major__ 3
#define __clang_minor__ 2
➜ prohibit-clang-3.2 /opt/local/bin/clang++-mp-3.3 -dM -E -x c /dev/null |
grep __clang_m
#define __clang_major__ 3
#define __clang_minor__ 3
➜ prohibit-clang-3.2 /opt/local/bin/clang++-mp-3.4 -dM -E -x c /dev/null |
grep __clang_m
#define __clang_major__ 3
#define __clang_minor__ 4
However, for some reason, the Apple provided clang has __clang_major__ and __clang_minor__ versions that track the Xcode version, not the base clang revision:
➜ prohibit-clang-3.2
/Applications/Xcode-4.6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
-dM -E -x c /dev/null | grep __clang_m
#define __clang_major__ 4
#define __clang_minor__ 2
➜ prohibit-clang-3.2
/Applications/Xcode-4.6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
--version
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
➜ prohibit-clang-3.2
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
-dM -E -x c /dev/null | grep __clang_m
#define __clang_major__ 5
#define __clang_minor__ 0
➜ prohibit-clang-3.2
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
--version
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
➜ prohibit-clang-3.2 /usr/bin/clang++ -dM -E -x c /dev/null | grep __clang_m
#define __clang_major__ 5
#define __clang_minor__ 0
This seems pretty awful, because it means you can't write conditional compilation lines like the following that will work accurately across both the Apple vendored clang, and clang built normally from the clang sources or from distro packages:
#if !defined(__clang__) || (__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ > 2))
// Thing that doesn't work for clang-3.2 due to an optimization bug.
#endif
I'd hate to need to extend that already pretty terrible preprocessor check to account for two different clang versioning schemes, one normal and one Apple. I'm not even sure how I could reliably detect that this is 'Xcode clang' rather than normal clang.
Does anyone have any suggestions on how to work around this? Is there a flag to pass to Apple's clang that will instruct it to report its 'true' version? Or has Apple doomed us to never be able to reliably use __clang_major__ and __clang_minor__? Are these not the macros I should be using here?
If the feature checking macros don't cover what you need to check for then you do need to treat vendor releases separately as they may have very different content from the open source LLVM releases. You can use __apple_build_version__ to check for a specific Apple LLVM version.

How to determine compilation flags at compile time on OS/X?

If I compile with -fPIC on x86 Linux with gcc 4.1, then the definition __PIC__ is set to 1 and the preprocessor can act on that at compile time. However, on OS/X under gcc 4.01 that is not the case. Is there some other way to determine the setting of -fPIC at compile time on OS/X?
A general facility for querying compilation flags at the preprocessor level under OS/X would be even more helpful, but I wasn't able to find anything like that.
-fPIC is the default on OS X. gcc 4.0.1 on my crufty old OS X 10.4 machine does define __PIC__; or, when it is explicitly turned off with -fno-PIC, it does not.
The settings of compilation flags are not in general exported to the preprocessor, except for certain special cases, which may vary across different GCC targets.
But you can see the effects of changing flags on the predefined preprocessor definitions, on any platform, using the -dM option to gcc, which dumps the preprocessor definitions after preprocessing is complete.
e.g. from a terminal window:
$ gcc -xc++ -dM -E /dev/null | sort > /tmp/defaults.txt
$ gcc -fno-PIC -xc++ -dM -E /dev/null | sort > /tmp/nopic.txt
$ diff /tmp/defaults.txt /tmp/nopic.txt
65d64
< #define __PIC__ 1
$
(I've specified -xc++ there because I'm preprocessing /dev/null rather than a file with an extension that indicates the language variant. That could also be -xc, -xobjective-c or -xobjective-c++.)