Determine gcc-toolchain version in clang++ preprocessor - c++

According to cppreference, the gcc libstdc++ supports the parallelism TS. In layperson terms and for what's relevant for me that means #include <execution> works in g++ 9 and doesn't work in g++ 8 or before. In my source code I can handle this with
#if ( defined( __GNUC__ ) && __GNUC__ > 8 )
# define can_use_std_execution
# include <execution>
#endif
For my clang++ builds, the availability of <execution> depends on the --gcc-toolchain that I use. So instead of checking the __clang_major__, I'd like to check the gcc libstdc++ version in the preprocessor.
As far as I see in this compiler-explorer example, __GNUC__ is defined in clang but the compilation command is
-g -o /tmp/compiler-explorer-compiler120120-1672-4ffux6.smufm/output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-8.3.0 -fcolor-diagnostics -fno-crash-diagnostics /tmp/compiler-explorer-compiler120120-1672-4ffux6.smufm/example.cpp
i.e. the gcc toolchain is from gcc 8.3.0, but the value of __GNUC__ is 4.
What's a good way to query the gcc toolchain version in the preprocessor with clang? Ideally a way that checks the libstdc++ version in a way that's compatible for g++ and clang++ such that I don't have write a spaghetti if that checks the compiler first.

Grepping for ^#.*define.*9 in the compiler headers of gcc 9 it seems that
#include <bits/c++config.h>
#if _GLIBCXX_RELEASE > 8
# include <execution>
#endif
can do the job. From this conformance view this variable was introduced with the toolchain of gcc 7.

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);
...
}

putchar_unlocked doesn't work in C++ 14 standard

I am using g++ (GCC) 4.9.3 on Cygwin. I am not able to use getchar_unlocked or putchar_unlocked with C++ 14 standard.
Consider this sample code
#include <cstdio>
int main() {
putchar_unlocked('1');
return 0;
}
When I compile and run with
g++ foo.cpp && a.exe && rm ./a.exe
I am getting expected output 1.
But when I do
g++ -std=c++14 foo.cpp && a.exe && rm ./a.exe
I am getting error saying putchar_unlocked was not declared.
foo.cpp: In function 'int main()':
foo.cpp:4:22: error: 'putchar_unlocked' was not declared in this scope
putchar_unlocked('1');
^
putchar_unlocked isn't part of any version of the C or C++ standards, and Cygwin doesn't implement any other standard that does provide putchar_unlocked.
Cygwin does provide putchar_unlocked as a non-standard extension, but you need to actually leave non-standard extensions enabled.
The default -std= version is -std=gnu++03 (or one of its synonyms). This is C++03 plus extensions. You changed it to -std=c++14. This is C++14 without extensions. Use -std=gnu++14 to leave extensions enabled.
putchar_unlocked is not part of any C++ standard. It is part of POSIX standard, but defining -std=c++14 causes gcc to define __STRICT_ANSI__ macro. Cygwin uses Newlib for C standard library, and from its sources we can see that this prevents putchar_unlocked from being declared, and also that there isn't any other macro to enable it anyway.
Therefore, we need to get rid of __STRICT_ANSI__. Using -std=gnu++14 should do that:
g++ -std=gnu++14 foo.cpp && a.exe && rm ./a.exe
A comment under the question points out that the code works with Ideone. This is probably, because Ideone runs on different platform (such as Linux), which probably has glibc, which provides putchar_unlocked with different conditions (from this manual page):
Feature Test Macro Requirements for glibc (see
feature_test_macros(7)):
getc_unlocked(), getchar_unlocked(), putc_unlocked(),
putchar_unlocked():
_POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE

Which C++ standard header defines SIZE_MAX?

I'm working on an existing C++ codebase that happens to use SIZE_MAX in a couple of places. I did some refactoring and now SIZE_MAX is not defined in one of the modules. This problem appeared when Travis-CI attempted to build the project on Linux. It worked fine before I refactored stuff, but tracing which exact header files were included is difficult.
In an attempt to replicate the problem locally, I installed an Ubuntu VM with the default gcc and was able to reproduce it. Here's the relevant source:
#include <stddef.h>
int main()
{
size_t a = SIZE_MAX;
}
The command line is simply:
g++ a.cpp
The error is:
a.cpp: In function ‘int main()’:
a.cpp:5:16: error: ‘SIZE_MAX’ was not declared in this scope
System info:
$ uname -a
Linux quartz 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
I have tried including cstdint, stdint.h, limits.h, inttypes.h, stdio.h, stdlib.h, and probably some others, and I can't figure out which specific header file I need for SIZE_MAX.
It is important to note that the program I'm working on compiled fine, with SIZE_MAX used in various places, before I made some changes. The changes I made caused it to become undefined in one .cpp source file where it was used (the others continue to be fine). So there exists some header file on my system where it is correctly defined.
It's likely that some header defined __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS before stdint.h was included.
Compiling on Linux with g++ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS a.cpp should fix this issue on the older compilers.
If you'd like to learn more about these macros...
18.4.1 Header <cstdint> synopsis
The header also defines numerous macros of the form:
INT_[FAST LEAST]{8 16 32 64}_MIN
[U]INT_[FAST LEAST]{8 16 32 64}_MAX
INT{MAX PTR}_MIN
[U]INT{MAX PTR}_MAX
{PTRDIFF SIG_ATOMIC WCHAR WINT}{_MAX _MIN}
SIZE_MAX
EDIT
In the current C++11/14 standard, SIZE_MAX is introduced and mentioned only in <cstdint>. It is also part of C99, of which specification C++11 fully includes via the <cxxx> headers. So it seems it was not defined prior to C++11.
Which C++ standard header defines SIZE_MAX?
Its supposed to be defined in <cstdint>, but its optional.
Here are the results on Fedora 22 with GCC 5.1:
#include <cstdint>
// use SIZE_MAX
Results in:
g++ -DNDEBUG -g -O2 -fPIC -march=native -pipe -c filters.cpp
In file included from /usr/include/c++/5.1.1/cstdint:35:0,
from filters.cpp:14:
/usr/include/c++/5.1.1/bits/c++0x_warning.h:32:2: error: #error This file requires
compiler and library support for the ISO C++ 2011 standard. This support is currently
experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support for the \
^
filters.cpp: In constructor ‘Filter::Filter(BufferedTransformation*)’:
filters.cpp:305:36: error: ‘SIZE_MAX’ was not declared in this scope
: Filter(attachment), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_M
^
It was simply easier to do the following, and stop worrying about non-portable optional-ness that still causes problems in 2015.
#include <limits>
#ifndef SIZE_MAX
# ifdef __SIZE_MAX__
# define SIZE_MAX __SIZE_MAX__
# else
# define SIZE_MAX std::numeric_limits<size_t>::max()
# endif
#endif
Trying __SIZE_MAX__ gets you back to the compile time constant that you probably crave. You can see if its defined in the preprocessor with cpp -dM < /dev/null | grep __SIZE_MAX__.
(And how/why numeric_limits<size_t>::max() is not a compile time constant is another C++ mystery, but that's a different problem).

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

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.