https://github.com/JacksonAllan/CC/blob/42a7d810274a698dff87...
Specifically, if (arg)==(arg) is not a constant expression, then it could have side effects.
However, this mechanism does generate some annoying false positives, as shown below:
// Create a map with int keys and values that are vectors of floats:
map( int, vec( float ) ) our_map;
init( &our_map );
// Create a vector of floats:
vec( float ) our_vec;
init( &our_vec );
push( &our_vec, 1.23f );
// Insert the vector into the map.
insert( &our_map, 456, our_vec );
// Generates a warning because get checks its first argument for side
// effects and the compiler can't tell that the first argument of the
// outermost get has none:
printf( "%f", *get( get( &our_map, 456 ), 0 ) );
// The "proper", albeit cumbersome, way to achieve the same thing without a
// warning:
vec( float ) *itr = get( &our_map, 456 );
printf( "%f", *get( itr, 0 ) );
C here is asserting that the value inside is a constant and then evaluating to that constant.
I mixed it up with a similar compile-time constness check in some of my libraries, where I decided if const of not. gcc throws, only clang could give me a proper answer.
warning: expression in static assertion is not an integer constant expression [-Wpedantic]
Instead you can use the sizeof + compound literal with array type, use the comma operator to preserve the type of the expression and cast the result of sizeof to void to suppress the warning: #define C(x) ( (void)sizeof( (char [(int)(x) || 1]){0} ), (x) )
The only problem is that it doesn't support floating point expressionsThank you! Separately, but related: fuck you, Google! (every time I have to deal with protobuf in C++, I curse Google and their "we don't give a shit about signed vs unsigned comparisons").
Yeah, some warnings are turned off, but not as many as you'd think, and usually for good reasons, which also includes deliberate design decisions. For example, we don't care about pre-C11 compatibility (because we won't build for pre-C11), so that warning is off. We also like 0-sized arrays, so that warning is off as well.
It's a moving target, because compiler engineers add new warnings over time. Adapting the new compiler means taking care of the new warnings. There's almost always a way to do so instead of turning a new warning off.
By keeping your own project warning-free in your environment, you are doing a service to everyone.
edit to add: and yes `-isystem` is absolutely a useful tool. If memory serves, though, it doesn't protect from macro or template expansions, though.
In my fork of chibicc (a small C11 compiler) there are plenty of additional logic that were implemented solely to play nice with C tricks from real world projects that could have been easier if they target later standards. The most recent being how curl's build script determines the size of primitive types: they use (sizeof(T) == N) as a case index and expect the compiler to error on case-duplication[1], I had to add a backtracking loop to check exactly that[2]. I'm not complaining as more error checks isn't a bad thing, however, I'll advise programmers willing to invest in obscure tricks to actually test them on obscure compilers (instead of just flipping -std).
[1]: https://github.com/curl/curl/blob/339464432555b9bd71a5e4a4c4...
[2]: https://github.com/fuhsnn/slimcc/blob/54563ecae8480f836a0bb2...
I don't actually know any details so I don't want to presume, but it wouldn't surprise me at all if targeting later standards simply isn't an option for the curl project due to portability. It may be that the (sizeof(t) == n) trick may just be what consistently works across all targets. (Until yours came along.)
I do remember when configure etc. still had to check whether ANSI prototypes (as opposed to the original K&R style declarations) were supported... I hope that check isn't much of a thing anymore.
Why not push/pop warnings to ignore in the library?
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wshadow\"")
int a = 1;
{
int a = 2;
}
_Pragma("GCC diagnostic pop")
But you don't want to disable warnings throughout the file, just locally.
> Then you don't have non-portable cruft littering the code,
You can make it perfectly portable, with a little macro work. See, ,for example:
https://github.com/eyalroz/printf/blob/013db1e345cbb166a7eb7...
(this is from the standalone-no-libc-printf-family-implementation I maintain; the library is C, the test suite is C++ but it doesn't matter for the purposes of my point here.)
and that you only need to do once in your project (you can make it your own header). Even when it comes to use - you can place your warning-disabling within another macro, so that you end up only using a simple single macro for your actual code.
* Some versions can only change compiler options at top level, not within a function.
* I had problems with trying to push/ignore/pop a warning around an expression in a macro, since the entire thing expands at a single location.
I seem to remember there's actually a solution for this .. at least on clang and I think MSVC .. you can programmatically turn warnings on/on with the _Pragma() macro. I don't remember exactly what you put in it, but it's designed specifically for this kind of macro nonsense
If you don't know what type of integer your preprocessor is using for arithmetic, you can still do right-shifts by up to 14 at a time, since `int` must be at least 16 bits and you can't use the sign bit.
Y_Y•2mo ago
https://en.cppreference.com/w/c/language/constexpr
lpribis•2mo ago
cmptrnerd6•2mo ago
pantalaimon•2mo ago
The problem is if you want to also still support esp8266 which is forever stuck at GCC 8.4
Y_Y•2mo ago
Aardwolf•2mo ago