Does #pragma warning supported in LLVM for ARM? - c

Currently I'm using #pragma warning in my code for #pragma push() and #pragma pop() like below. And code is building success when i use Visual Studio compiler.
#pragma warning(push)
#pragma warning(disable: 4200) // zero-sized array
#pragma pack (push, 1)
...
...
#pragma pack (pop)
#pragma warning(pop)
But when I try to build the same code for LLVM compiler it is showing build error for
#pragma warning
How to handle this for building in LLVM without removing it?
Any pointer is encouraging..

Clang uses a different syntax for warnings:
#pragma clang warning "I'm a warning"
You can disable the unknow-pragmas warning before emitting the pragma; something like
#if defined(__has_warning)
# if __has_warning("-Wunknown-pragmas")
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
...
# pragma clang diagnostic pop
# endif
#endif
It would be smarter to actually test for MSVC, though, and only write the pragma there…
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4200) // zero-sized array
# pragma pack (push, 1)
#endif /* defined(_MSC_VER) */
...
...
#if defined(_MSC_VER)
# pragma pack (pop)
# pragma warning(pop)
#endif
Of course, clang also has a warning for zero-length arrays, as well as pragmas for pushing/popping the error stack, so you might want to include those, too…
#if defined(__clang__) && defined(__has_warning)
# if __has_warning("-Wzero-length-array")
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wzero-length-array"
# endif
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4200)
# pragma pack (push, 1)
#endif
// ...
#if defined(__clang__) && defined(__has_warning)
# if __has_warning("-Wzero-length-array")
# pragma clang diagnostic pop
# pragma clang warning "pop"
# endif
#elif defined(_MSC_VER)
# pragma pack (pop)
# pragma warning(pop)
#endif
FWIW, pushing/popping warnings is only available in MSVC 15+; I'm too lazy to check on when that specific warning is supported, but you may want to test for the MSVC version if you want to support older compilers.
Other compilers may or may not support 0-length arrays at all, and if they do they may or may not emit a warning which can be disabled. The ones I can test conveniently:
Doesn't support 0-length arrays:
suncc
pgcc (PGC-S-0047)
Supports 0-length arrays, doesn't emit a warning
TI cl6x
ICC
Supports 0-length arrays and emits a warning in some cases
GCC (-Wpedantic)
Other compilers probably support a similar warning, and many support pushing/popping and disabling warnings about unknown pragmas.

Related

Keil ARMCC Warning Macro

I want to write an all inclusive compiler warning message macro. How can you define such a macro to write out a warning given a certain compiler.
The standard for writing warnings is #pragma message "warning" which you can define in a macro using _Pragma, but when it comes to something like Keil you have to use #warning and a macro cannot be defined using _Pragma seeing as #pragma will precede the macro argument and Keil does not recognise #prama warning.
#if defined(__GNUC__)
#define PRAGMA(x) _Pragma(#x)
#define COMP_MSG(msg)\
PRAGMA(message msg)
#elif defined(__ARMCC_VERSION)
// need code here
#endif
COMP_MSG("WARNING")

how to disable this particular warning

