Check for availablity of #warning preprocessor - c

I am going to use #warning in my portable C code for generating compile time warnings. But #warning is not supported in all platforms. Is there any way to find whether #warning is supported in that platform.
#ifdef warning //expecting similar check, not exactly this
#warning ("my message")
#endif
Because I will be compiling my code in so many platforms, in some platform it may give compilation error if its not supported. If some macro are available to find the availability of #warning then I will be able to avoid build failure in platforms where it's not supported.

You can use something like this to check for support:
#if defined(_MSC_VER) || defined(__GNUC__) || defined(__clang__)
# define HAVE_WARNING
#endif
#ifdef HAVE_WARNING
# pragma message("some warning")
#endif
Add more compiler-specific checks to the first #if when needed.

#pragma message("Warning...")
#pragma message "Oh NO!"
Are both supported by GCC and MSVC. Some please comment on Clang? I don't have a current version.

#warning is a gcc extension mainly, although some others may support. Microsoft will require something like #pragma message instead. You can not call it "portable" if you mean a standard C version rather than just where gcc is available.

Related

What is the compiler-defined macro for WASM?

What is the macro that clang and/or gcc would define when compiling for a WASM backend?
To clarify, one can write platform-specific code using macros the compiler defines like so:
#if _WIN32
// Windows-specific code
#elif __linux__
// Linux-specific code
#elif __APPLE__
// macOS-specific code
#else
#error Unsupported platform
#endif
I would like to do the same thing specifying WebAssembly as one of the potential backends.
As per #Jonathan Leffler's comment, there does not appear to be a standard macro that is defined across compilers.
My current solution for working with different compilers is to create a separate build job for WASM that defines a macro. For gcc and clang, it passes the flag -D__WASM__ to define a __WASM__ macro.
In my setup, I just change an environment variable and my build script selects the appropriate build flags.

Restricting clang warnings to my source files

I'm compiling a program using a library in C using clang. I want to check my program for errors (-Wall -Weverything) but I don't want to check the library. Is there a way to restrict clang's warnings to just my source files?
If a library header file is generating copious amounts warnings whenever you include it, you can try and solve by using a bit of indirection (what else).
So for a library header named lib_a.h, create a wrapper (my_lib_a.h) that looks something like this:
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Weverything"
#endif
#include "lib_a.h"
#ifdef __clang__
# pragma clang diagnostic pop
#endif
Now include it instead of directly including the library header.
Those pragams will turn off the warnings for that particular library header only.
You can of course add support for other tool-chains, and even make this utility header the point of entry for all the problematic headers in your program. Precompiling it will make the overhead negligible.

Predefined cpu target macro for Cortex-M0+

