gcc macro expansion of #error - gcc

I have some preprocessor code like this:
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#if GCC_VERSION < 40503
#error Your compiler is outdated.
#error You need at least gcc 4.5.3 for this library.
#error You have: GCC_VERSION
#error You have: STR(GCC_VERSION)
#endif
However both ways I tried to output the current compiler version fail. According to the documentation this is because
Neither ‘#error’ nor ‘#warning’ macro-expands its argument. Internal whitespace sequences are each replaced with a single space. The line must consist of complete tokens. It is wisest to make the argument of these directives be a single string constant; this avoids problems with apostrophes and the like.
How can I output the compiler version with the error message anyway? Is there any preprocessor magic that allows me to achieve this?

The classic "solution" to this problem is to manage to generate an error which includes the desired message. For example:
#define S(x) #x
#define STR(x) S(x)
#if GCC_VERSION < 40503
#error Outdated compiler: you need at least gcc 4.5.3 for this library.
#define above_message_indicates_installed_gcc_version STR(Installed GCC version: GCC_VERSION)
#include above_message_indicates_installed_gcc_version
#endif
While that does provide some information, it is still subject to misinterpretation; personally, I think letting the developer know the minimum version required is sufficient.
Note: The above snippet assumes that GCC_VERSION has already been defined, which I assume must have been done before the snippet in the OP. But beware: since the preprocessor does text substitution, not arithmetic evaluation (except in #if directives), you need to assemble GCC_VERSION in a different form for the error message If you want to try this, you could use the following:
#define GCC_VERSION (__GNUC_PATCHLEVEL__ + 100 * (__GNUC_MINOR__ + 100 * __GNUC__))
#define S_(x) #x
#define STR(x) S_(x)
#if GCC_VERSION < 40503
#undef GCC_VERSION
#define GCC_VERSION __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
#error Outdated compiler: you need at least gcc 4.5.3 for this library.
#define above_message_indicates_installed_gcc_version STR(Installed GCC version: GCC_VERSION)
#include above_message_indicates_installed_gcc_version
#endif
See it on gcc.godbolt

If #error does not expand its arguments, I would just take a pragmatic approach:
#if GCC_VERSION < 40503
#error Outdated compiler < 4.5.3, run 'gcc --version' to get version.
#endif
The only other possibility I can think of is to preprocess the file with your own preprocessor, to replace all occurences of (for example) xyzzy_GCC_VERSION_plugh with something extracted from gcc --version.
That's going to be a lot of effort and maintenance load to do what probably isn't necessary anyway.
But, if you really want to do it, you could use something like:
actual=$(echo "GCC_VERSION" | gcc -E - | tail -1)
sed "s/xyzzy_GCC_VERSION_plugh/$actual/g" file1.c >file1_morphed.c
gcc -c -o file1.o file1_morphed.c
and your file1.c would contain at the top somewhere:
#if GCC_VERSION < 40503
#error Outdated compiler xyzzy_GCC_VERSION_plugh < 4.5.3
#endif
But, as i said, that's a fair bit of work for not much benefit. My advice is just to tell the person using your library how to get the compiler version themselves. They are developers after all, I'd expect them to be able to handle an instruction like that.

Combining the proposal of paxdiablo and ideas for static compile time assertions I settled for the following solution.
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#define ERROR_MESSAGE(major, minor, patchlevel) compiler_version__GCC_ ## major ## _ ## minor ## _ ## patchlevel ## __ ;
#define OUTDATED_COMPILER_ERROR(major, minor, patchlevel) ERROR_MESSAGE(major, minor, patchlevel)
#if GCC_VERSION < 40503
#error Outdated compiler version < 4.5.3
#error Absolute minimum recommended version is avr-gcc 4.5.3.
#error Use 'avr-gcc --version' from the command line to verify your compiler version.
#error Arduino 1.0.0 - 1.0.6 ship with outdated compilers.
#error Arduino 1.5.8 (avr-gcc 4.8.1) and above are recommended.
OUTDATED_COMPILER_ERROR(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#endif

Related

Detect whether clang is compiling using c++11 or legacy libstdc++ standard library

I've got an Xcode project that I'm migrating to use with clang's option -stdlib libc++, to enable C++11 support. Some of my source files need to know which library is being used, for instance so that I do things like this:
#ifdef HAVE_CPP11_LIB_SUPPORT
#include <memory>
#else
#include <tr1/memory>
#endif
#ifdef HAVE_CPP11_LIB_SUPPORT
vector.emplace_back(newValue);
#else
vector.push_back(newValue);
#endif
I'm having trouble though finding the preprocessor macros (if indeed there are any) that are set for this option. I've tried dumping the outputs of clang with:
clang -x c++ -std=c++11 -stdlib=libc++ -dM -E - < /dev/null
to compare with:
clang -x c++ -std=c++11 -stdlib=libstdc++ -dM -E - < /dev/null
but this gives the same results. Note that I don't want to switch on whether we're using the c++11 language setting, but whether we're using the c++11 library. Is there any reliable way of detecting this in the code?
I don't know of any sure way that is guaranteed to be portable, but this is what I use for now:
// libc++ detected: _LIBCPP_VERSION
// libstdc++ detected: __GLIBCXX__
#if defined(__clang__)
# if __has_include(<__config>) // defines _LIBCPP_VERSION
# include <__config>
# elif __has_include(<bits/c++config.h>) // defines __GLIBCXX__
# include <bits/c++config.h>
# else
# include <ios>
# endif
#elif defined(__GNUC__) // gcc does not have __has_include
# include <ios> // ios should include the c++config.h which defines __GLIBCXX__
#endif
It's not great, but works for me for now.
libc++ defines _LIBCPP_VERSION and stdc++ defines __GLIBCXX__ which is nice, but unfortunately these macros are not defined by the compiler. Instead, they're defined in a non-standard header file, and you cannot test their definition unless that header has been included.
Note: Apparently stdc++ defined __GLIBCPP__ in older versions instead. Since you require c++11, this isn't going to be a problem.
Clang (Edit: Standard since C++17) has a nice feature __has_include which can be used to test for these but if neither header is found, the macro falls back to just including a standard header which hopefully uses the internal header under the hood. I have <ios> here, but the choice of standard header to include is up to you. You can look for headers that include the internal header with something like (this is for gcc on linux):
grep -Rl '#include <bits/c++config.h>' /usr/include/c++
Pick any header that you're likely to use in the project anyway.
Since this isn't guaranteed to work for any given past or future compiler/standard library version, I wouldn't rely on these defines for anything but optional features like:
#ifdef __GLIBCXX__
std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
#endif
#ifdef __has_include
# if __has_include(<ciso646>)
# include <ciso646>
# if defined(_LIBCPP_VERSION)
# define USING_LIBCPP 1
# endif
# endif
#endif
#if !USING_LIBCPP
# define USING_LIBSTDCXX 1
#endif
If you're writing these kinds of checks I suggest you choose a compiler/library version and require that or newer. It makes no sense to half-use C++11 library features. On Mac OS X, just require compilation with clang++ -stdlib=libc++.
I use next code:
#include <cstddef> // for __GLIBCXX__
#ifdef __GLIBCXX__
# include <tr1/memory>
#else
# include <memory>
#endif
source

GCC preprocessor [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Running the GCC preprocessor
Is there a GCC option to make the GCC preprocessor generate C source code but filter out irrelevant source code?
For example, a C file has #define switch to define for many different platforms. I'm only intersted in one platform, so I want the C preprocessor to filter out unrelated code. Does GCC support this?
Use gcc -E to only run the preprocessor part, e.g. give a file in.c
#if 0
0;
#endif
#if 1
1;
#endif
running
$ gcc -E in.c -o in.i
yields a file in.i
# 1 "in.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "in.cpp"
1;
i.e. the parts behind the #if 0 got removed. If you would have #include'd files they would have been pasted too though, so I am not sure how much help this is.
It sounds like you actually want unifdef, not the GCC preprocessor.
Yes - almost certainly your compiler provides certain default definitions in the environment that you can use to turn code on and off for different systems. __GNUC__ is a good one for GCC. For example:
#ifdef __GNUC__
#define SOME_VALUE 12
#else
#define SOME_VALUE 14
#endif
If you compile that block with GCC, SOME_VALUE will be 12, and if you compile with MSVC, for example, SOME_VALUE will be 14. A list of platform specific definitions is available at this question.
You probably can use:
gcc -CC -P -Uswitch -undef -nostdinc -fdirectives-only -dDI -E
With switch the #define you know will be undefined.

gcc ignore casing of symbol names while linking

A software I am working on ships with NETLIB BLAS/LAPACK embedded into its sources using all-lowercase symbol names but now while porting the application to windows I discovered that Intel MKL and several other BLAS/LAPACK implementations for this platform use all-uppercase symbol names. Is there a way to tell the gnu compiler/linker to ignore case while matching symbol names?
.
.
.
undefined reference to `_dgeqp3'
.
.
.
$ nm /lib/LAPACK.lib | grep -i " T _dgeqp3"
00000000 T _DGEQP3
The difference you're seeing is due to Fortran calling conventions: in Fortran, symbol case is unimportant, and thus every compiler has a way to translate Fortran symbol names into assembler symbol names: GNU compilers usually translate all to lowercase, Intel on Windows goes for uppercase.
If you're working with Fortran code, you can use the -fsymbol-case-upper option on the older g77 compiler (the newer gfortran compiler doesn't have this). Otherwise, no simple answer for C, except:
using #define's
using the C interfaces to BLAS and LAPACK.
I think you might be in for some trouble. Section 6.4.2.1 of the C spec says "Lowercase and uppercase letters are distinct" with respect to identifiers. That means that as far as your compiler and linker are concerned, _DGEQP3 and _dgeqp3 are different symbols. You can probably add some #define statements in a platform-specific header to line things up for you.
Is it because you're linking against a windows library rather than whatever you were using before that this bug showed up?
t.c
#define __CONCAT(x,y) x##y
#ifdef SUFFIX
#define __SUFFIX(x) __CONCAT(x,_)
#else
#define __SUFFIX(x) x
#endif
#ifdef UPPER
#define __c(U,l) __SUFFIX(U)
#else
#define __c(U,l) __SUFFIX(l)
#endif
#define xaxpy __c(XAXPY, xaxpy)
#include <stdio.h>
char* xaxpy;
char* DAXPY;
int main()
{
printf(xaxpy);
printf(DAXPY);
}
e.c
char* xaxpy = "ln";
char* xaxpy_ = "ls";
char* XAXPY = "UN";
char* XAXPY_ = "US";
there seems to be a way to introduce symbol aliases at link-time using --defsym:
Cetin#BAKA-CHAN ~
$ gcc -D UPPER -D SUFFIX -c t.c e.c
Cetin#BAKA-CHAN ~
$ gcc -o t t.o e.o -Wl,--defsym=_DAXPY=_xaxpy
Cetin#BAKA-CHAN ~
$ ./t
USln
Cetin#BAKA-CHAN ~
$
There must also be a way to give the linker different scripts to handle a large number of such symbol definitions. So I could make it part of the build process to automatically create linker scripts that create mappings between different cases.

What are the gcc predefined macros for the compiler's version number?

I have run into a bug with gcc v3.4.4 and which to put an #ifdef in my code to work around the bug for only that version of the compiler.
What are the GCC compiler preprocessor predefined macros to detect the version number of the compiler?
From the gnu cpp manual...
__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.
__GNUC_PATCHLEVEL__ is new to GCC 3.0; it is also present in the widely-used development snapshots leading up to 3.0 (which identify themselves as GCC 2.96 or 2.97, depending on which snapshot you have).
If all you need to know is whether or not your program is being compiled by GCC, or a non-GCC compiler that claims to accept the GNU C dialects, you can simply test __GNUC__. If you need to write code which depends on a specific version, you must be more careful. Each time the minor version is increased, the patch level is reset to zero; each time the major version is increased (which happens rarely), the minor version and patch level are reset. If you wish to use the predefined macros directly in the conditional, you will need to write it like this:
/* Test for GCC > 3.2.0 */
#if __GNUC__ > 3 || \
(__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
(__GNUC_MINOR__ == 2 && \
__GNUC_PATCHLEVEL__ > 0)))
__GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__.
For instance, GCC 4.0.1 will do:
#define __GNUC__ 4
#define __GNUC_MINOR__ 0
#define __GNUC_PATCHLEVEL__ 1
Here is a little command line that is nice to remember when you are wondering which are the predefined preprocessor directives defined by the GNU GCC compiler under your current programming environment:
gcc -E -dM - < /dev/null |less
There's 3 macros for the gcc version you can test on.
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
__GNUC__
e.g. my gcc v 4.3.1 defines them as such:
#define __GNUC_MINOR__ 1
#define __GNUC_PATCHLEVEL__ 3
#define __GNUC__ 4
You can see the "buitin" macros defined by running
gcc -E -dM -x c /dev/null
From the online docs:
__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.
and
__VERSION__
This macro expands to a string constant which describes the version of the compiler in use. You should not rely on its contents having any particular form, but it can be counted on to contain at least the release number.

user warnings on msvc AND gcc?

In MSVC I have this in a header:
#define STR(x) #x
#define STR2(x) STR(x)
#define NOTE(text) message (__FILE__ "(" STR2(__LINE__) ") : -NOTE- " #text)
#define noteMacro(text) message (__FILE__ "(" STR2(__LINE__) ") : " STR2(text))
and I do
#pragma NOTE(my warning here)
GCC has:
#warning(my warning here)
However MSVC (2003) throws a fit when it sees #warning and gives "fatal error C1021: invalid preprocessor command 'warning'"
What can I do about this? Is there a way to have GCC recognize MSVC warnings or MSVC not throw an error on GCC warnings? Is there something I can do that works on both? I can have GCC warn me about unknown pragmas but that's not the most ideal solution.
The best solution I've found for this problem is to have the following in a common header:
// compiler_warning.h
#define STRINGISE_IMPL(x) #x
#define STRINGISE(x) STRINGISE_IMPL(x)
// Use: #pragma message WARN("My message")
#if _MSC_VER
# define FILE_LINE_LINK __FILE__ "(" STRINGISE(__LINE__) ") : "
# define WARN(exp) (FILE_LINE_LINK "WARNING: " exp)
#else//__GNUC__ - may need other defines for different compilers
# define WARN(exp) ("WARNING: " exp)
#endif
Then use
#pragma message WARN("your warning message here")
throughout the code instead of #warning
Under MSVC you'll get a message like this:
c:\programming\some_file.cpp(3) : WARNING: your warning message here
Under gcc you'll get:
c:\programming\some_file.cpp:25: note: #pragma message: WARNING: your warning message here
Not perfect, but a reasonable compromise.
As you have now discovered, #warning is not a standard feature, so you cannot use it with compilers that don't suppport it. If you want your code to work across platforms, you won't use #warning at all - or, at the least, not in code that MSVC is intended to process (it could be preprocessed out by #ifdef or equivalent). Hence:
#ifdef __GNUC__
#warning(warning message)
#else
#pragma NOTE(warning message)
#endif
But that repeats the message and I'm sure you had in mind not doing that - and it is bulky ; you'd only use it very seldom. You might also need to deal with other compilers than GCC (and I'm not familiar enough with MSVC to know how to identify it reliably).
It would be nice if #warning were standardized; it is not standardized in C99.
(There was, once upon a long time ago, an SO question about such features that could be added to C and #warning came up there.)
See also: Portability of #warning preprocessor directive
Guard them with #if statements. Look for a symbol that's defined by one compiler but not the other.
#ifdef _MSC_VER
#pragma NOTE(my warning here)
#else
#warning(my warning here)
#endif
Kind of ugly, but I don't see another way.
It is possible have code that works everywhere, and emits custom
warnings on many compilers, including most compilers people are likely
to use (GCC, clang, MSVC, Intel, ...).
First, we should distinguish between warnings and informational
messages. I think the only thing that makes sense is that, if you
compile with fatal warnings (e.g., -Werror on GCC), warnings
should cause compilation to fail, whereas informational messages
shouldn't.
As the original question mentions, MSVC 9.0+ supports
#pragma message("Hello")
Despite the (IMHO unfortunate) name, MSVC will emit a warinng here,
not an informational message. AFAICT there is no way to emit an
informational message.
GCC 4.8+ and Intel support warning message pragmas, which means we can
use the preprocessor to generate them:
#pragma GCC warning "Hello"
Note that, as of version 18, PGI does not support such warnings, even
though pgc++ masquerades as a version of GCC that should (i.e., it
sets __GNUC__, __GNUC_MINOR__, and __GNUC_PATCHLEVEL__ to values which
indicate GCC >= 4.8). They are
aware
of the issue. To get around this while still allowing some future
version of PGI which does support those to work properly, you can do
something like:
#if defined(__PGI)
# pragma diag_suppress 1675
#endif
Unfortunately I don't think there is a way to push/pop the warning
stack for PGI, so if you do this all subsequent unknown pragmas will
be silently ignored. Also, keep in mind that #pragma message is
silently ignored by PGI (it will not even generate a warning about the
pragma being unknown).
Clang also supports #pragma GCC warning (as well as #pragma clang
...), but as of 6.0 such warnings are actually informational (I've
filed a bug). I'm not sure when support was added, but clang's version
numbers are pretty useless anyways (thanks to Apple setting them to
something completely different in their clang
distribution). Unfortunately there is no __has_pragma feature test
macro, but we can temporarily disable the unknown pragma warnings so
that if the compiler doesn't support the pragma it will be silently
ignored instead of emitting an unwanted warning:
#if defined(__has_warning)
# if __has_warning("-Wunknown-pragmas")
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma message "Hello"
# pragma clang warning "Hello"
# pragma clang diagnostic pop
# endif
#endif
Sure, it's ugly, but at least we can hide it behind a macro.
Cray 5.0+ also has a pragma for messages:
#pragma _CRI message "Hello"
I don't actually have access to Cray's compiler, so I can't be sure
about whether it is informational or a warning. If someone knows the
anwser, please comment!
Putting it all together, I recently added some macros to
Hedley to handle this, the current
version looks like this:
#if HEDLEY_HAS_WARNING("-Wunknown-pragmas")
# define HEDLEY_MESSAGE(msg) \
HEDLEY_DIAGNOSTIC_PUSH \
_Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \
HEDLEY_PRAGMA(message msg) \
HEDLEY_DIAGNOSTIC_POP
#elif \
HEDLEY_GNUC_VERSION_CHECK(4,4,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0)
# define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message msg)
#elif HEDLEY_CRAY_VERSION_CHECK(5,0,0)
# DEFINE HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(_CRI message msg)
#else
# define HEDLEY_MESSAGE(msg)
#endif
#if HEDLEY_HAS_WARNING("-Wunknown-pragmas")
# define HEDLEY_WARNING(msg) \
HEDLEY_DIAGNOSTIC_PUSH \
_Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \
HEDLEY_PRAGMA(clang warning msg) \
HEDLEY_DIAGNOSTIC_POP
#elif \
(HEDLEY_GNUC_VERSION_CHECK(4,8,0) && !defined(__PGI)) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0)
# define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(GCC warning msg)
#elif HEDLEY_MSVC_VERSION_CHECK(15,0,0)
# define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(message(msg))
#else
# define HEDLEY_WARNING(msg) HEDLEY_MESSAGE(msg)
#endif
If you don't want to use Hedley (it's a single public domain / CC0 header for just this sort of thing) you can replace the internal macros without too much effort. If you do that, I'd suggest basing your port on the Hedley repo instead of this answer as I'm much more likely to keep it up to date.
If you wish, you can add to the above solutions a little thing (#pragma warning) before
your #pragma message:
#pragma warning()
#pragma message(" SOME USER WARNING - FILE LINE etc... ")
This little add-in generates real warning, and does not look bad in the window of VC.
For example:
1>e:\proj\file.h(19) : warning C4615: #pragma warning : unknown user warning type
1> SOME USER WARNING - FILE LINE etc...
1>proj - 0 error(s), 1 warning(s)
Usually I use this method to warnings were not too quiet, as in the case code without the #pragma warning().
For example, the form of warnings too quiet (for me of course).
1> SOME USER WARNING - FILE LINE etc..
1>proj - 0 error(s), 0 warning(s)
However, only a small cosmetics.

Resources