Is #error directive crossplatform and crosscompiler - c++

I know that #error directive works at least with GCC and MSVC
#if !defined(__cplusplus)
#error C++ compiler required.
#endif
But is it crossplatform and crosscompiler in general? Is it a part of some standard maybe?
PS. Because even looking at examples given in GCC and MSVC manuals one sees differences. While it works both with quotes or not, it makes a sad feeling, that it might be somehow compiler dependent.
GCC example
#error "Won't work on ..." // quotes here
MSVC example
#error C++ compiler required. // no qutes

Yes it is. It's a standard preprocessor directive in C and C++.
References:
http://en.cppreference.com/w/cpp/preprocessor/error
http://en.cppreference.com/w/c/preprocessor/error

Related

Distinguish between Clang CL and MSVC CL

There is CLang-CL which is a drop-in replacement for MSVC's CL.
Does anyone know how to distinguish if my code is currently compiled by clang-cl or msvc's cl? Without passing any extra defined macros on command line.
Using
#ifdef _MSC_VER
//.....
#endif
doesn't work, both compilers define _MSC_VER.
Also in regular CLang on Linux (Windows too) it was possible to do clang -dM -E - < /dev/null which dumps all defined macros. But clang-cl and msvc-cl both don't have such option to dump all defined macros as far as I know, so I don't know of a way to see a difference in list of defined macros for both compilers to figure out which macro to use to distinguish between these compilers.
The macro you're looking for is __clang__.
Note that the regular Clang (not only Clang-CL) also defines it, so you want to check for both __clang__ and _MSC_VER at the same time.

How do I test the version of libstdc++, not GCC, at compile time?

I am trying to test the version of libstdc++ because std::regex is implemented, but largely broken, in the versions of libstdc++ distributed with GCC before version 4.9.0.
Note that:
I need to test the version of libstdc++, not GCC because Clang also supports using libstdc++ as the standard library. This rules out testing the __GNUC_PATCHLEVEL__, __GNUC__, and __GNUC_MINOR__ macros.
The __GLIBCXX__ macro is a date, not a version number and does not increase monotonically. For example, GCC 4.8.4 ships with #define __GLIBCXX__ 20150426, which is newer than the release date of GCC 4.9.0.
Is there any portable way to test the version of libstdc++ that does not depend on using GCC my compiler?
In my opinion the problem is sufficiently small to be solved by brute force.
In a header file called machine.hpp or similar I would test that the version of the C++ Standard is at least what I need it to be (the __cplusplus macro). Then I would add the various macro checks to reject any library that I know to be flawed.
In other words, I would take a black-list approach instead of a white-list approach.
For example:
#pragma once
#ifndef MACHINE_HPP_HEADER_GUARDS
#define MACHINE_HPP_HEADER_GUARDS
#if __cplusplus < 201103L
// Library is incompatible if it does not implement at least the C++11
// standard.
#error "I need a library that supports at least C++11."
#else
// Load an arbitrary header to ensure that the pre-processor macro is
// defined. Otherwise you will need to load this header AFTER you
// #include the header you care about.
#include <iosfwd>
#endif
#if __GLIBCXX__ == 20150422
#error "This version of GLIBCXX (20150422) has flaws in it"
#endif
// ...repeat for other versions of GLIBCXX that you know to be flawed
#endif // MACHINE_HPP_HEADER_GUARDS

Upgrading from C++98 to C++11 causes error