This simple code:
#define WIDTH 500.5
#define NB 23.2
int x[(int)(WIDTH/NB)];
gives me a warning:
prog.c:4:1: warning: variably modified 'x' at file scope [enabled by default]
If I set #define WIDTH 500 and #define NB 23, the warning disappears.
Passing a float value for WIDTH macro forces evaluation by the compiler and thus issues a warning because array has not a constant size.
The preprocessed C code looks like int x[(int)(500.5/23.2)];, whereas int x[(int)(500/23)]; is OK for the compiler (value is already constant integer)
I would like to find a way either
to ignore this particular warning (but leaving the others so I can enable -Werror: seems that is a lost cause: GCC, C: Finding out name of default warnings for use in #pragma ignore
fix the code so it does what I want without issuing warnings.
force the pre-processor to perform the computation as integer
Funny thing: compiling with g++ I don't have the warning whereas I read here that variable length arrays are not officially supported in C++, only in C99. But that's not an option for me, since I need to stick to C.
It just violates the standard:
Integer constant expression
An integer constant expression is an
expression that consists only of operators other than assignment,
increment, decrement, function-call, or comma, except that cast
operators can only cast arithmetic types to integer types, integer
constants, enumeration constants, character constants, floating
constants, but only if they are immediately used as operands of casts
to integer type
And further:
The following contexts require expressions that are known as integer
constant expressions':
...
The index in an array designator (since C99)
One could ensure that a normal array (non VLA) is created like this:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
enum{ARRAY_DIMENSION_OF_x = (int)(WIDTH/NB)};
int x[ARRAY_DIMENSION_OF_x];
#pragma GCC diagnostic pop
This compiles without warning in gcc and clang in C mode and with a old-style cast to 'int' warning in C++ mode.
One could also hide the creation of the enum within a macro:
/* ================= define MAKE_CONST_INT() macro ================= */
#ifdef __cplusplus
template<class T> struct make_const_int_helper{static T t;};
# define MAKE_CONST_INT(x) (sizeof(*(make_const_int_helper<char (*)[int((x)+0L)]>::t))) /* +0L avoids "useless cast" warning*/
#else
# define EVALUATE_TO_0(type) (0*__builtin_types_compatible_p(type,int))
# define EVALUATE_TO_0_PRAGMA(x) EVALUATE_TO_0(struct{int dummy; _Pragma(x)})
# define EVALUATE_TO_0_START_DISABLE_WARNINGS \
( EVALUATE_TO_0_PRAGMA("GCC diagnostic push") \
+ EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wpedantic\"") \
+ EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wc++-compat\"") )
# define EVALUATE_TO_0_END_DISABLE_WARNINGS \
EVALUATE_TO_0_PRAGMA("GCC diagnostic pop")
# define MAKE_CONST_INT(x) MAKE_CONST_INT_HELPER2(x,__LINE__,__COUNTER__)
# define MAKE_CONST_INT_HELPER2(x,line,counter) MAKE_CONST_INT_HELPER(x,line,counter)
# define MAKE_CONST_INT_HELPER(x,line,counter) \
( EVALUATE_TO_0_START_DISABLE_WARNINGS \
+ EVALUATE_TO_0(enum{ INT_CONSTANT_##counter##_AT_LINE_##line = (int)(x) }) \
+ INT_CONSTANT_##counter##_AT_LINE_##line \
+ EVALUATE_TO_0_END_DISABLE_WARNINGS)
#endif
/* ================= test MAKE_CONST_INT() macro ================= */
#define WIDTH 500.5
#define NB 23.2
extern int x[MAKE_CONST_INT(WIDTH/NB)];
This compiles without warning in gcc and clang in C and in C++ mode.
The structs with the int dummy members are only necessary to get a place where gcc accepts a _Pragma("GCC diagnostic ....") pragma.
Example
Extended implementation that works for MSVC, gcc, clang and icc, but still won't compile on really picky compilers:
/* ================= define MAKE_CONST_INT() macro ================= */
#ifdef __cplusplus
# if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wtemplates"
# endif
template<class T> struct make_const_int_helper{static T t;};
# if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic pop
# endif
# define MAKE_CONST_INT(x) (sizeof(*(make_const_int_helper<char (*)[int((x)+0L)]>::t))) /* +0L avoids "useless cast" warning*/
#else
# if defined(__GNUC__)
# define EVALUATE_TO_0(type) (0*__builtin_types_compatible_p(type,int))
# define EVALUATE_TO_0_PRAGMA(x) EVALUATE_TO_0(struct{int dummy; _Pragma(x)})
# define EVALUATE_TO_0_START_DISABLE_WARNINGS \
( EVALUATE_TO_0_PRAGMA("GCC diagnostic push") \
+ EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wpedantic\"") \
+ EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wc++-compat\"") )
# define EVALUATE_TO_0_END_DISABLE_WARNINGS \
EVALUATE_TO_0_PRAGMA("GCC diagnostic pop")
# else
# define EVALUATE_TO_0(type) (0*sizeof(type))
# if defined(_MSC_VER)
# define EVALUATE_TO_0_START_DISABLE_WARNINGS \
(0 __pragma(warning( push )) __pragma(warning(disable:4116)))
# define EVALUATE_TO_0_END_DISABLE_WARNINGS (0 __pragma(warning( pop )) )
# else
# define EVALUATE_TO_0_START_DISABLE_WARNINGS 0 /*other compilers will not disable warning*/
# define EVALUATE_TO_0_END_DISABLE_WARNINGS 0
# endif
# endif
# define MAKE_CONST_INT(x) MAKE_CONST_INT_HELPER2(x,__LINE__,__COUNTER__)
# define MAKE_CONST_INT_HELPER2(x,line,counter) MAKE_CONST_INT_HELPER(x,line,counter)
# define MAKE_CONST_INT_HELPER(x,line,counter) \
( EVALUATE_TO_0_START_DISABLE_WARNINGS \
+ EVALUATE_TO_0(enum{ INT_CONSTANT_##counter##_AT_LINE_##line = (int)(x) }) \
+ INT_CONSTANT_##counter##_AT_LINE_##line \
+ EVALUATE_TO_0_END_DISABLE_WARNINGS)
#endif
/* ================= test MAKE_CONST_INT() macro ================= */
#define WIDTH 500.5
#define NB 23.2
extern int x[MAKE_CONST_INT(WIDTH/NB)];
Here one example from GNU GCC that can help you:
#pragma GCC diagnostic error "-Wuninitialized"
foo(a); /* error is given for this one */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
foo(b); /* no diagnostic for this one */
#pragma GCC diagnostic pop
foo(c); /* error is given for this one */
#pragma GCC diagnostic pop
foo(d); /* depends on command-line options */

Redundant __thread and omp threadlocal declaration

I am trying to write some library code that may be used by people who have pthreads enabled (or not), and by people who have openmp support (or not). I have some variable that I really want to be in thread-local storage. Is there any potential harm in specifying this twice, for example
#ifdef __GNUC__
# define PREFIX __thread
#elif __STDC_VERSION__ >= 201112L
# define PREFIX _Thread_local
#elif defined(_MSC_VER)
# define PREFIX __declspec(thread)
#else
# define PREFIX
#endif
PREFIX int var = 10;
#pragma omp threadprivate(var)
(Note, the business to figure out the TLS prefix is taken from How to declare a variable as thread local portably?)
I know this works on my system (Debian with recent gcc) but it's hard to know whether things could go wrong elsewhere since these compiler-specific declarations are not part of the OpenMP standard.
What about:
#if __STDC_VERSION__ >= 201112L
# define PREFIX _Thread_local
#elif defined(__GNUC__)
# define PREFIX __thread
#elif defined(_MSC_VER)
# define PREFIX __declspec(thread)
#else
# define PREFIX
#endif
PREFIX int var = 10;
#if !PREFIX
#ifdef _OPENMP
#pragma omp threadprivate(var)
#else
#error "Failure to put variable into TLS"
#endif
#endif
GCC doesn't mind the over-specifying because __thread is an implicit #pragma omp threadprivate anyway.
Instead of worrying about compilers where this might not be the case, just use OpenMP's threadprivate conditionally.

Warning about incorrect packing pragma

How can I get GCC or Clang to warn me about the error below, where M was supposed to be N in line 2?
Even with -Wall -Wextra -Wunknown-pragmas, none of these compilers emit any sort of warning.
#define N 4
#pragma pack(push, M)
int main() {
return 0;
}
#pragma pack(pop)
The compiler cannot know your intentions, only if the code is valid. You can check up on yourself with this
#ifndef M
#error M not defined
#endif
Or if M was defined separately from N with this
#if M != N
#error M is not N
#endif
If you look at the output of the preprocessor the pragma is not evaluated ie if you add N you won't get a 4 after the preprocessor is done.
I don't think you can have it warn here, at least not easily, maybe a preprocessor wizard might be able to figure it out. The following warning does not help unless it's in an undefined value in an #if statement.
-Wundef
If you try and add anything to the pragma ie
#pragma pack(push, (M + 0))
You get a warning because the pragma is expecting an integer or identifier ie
warning: expected integer or identifier in '#pragma pack'

gcc disable ALL warnings for a few lines of code

I have the same problem as described by Jonathon Reinhart here:
Temporarily disable gcc warning on redefinition
That is because I have to use thrid party libraries (C only) which throws tons of warnings like this
Warning "__always_inline" redefined [enabled by default]
What I want is something like this:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-W???"
#include "someheader.h"
#include "otherheader.h"
#pragma GCC diagnostic pop
Is there a way to disable warnings by gcc which are enabled by default with a
#pragma GCC diagnostic ignored
EDIT:
here is the block causing the warning (file: compiler.h):
#if defined(__CC_ARM)
# define __always_inline __forceinline
#elif (defined __GNUC__)
# define __always_inline inline __attribute__((__always_inline__))
#elif (defined __ICCARM__)
# define __always_inline _Pragma("inline=forced")
#endif
I fixed it by undefining all lines where __always_inline was defined. :-(
Thanks Jasen for helping!

Resources