I am currently using predefined cpu target macros to make software run on multiple cpu targets.
#ifdef __TARGET_CPU_CORTEX_M0
[do something here]
#elif __TARGET_CPU_CORTEX_M3
[do something here]
#else
#error Unsupported compiler platform
#endif
Example:
This works for Cortex-M0 and Cortex-M3, but I can't figure out what macro to use for Cortex-M0+. Does anyone know which macro I can use?
I use the armcc compiler.
This is documented, albeit rather obliquely. The relevant macro name is derived from the command-line option, thus --cpu=Cortex-M0plus defines __TARGET_CPU_CORTEX_M0PLUS.
Annoyingly, whilst it doesn't show up in the --cpu=list output, the compiler (I tried armcc version 5.04) does also recognise the option --cpu=Cortex-M0+, for which it defines the macro __TARGET_CPU_CORTEX_M0_
In general, invoking armcc --cpu=xx --list_macros /dev/null will show what macros are defined for cpu option xx (or an error if it isn't supported).

__func__ or __FUNCTION__ or manual const char* id?

I'm wondering how widely are __func__ (part of C99, but I'm compiling as C89) and __FUNCTION__ supported.
I have an old code base that is mostly using manual const char* id; variables that are then passed to various (mostly logging) functions. I would like to get rid of this and move the function name into a macro.
The predefined identifier __func__ was added to the 1999 ISO C standard; the older 1990 C standard doesn't have it.
Support for __func__ in pre-C99 compilers will depend on which compiler you're using.
Modern versions of gcc support __func__ even in C90 mode (-ansi or -std=c89).
Before __func__ was added to the standard, gcc implemented its own equivalent extension, but with the name __FUNCTION__. (gcc also supports __PRETTY_FUNCTION__, which is identical to __func__ and __FUNCTION__ for C, but provides more information in C++.)
The gcc manual gives some advice:
__FUNCTION__ is another name for __func__. Older versions of GCC recognize only this name. However, it is not standardized. For maximum
portability, we recommend you use __func__, but provide a fallback
definition with the preprocessor:
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
#endif
which implies that gcc added support for __FUNCTION__ in version 2. gcc 2.0 was released in 1992; you're very unlikely to be using a version of gcc that doesn't support at least __FUNCTION__, if not __func__.
Note that since __func__ and __FUNCTION__ are predefined identifiers, not macros, you only need the #define once, not in each function. On the other hand, you can't use #ifdef __func__ or #ifdef __FUNCTION__ to detect the level of support.
As for other compilers, a quick experiment indicates that Microsoft Visual C++ 2010 Express supports __FUNCTION__, but not __func__ or __PRETTY_FUNCTION__, when compiling C code. The above block of code from the gcc manual compiles under MSVC, but it results in __func__ being defined as "<unknown>". It shouldn't be too difficult to adjust it to recognize that MSVC supports __FUNCTION__. (I don't know whether older versions do so.) You can probably use the predefined macro _MSC_VER for this. Microsoft's documentation says that support for __FUNCTION__ goes back at least to the 2003 release, which sets _MSC_VER to 1300, so changing the second line to
# if __GNUC >= 2 || _MSC_VER >= 1300
is a good start. (It may well have been supported in earlier releases.)
For compilers other than gcc and MSVC, you'll have to consult their respective documentation -- but in any case, the block of code recommended in the gcc manual should work for any compiler, at worst falling back to "<unknown>".
The boost current_function.hpp header contains several #defines for the ways to get the current function on different platforms.
That's not to say that those platforms don't support other ways of getting the current function, but the choices made for boost are likely to represent nice (if not the nicest) ways of getting the information on those platforms.
An adaptation of this header for your code (and for C) could well be what you need.
I believe it is regardless what C standard is used (if C89 or C99). The more important factor is the compiler being used since it is the one that will implement __func__. The latest GCC compilers will add __func__ no matter the standard being used. I think. :)

Is it possible to check whether you are building for 64-bit with Microsoft C Compiler?

Is there a simple preprocessor macro that is defined for a 64-bit build? I thought _WIN64 might have been it, but even when I build a 32-bit target, the parts enclosed in a #ifdef _WIN64 ... #endif are compiled in, and this is causing problems. It's Friday and I can't think straight, but I'm sure I'm overlooking something very simple here. Maybe even something involving sizeof.
I have always used _WIN64 to check if it is a 64 bit build.
N.B. _WIN32 is also always (automatically) defined by MSVC in 64 bit builds, so check for _WIN64 before you check for _WIN32:
#if defined( _WIN64 )
// Windows 64 bit code here
#elif defined( _WIN32 )
// Windows 32 bit code here
#else
// Non-Windows code here
#endif
It sounds like your problem might be related to a header or project setting improperly defining _WIN64 - that should be left to the compiler.
There's a subtle difference between WIN64 and _WIN64 (at least for the Microsoft compilers - other compilers should follow suit, but not all do):
_WIN64 is defined by the compiler when it's building a program for a Windows 64-bit platform. Note that this name is in the compiler implementor's namespace (leading underscore followed by a capital letter)
WIN64 is defined by the Windows Platform SDK (or whatever they're calling it this year) when targeting a 64-bit platform.
So if you're only including standard headers and don't take other measures to define it, WIN64 will not be defined.
There's a similar story for _WIN32 and WIN32 - but checking other compilers: GCC 3.4.5 does define WIN32 even if only standard headers are used. As does Digital Mars.
Microsoft's compilers and Comeau do not.
Another bit of (hopefully) well known trivia is that _WIN32 and WIN32 are set when targeting 64-bit Windows platforms. Too much stuff would have broken otherwise.
The Visual C++ compiler defines the following macros:
_M_IX86 - x86 platform
_M_IA64 - ia64 platform
_M_X64 - x64 platform
Check your project's build properties, particularly the preprocessor section. Are you defining _WIN64 somewhere in WIN32 builds? The sizeof thing probably won't work since you cannot use in a #if test.

Resources