I am working on a project that has been built with both gcc and msvc so far. We recently started building with clang as well.
There are some parts in the code, where platform-specific things are done:
#ifndef _WIN32
// ignore this in msvc
#endif
Since gcc has previously been the only non-windows build, this was equivalent to saying "do this only for gcc". But now it means "do this only for gcc and clang".
However there are still situations, where I would like to handle something specifically for gcc, and not for clang. Is there a simple and robust way to detect gcc, i.e.
#ifdef ???
// do this *only* for gcc
#endif
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. These macros are also defined if you invoke the preprocessor directly.
Also:
__GNUG__
The GNU C++ compiler defines this. Testing it is equivalent to testing (__GNUC__ && __cplusplus).
Source
Apparently, clang uses them too. However it also defines:
__clang__
__clang_major__
__clang_minor__
__clang_patchlevel__
So you can do:
#ifdef __GNUC__
#ifndef __clang__
...
Or even better (note the order):
#if defined(__clang__)
....
#elif defined(__GNUC__) || defined(__GNUG__)
....
#elif defined(_MSC_VER)
....
I use this define:
#define GCC_COMPILER (defined(__GNUC__) && !defined(__clang__))
And test with it:
#if GCC_COMPILER
...
#endif
With Boost, this becomes very simple:
#include <boost/predef.h>
#if BOOST_COMP_GNUC
// do this *only* for gcc
#endif
See also the Using the predefs section of the boost documentation.
(credit to rubenvb who mentioned this in a comment, to Alberto M for adding the include, and to Frederik Aalund for correcting #ifdef to #if)
Related
Various modern C/C++ compilers include one or both of __func__ / __FUNCTION__ for purposes of logging the currently executing function. MSVC++ also includes __FUNCSIG__ and GCC __PRETTY_FUNCTION__ as compiler-specific enhanced flavors of this functionality.
GCC defines these as variables rather than macros, however, so it isn't possible to test for their presence via a #ifdef preprocessor directive.
I'm working with a codebase that must work with C++98 and C++11 flavors of MSVC++ and GCC, and the logging facility that someone wrote erroneously tries to test for __FUNCTION__ if __FUNCSIG__ is not available. This check always returns false, rendering function logging support non-operational.
Question: Is there a good macro out there that makes a sufficient-for-my-use-cases guess at which (if any) of these features should be present, possibly by sniffing out compiler versions?
T.C. supplied this answer first, as a comment under my question, and I ended up basing my solution on it:
The header <boost/current_function.hpp> in Boost.Assert implements a BOOST_CURRENT_FUNCTION macro that attempts to map to a suitable "current function" facility provided by the compiler.
Documentation is here:
http://www.boost.org/doc/libs/1_66_0/libs/assert/doc/html/assert.html#current_function_macro_boost_current_function_hpp
And here is a concise reproduction of the macro for reference:
#if defined( BOOST_DISABLE_CURRENT_FUNCTION )
# define BOOST_CURRENT_FUNCTION "(unknown)"
#elif defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(__DMC__) && (__DMC__ >= 0x810)
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(__FUNCSIG__)
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
# define BOOST_CURRENT_FUNCTION __FUNCTION__
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
# define BOOST_CURRENT_FUNCTION __FUNC__
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
# define BOOST_CURRENT_FUNCTION __func__
#elif defined(__cplusplus) && (__cplusplus >= 201103)
# define BOOST_CURRENT_FUNCTION __func__
#else
# define BOOST_CURRENT_FUNCTION "(unknown)"
#endif
I ended up modifying the codebase I was working with to use the Boost macro when available, and to fall back to a reasonable subset of the Boost checks otherwise (GCC > MSVC++ > C++11).
__func__ was specified in C99 (not C++) and gcc has provided __FUNCTION__ and __PRETTY_FUNCTION__ for quite a while. However, none are actually macros, so can't be used as such. Among other things, that means you can't test for them using #ifdef.
To test if you are compiling as C++, and to what standard, use __cplusplus which is specified in the C++ standard, and expands to values 199711L (before C++11), 201103L (C++11), 201402L (C++14), and 201703L (C++17). The values correspond to the dates (year and month) when the standardisation committee approved the standard (e.g. 201703L means that C++17 was approved in March 2017). Note this is macro is only defined when compiling C++, not C.
Beyond that, to use features specific to a compiler, you need to test for the compiler that supports the features you want, not the feature itself (although some compilers/preprocessors do allow testing for particular language features, that's patchy in practice).
gcc and g++ (and other compilers that claim to support gnu C dialects) provide a number of specific macros, so you can check for them including
__GNUC__, defined for the GNU C compiler (can be tested using #ifdef). For gcc version x.y.z, __GNUC__ expands to the value x;
__GNUC_MINOR__, defined for the GNU C compiler (can be tested using #ifdef). For gcc version x.y.z, __GNUC_MINOR__ expands to the value y;
__GNUC_PATCH_LEVEL__, defined for the GNU C compiler (can be tested using #ifdef). For gcc version x.y.z, __GNUC_PATCHLEVEL__ expands to the value z;
__GNUG__ - defined for the g++ compiler.
An example of how you might use the gnu-specific macros is
#ifdef __GNUG__
/* Assume all versions of gcc that you use support __FUNCTION__ */
/* can use gcc's __FUNCTION__ here */
#endif
I don't know offhand which g++ versions started supporting __FUNCTION__ and __PRETTY_FUNCTION__, but if you want to test for particular version of the compiler, it's easy. For example, to test for g++ 3.2.0 or better
#ifdef __GNUG__
// test for g++ 3.2.0 or better
#if __GNUC__ > 3 || \
(__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
(__GNUC_MINOR__ == 2 && \
__GNUC_PATCHLEVEL__ > 0))
// use features not introduced before g++ 3.2.0
#endif
#endif
For MSVC++, compiler-specific macros for a similar purpose include _MSC_VER which expands to an encoding of the major and minor versions. For example, under MSVC++ version 17.00.51106.1, _MSC_VER expands to 1700. You can find others on MSDN.
I have found that writing
#ifdef ...
#elseif defined(...)
#else
#endif
always results in using either the #ifdef or the #else condition, never the #elseif. But substituting #elif causes it to work as expected based on what's defined. What convoluted purpose, if any, is served by the existence of #elseif? And if none, why doesn't the preprocessor complain?
Maybe this is why for years (decades, really), I've been using ugly #else/#endif blocks, since at least they're reliable!
#elseif is not defined. The preprocessor doesn't complain because your #ifdef is false, and the directives within that #ifdef block are not parsed. To illustrate it, this code is valid:
#if 0
#random nonsense
#else
// This must be valid
#endif
I just uncovered in IAR Embedded Workbench for MSP430, v7.11.1, which reports icc430 --version as "IAR C/C++ Compiler V7.11.1.983/W32 for MSP430",
that #elseif compiles without error, but does NOT evaluate the same as #elif.
I have been working with qt creator and recently tried to change the compiler from gcc to clang. Since I don't get any info (or can't see it) on whether this worked (I'm struggling to understand the interface) I wanted to ask if there's a way for my c++ code to print out the compiler under which it's being compiled.
Compilers set certain #defines to help out with things like this.
In your case,
#ifdef __GNUC__ //GCC
//do whatever GCC-specific stuff you need to do here
#endif
#ifdef __clang__ //clang
//do whatever clang-specific stuff you need to do here
#endif
This page on SourceForge shows a list of such compiler-specific #define values.
EDIT: as pointed out in the comments, clang sets __GNUC__, and possibly __GNUC_MINOR__ and __GNUC_PATCHLEVEL__. You might be better off using a double test to make sure clang isn't misleading you:
#if defined(__GNUC__) && !defined(__clang__)
//do whatever GCC-specific stuff you need to do here
#endif
Use the informational macros of boost.
#include <boost/config.hpp>
#ifdef BOOST_CLANG
printf("Successfully changed to clang\n");
#endif
So I was deep in the depths of my code writing an erase method for my container class when I went to call std::vector::erase with a const_iterator and if failed mightily. Just like it did for this person.
Following the links to gnu libstdc++ status shows that this issue has still not been fixed (the original question was early 2013).
So I coded up a horrible hack-around:
#if 1
// horrible hack for gnu libstd++ deficit
// current implementation does not allow erase(const_iterator), so recreate plain iterator
off_t::iterator itx= offsets_.begin() + ( apos.iter() - offsets_.begin() ) ;
#else
// for compliant implementations
auto itx= apos.iter() ;
#endif
But I am wondering if there is #define I can use the relates to the version of libstdc++. There are plenty to test for the version of the compiler, but I don't think that gcc versions are going to be a good indicator for when this is fixed, and since clang uses the same library by default I need to catch it either way. I took a look at the output of g++ -E -dM - < /dev/null but the only ones that even mentioned STD didn't seem to promising:
#define __STDC_HOSTED__ 1
#define __STDC_IEC_559__ 1
#define __STDC_ISO_10646__ 201103L
#define __STDC_NO_THREADS__ 1
#define _STDC_PREDEF_H 1
#define __STDC_IEC_559_COMPLEX__ 1
#define __STDC__ 1
Won't you be on the hook with clang anyway? If it's fixed by the gcc distribution, is it guaranteed to be fixed by clang and visa versa? How about the other compilers?
You can obtain a list of compiler defines
For example
#define __GNUC_PATCHLEVEL__
#define __GNUC__
#define __GNUC_MINOR__
or for clang
#define __clang__
#define __clang_major__
#define __clang_minor__
#define __clang_patchlevel__
Do you use autotools? If so, then since you're thinking of macro-ing yourself out of this situation anyway, you can create an autotools test to create your own define. The test doesn't need to compile, in fact that typically IS the test.
I'm interested in creating a macro for eliminating the unused variable warning.
This question describes a way to suppress the unused parameter warning by writing a macro inside the function code:
Universally compiler independent way of implementing an UNUSED macro in C/C++
But I'm interested in a macro that can be used in the function signature:
void callback(int UNUSED(some_useless_stuff)) {}
This is what I dug out using Google (source)
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*#unused#*/ x
#elif defined(__cplusplus)
# define UNUSED(x)
#else
# define UNUSED(x) x
#endif
Can this be further expanded for other compilers?
Edit: For those who can't understand how tagging works: I want a solution for both C and C++. That is why this question is tagged both C and C++ and that is why a C++ only solution is not acceptable.
The way I do it is like this:
#define UNUSED(x) (void)(x)
void foo(const int i) {
UNUSED(i);
}
I've not had a problem with that in Visual Studio, Intel, gcc and clang.
The other option is to just comment out the parameter:
void foo(const int /*i*/) {
// When we need to use `i` we can just uncomment it.
}
Just one small thing, better using __attribute__((__unused__)) as __attribute__((unused)), because unused could be somewhere defined as macro, personally I had a few issues with this situation.
But the trick I'm using is, which I found more readable is:
#define UNUSED(x) (void)x;
It works however only for the variables, and arguments of the methods, but not for the function itself.
After testing and following the comments, the original version mentioned in the question turned out to be good enough.
Using: #define UNUSED(x) __pragma(warning(suppress:4100)) x (mentioned in comments), might be necessary for compiling C on MSVC, but that's such a weird combination, that I didn't include it in the end.
Across many compilers I have used the following, excluding support for lint.
#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
# define PGM_GNUC_UNUSED __attribute__((__unused__))
#else
# define PGM_GNUC_UNUSED
#endif
Tested compilers: GCC, Clang, EKOPath, Intel C Compiler / Composer XE, MinGW32 on Cygwin / Linux / MSYS, MinGW-w64 on Cygwin / Linux, Sun ONE Studio / Oracle Solaris Studio, Visual Studio 2008 / 2010.
Example usage:
pgm_tsc_init (
PGM_GNUC_UNUSED pgm_error_t** error
)
{
...
}
PGM is the standard prefix for this C based project. GNUC is the convention from GLib for this attribute.
I think one compile warns about __attribute__ in certain circumstances but certainly no error.