I am using QT Creator to make a C++ program on Ubuntu. The program I had written was compiling fine, until I decided to start using C++11 rather than C++98 (which is the default in QT Creator). I am using my own cmake file, rather than qmake, and so to do this, I included the following line in my CMakeLists.txt file:
set(CMAKE_CXX_FLAGS "-std=c++0x")
Now, part of my code has the following (which was not written by me):
#if (linux && (i386 || __x86_64__))
# include "Linux-x86/OniPlatformLinux-x86.h"
#elif (linux && __arm__)
# include "Linux-Arm/OniPlatformLinux-Arm.h"
#else
# error Unsupported Platform!
#endif
After transferring to C++11, I get an error at the line error Unsupported Platform!. This is because, from what I can see, the variable linux is not defined anywhere, although the variable __x86_64__ is defined.
Therefore, I have two questions:
1) Why is the variable linux not defined, even though I am using Linux?
2) How can I tell C++11 to ignore this error?
Thanks.
The identifier linux is not reserved. A conforming compiler may not predefine it as a macro. For example, this program:
int main() {
int linux = 0;
return linux;
}
is perfectly valid, and a conforming compiler must accept it. Predefining linux causes the declaration to be a syntax error.
Some older compilers (including the compiler you were using, with the options you were giving it) predefine certain symbols to provide information about the target platform -- including linux to indicate a Linux system. This convention goes back to early C compilers, written before there was a distinction between reserved and unreserved identifiers.
The identifier __linux__, since it starts with two underscores, is reserved for use by the implementation, so compilers are allowed to predefine it -- and compilers for Linux systems typically do predefine it as a macro expanding to 1.
Confirm that your compiler predefines __linux__, and then change your code so it tests __linux__ rather than linux. You should also find out what reserved symbol is used instead of i386 (likely __i386__).
Related: Why does the C preprocessor interpret the word "linux" as the constant "1"?
Change your standard-selection flag to -std=gnu++0x instead of c++0x. The gnu flavors provide some non-standard extensions, apparently including predefining the macro linux. Alternatively, check for __linux__ instead.

Gnu C++ macro __cplusplus standard conform?

The Gnu C++ compiler seems to define __cplusplus to be 1
#include <iostream>
int main() {
std::cout << __cplusplus << std::endl;
}
This prints 1 with gcc in standard c++ mode, as well as in C++0x mode, with gcc 4.3.4, and gcc 4.7.0.
The C++11 FDIS says in "16.8 Predefined macro names [cpp.predefined]" that
The name __cplusplus is defined to the value 201103L when compiling a C++ translation unit. (Footnote: It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming com-
pilers should use a value with at most five decimal digits.)
The old std C++03 had a similar rule.
Is the GCC deliberatly setting this to 1, because it is "non-conforming"?
By reading through that list I thought that I could use __cplusplus to check in a portable way if I have a C++11 enabled compiler. But with g++ this does not seem to work. I know about the ...EXPERIMENTAL... macro, but got curious why g++ is defining __cplusplus this way.
My original problem was switch between different null-pointer-variants. Something like this:
#if __cplusplus > 201100L
# define MYNULL nullptr
#else
# define MYNULL NULL
#endif
Is there a simple and reasonably portable way to implement such a switch?
This was fixed about a month ago (for gcc 4.7.0). The bug report makes for an interesting read: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773
If I recall correctly this has to do with Solaris 8 causing issues when __cplusplus is set as it should. The gcc team decided at the time to support the Solaris 8 platform rather than be compliant in this particular clause. But I noticed that the latest version of gcc ends the Solaris 8 support, and I guess this is a first step in the right direction.
It is a very old g++ bug.
That is, the compiler is not conforming.
Apparently it can't be fixed because fixing it would break something on a crazy platform.
EDIT: oh, I see from #birryree's comment that has just been fixed, in version 4.7.0. So, it was not impossible to fix after all. Heh.
Cheers & hth.

Detect ICC vs GCC at compile time

How to detect at compile time if I'm using gcc or icc?
(I was quite puzzled to find out that icc defines __GNUC__ -- and even __GNUC_MINOR__ and __GNUC_PATCHLEVEL__ ! why?)
We use
#ifdef __INTEL_COMPILER
to split icc off, assuming gcc as a default.
I believe you could check for __INTEL_COMPILER according to this.
The reason ICC defines __GNUC__ etc. is because of code like yours that is inspecting compiler-specific macros and expects to see them...
Traditionally, compilers have defined a symbol of their own as well as their version as preprocessor symbols so that the code could be adapted (generally to work around bugs or specificities).
CLang has introduced a mechanism I had not seen so far, under the form of the __has_feature query. It does not replace the "work around bugs" practices (which is why CLang still exposes specific symbols) but allows a more natural style for querying the compiler capacities. I don't know if other compilers plan on defining such a facility.
You can make the processor output the defined macros in the preprocessor output and look for a macro that suits you. You can generated the preprocessor output like this:
icc -dM -E -o foo.P foo.c
Then look at foo.P (since it is a text file). In my case, I found icc defined an __ICC macro with the version of the compiler. It didn't define any __INTEL_COMPILER though.