Distinguish between Clang CL and MSVC CL - c++

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.

Related

#pragma(* diagnostic) when mixing Clang analyzers with a GCC compiler

I'm compiling on with GCC on Linux, but CMake is kind enough to produce a Clang compatible compilation database. This means that I can run fancy, modern Clang based tools on my codebase and those tools have perfect knowledge of how each file is to be built (flags, defines, include paths, etc.) So far so good.
But today the Clang based static analysis in my IDE started showing a Clang specific warning. I don't think it particularly matters for my question which warning it is, but it was warning: disabled expansion of recursive macro, generated by -Wdisabled-macro-expansion. This particular macro is provided by a third party, so fixing the warning isn't an option, but I would like to suppress it as it occurs several times in the file in question.
What I'm struggling with is how to suppress the warning in Clang based analysis tools without causing new warnings in the GCC build.
Adding #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" suppresses the warning for Clang tools, but causes GCC to issue warning: ignoring #pragma clang diagnostic [-Wunknown-pragmas].
Similarly, adding #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" suppresses the Clang warning (because Clang tries to be compatible with GCC diagnostics), but causes GCC to issue warning: unknown option after ‘#pragma GCC diagnostic’ kind [-Wpragmas].
Wrapping either of the above with #ifdef __clang__ makes GCC happy, but doesn't suppress the Clang warning because the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead.
Is there a way to make a diagnostic #pragma visible to Clang tooling, but not to GCC?
the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead
If it's reporting a clang-only warning, but does not think that __clang__ is defined, that sounds like a problem with the tooling. If it's trying to be that clever about misrepresenting itself, you may be up a creek... but also you should be complaining to the tool author for creating this situation in the first place.
That said, you could try:
#if defined(__has_warning)
# if __has_warning("-Wdisabled-macro-expansion")
# pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
# endif
#endif
I'm not sure if this will work... it depends on how hard the tooling is pretending to not be clang (__has_warning is a clang-only extension).

Unix macro becomes undefined when compiling with -std=c++0x flag

When compiling the code below with -std=c++0x flag the unix macro becomes undefined and the error "Unix is not defined!" is shown. Is there any reason why this happens and how to fix it? Verified in gcc versions 4.7.2 and 4.8.4.
#include <iostream>
#if !defined(unix)
#error Unix is not defined!
#endif
int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
From the GCC manual, 3.7.3 System-specific Predefined Macros:
The C standard requires that all system-specific macros be part of the reserved namespace. All names which begin with two underscores, or an underscore and a capital letter, are reserved for the compiler and library to use as they wish. However, historically system-specific macros have had names with no special prefix; for instance, it is common to find unix defined on Unix systems. For all such macros, GCC provides a parallel macro with two underscores added at the beginning and the end. If unix is defined, __unix__ will be defined too. There will never be more than two underscores; the parallel of _mips is __mips__.
When the -ansi option, or any -std option that requests strict conformance, is given to the compiler, all the system-specific predefined macros outside the reserved namespace are suppressed. The parallel macros, inside the reserved namespace, remain defined.
Take note of the second paragraph, specifically.
tl;dr
The unix macro is not conforming to the standard, __unix__ is. When you asked your compiler for -std=c++0x, it switched to "strict conformance" where only __unix__ is available (and the by-default supported "extension" unix is dropped).
As others have said 'unix' is a gcc extension to the standard and by specifying --std=c++0x you have told it to use the standard. You can instead do --std=gnu++0x and it will retain the extensions (Or use __unix__ as others suggested)

Is #error directive crossplatform and crosscompiler

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

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.

Sun Studio 10 has strange `sun` constant?

Strangely, the following C++ program compiles on Sun Studio 10 without producing a warning for an undefined variable:
int main()
{
return sun;
}
The value of sun seems to be 1. Where does this variable come from and what is it for?
It's almost certainly a predefined macro. Formally, the C and
C++ standards reserve names starting with an underscore and
a capital letter, or containing two underscores, for this, but
practically, compilers had such symbols defined before the
standard, and continue to support them, at least in their
non-compliant modes which is the default mode for all of the
compilers I know. I can remember having problems with `linux'
at one time, but not when I invoked g++ with -std=c++89.
It must be one of the automatic macros created by the compiler.
Try the same thing, replace sun by gnu and use a gcc compiler on Linux. You'll get a similar result.
With gcc, you can get all the predefined macros with: echo "" | gcc -E - -dM.
sun is defined for historical backwards compatibility from before the convention to start with an underscore was adopted. For Studio, it's documented in the cc(1) and CC(1) man pages under the -D flag:
-Dname[=def]
Defines a macro symbol name to the preprocessor. Doing so is
equivalent to including a #define directive at the beginning of the
source. You can use multiple -D options.
The following values are predefined.
SPARC and x86 platforms:
__ARRAYNEW
__BUILTIN_VA_ARG_INCR
__DATE__
__FILE__
__LINE__
__STDC__ = 0
__SUNPRO_CC = 0x5130
__SUNPRO_CC_COMPAT = 5 or G
__TIME__
__cplusplus
__has_attribute
__sun
__unix
_BOOL if type bool is enabled (see "-features=[no%]bool")
_WCHAR_T
sun
unix
__SVR4 (Oracle Solaris)
__SunOS_5_10 (Oracle Solaris)
__SunOS_5_11 (Oracle Solaris)
...
Various standards compliance options can disable it, as can the +p flag to CC.