_Static_assert in unused generic selection - c

It looks like the typeof operator is likely to be accepted into the next C standard, and I was looking to see if there was a way to leverage this to create a macro using portable ISO-C that can get the length of an array passed into it or fail to compile if a pointer is passed into it. Normally generic selection can be used to force a compiler error when using an unwanted type by leaving it out of the generic association list, but in this case, we need a default association to deal with arrays of any length, so instead I am trying to force a compiler error for the generic association for the type we don't want. Here's an example of what the macro could look like:
#define ARRAY_SIZE(X) _Generic(&(X), \
typeof(&X[0]) *: sizeof(struct{_Static_assert(0, "Trying to get the array length of a pointer"); int _a;}), \
default: (sizeof(X) / sizeof(X[0])) \
)
The problem is that _Static_assert is tripping even when the generic association selected is the default association. For sake of simplicity, since the issue at hand is not related anything being introduced in C23, we'll make a test program that works explicitly to reject a pointer to int:
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_SIZE(X) _Generic(&(X), \
int **: sizeof(struct{_Static_assert(0, "Trying to get the array length of a pointer"); int _a;}), \
default: (sizeof(X) / sizeof(X[0])) \
)
int main(void) {
int x[100] = {0};
int *y = x;
int (*z)[100] = {&x};
printf("length of x: %zu\n", ARRAY_SIZE(x));
printf("length of y: %zu\n", ARRAY_SIZE(y));
printf("length of z: %zu\n", ARRAY_SIZE(z));
printf("length of *z: %zu\n", ARRAY_SIZE(*z));
return EXIT_SUCCESS;
}
Building the above with -std=c11, I find _Static_assert tripping on all expansions of ARRAY_SIZE when I would expect to only have problems with the pointers that will use the int ** generic association.
According to 6.5.1.1 p3 of the C11 standard for Generic Selection,
None of the expressions from any other generic association of the generic selection is evaluated
Is this a bug in gcc and clang, or is there something I've missed in the standard that would cause the compile-time evaluation of this _Static_assert in the unused generic association?

It doesn't matter which generic selection is evaluated.
When the expression that is part of a _Status_assert has the value 0, this is considered a constraint violation and the compiler is required to generate a diagnostic.

You can't really mix _Static_assert with expressions that should return a value, such as a function-like macro. You could perhaps work around that with a "poor man's static assert", like one of the ugly tricks we used before C11:
#define POOR_STATIC_ASSERT(expr) (int[expr]){0}
#define CHECK(X) _Generic((&X), \
int **: 0,\
default: (sizeof(X) / sizeof(X[0])) \
)
#define ARRAY_SIZE(X) ( (void)POOR_STATIC_ASSERT(CHECK(X)), CHECK(X) )
Here the comma operator is called to have the macro CHECK return the size or zero, in case a type is valid or not. Then call the same macro again to have that one returned from the function-like macro ARRAY_SIZE. This will lead to some cryptic error from an ISO C compiler such as "error: ISO C forbids zero-size array".
The next problem is that &(X) in _Generic is by no means guaranteed to boil down to a int** so this macro isn't safe or reliable. Regarding array sizes though, there's a trick we can use. A pointer to an array of no size (incomplete type) is compatible with every array of the same element type no matter it's size. The macro could be rewritten as:
#define POOR_STATIC_ASSERT(expr) (int[expr]){0}
#define CHECK(X) _Generic((&X), \
int (*)[]: sizeof(X) / sizeof(X[0]), \
default: 0)
#define ARRAY_SIZE(X) ( (void)POOR_STATIC_ASSERT(CHECK(X)), CHECK(X) )
This will work for any int array no matter size but fail for everything else.

Utilizing some of the suggestions from Lundin's answer, I have come up with the following solution to the simplified problem:
#define STATIC_ASSERT_EXPRESSION(X, ERROR_MESSAGE) (sizeof(struct {_Static_assert((X), ERROR_MESSAGE); int _a;}))
#define NO_POINTERS(X) _Generic(&(X), \
int (*)[]: 1, \
default: 0 \
)
#define ARRAY_SIZE(X) ( (void)STATIC_ASSERT_EXPRESSION(NO_POINTERS(X), "Cannot retrieve the number of array elements from a pointer"), (sizeof(X) / sizeof(X[0])) )
For the actual use-case to be type generic using typeof, which should be coming to the C23 standard, replace the NO_POINTERS macro using this:
#define NO_POINTERS(X) _Generic(&(X), \
typeof(*X) (*)[]: 1, \
default: 0 \
)
By moving the _Static_assert outside of the Generic Selection, it will only be evaluated with the value that actually returns from the selection, so it won't get fired off for existing in an unused selection. Additionally, the number of elements calculation was also removed from the generic selection so that expression of the generic selection could safely be used in a Static Assert even if your array was a Variable-Length array which requires its size to be calculated at run-time.
The Static Assert itself is placed inside of an anonymous struct that we take the sizeof so that it is a part of an expression. And then as in Lundin's example, we use the comma operator to have that expression evaluated, and then thrown out and use the results of the array size calculation.
With this, we reject pointers while getting the number of elements in both static arrays and VLAs, plus we get a nice compiler error message when trying to pass in a pointer.

Related

Implementing std::bit_cast equivalent in C

Is it possible to implement something similar to C++20's std::bit_cast in C? It would be a lot more convenient than using union or casting pointers to different types and dereferencing.
If you had a bit_cast, then implementing some floating point functions would be easier:
float Q_rsqrt( float number )
{
int i = 0x5f3759df - ( bit_cast(int, number) >> 1 );
float y = bit_cast(float, i);
y = y * ( 1.5f - ( number * 0.5f * y * y ) );
y = y * ( 1.5f - ( number * 0.5f * y * y ) );
return y;
}
See also Fast inverse square root
The naive solution is:
#define bit_cast(T, ...) (*(T*) &(__VA_ARGS__))
But it has major problems:
it is undefined behavior because it violates strict aliasing
it doesn't work for bit-casting rvalues because we are taking the address of the second operand directly
it doesn't make sure that the operands have the same size
Can we implement a bit_cast without these issues?
It is possible in non-standard standard C, thanks to typeof. typeof is also a further proposed feature for C23, so it may become possible in standard C23. One of the solutions below makes some sacrifices which allow C99 compliance.
Implementation Using union
Let's look at how the approach using union works first:
#define bit_cast(T, ...) \
((union{typeof(T) a; typeof(__VA_ARGS__) b;}) {.b=(__VA_ARGS__)}.a)
We are creating a compound literal from an anonymous union made of T and whatever type the given expression has. We initialize this literal to .b= ... using designated initializers and then access the .a member of type T.
The typeof(T) is necessary if we want to pun function pointers, arrays, etc., due to C's type syntax.
Implementation using memcpy
This implementation is slightly longer, but has the advantage of relying only on C99, and can even work without the use of typeof:
#define bit_cast(T, ...) \
(*(typeof(T)*) memcpy(&(T){0}, &(typeof(__VA_ARGS__)) {(__VA_ARGS__)}, sizeof(T)))
We are copying from one compound literal to another and then accessing the destination's value:
the source literal is a copy of our input expression, which allows us to take its address, even for bit_cast(float, 123) where 123 is an rvalue
the destination is a zero-initialized literal of type T
memcpy returns the destination operand, so we can cast the result to typeof(T)* and then dereference that pointer.
We can completely eliminate typeof here and make this C99-compliant, but there are downsides:
#define bit_cast(T, ...) \
(*((T*) memcpy(&(T){0}, &(__VA_ARGS__), sizeof(T))))
We are now taking the address of the expression directly, so we can't use bit_cast on rvalues anymore. We are using T* without typeof, so we can no longer convert to function pointers, arrays, etc.
Implementing Size Checking (since C11)
As for the last issue, which is that we don't verify that both operands have the same size: We can use _Static_assert (since C11) to make sure of that. Unfortunately, _Static_assert is a declaration, not an expression, so we have to wrap it up:
#define static_assert_expr(...) \
((void) (struct{_Static_assert(__VA_ARGS__); int _;}) {0})
We are creating a compound literal that contains the assertion and discarding the expression.
We can easily integrate this in the previous two implementations using the comma operator:
#define bit_cast_memcpy(T, ...) ( \
static_assert_expr(sizeof(T) == sizeof(__VA_ARGS__), "operands must have the same size"), \
(*(typeof(T)*) memcpy(&(T){0}, &(typeof(__VA_ARGS__)) {(__VA_ARGS__)}, sizeof(T))) \
)
#define bit_cast_union(T, ...) ( \
static_assert_expr(sizeof(T) == sizeof(__VA_ARGS__), "operands must have the same size"), \
((union{typeof(T) a; typeof(__VA_ARGS__) b;}) {.b=(__VA_ARGS__)}.a) \
)
Known and Unfixable Issues
Because of how macros work, we can not use this if the punned type contains a comma:
bit_cast(int[0,1], x)
This doesn't work because macros ignore square brackets and the 1] would not be considered part of the type, but would go into __VA_ARGS__.

Compile-time assertion to determine if pointer is an array

Currently, I have the following block of code to make safe string copying (it works):
#define STRCPY(dst, src) do { assert(((void*)(dst)) == ((void*) & (dst))); \
strlcpy(dst, src, sizeof(dst)); } while (0)
So it accepts the construction like:
const char *src = "hello";
char dest[5];
STRCPY(dest, src); //hell
And denies the following:
void (char *dst) {
STRCPY(dst, "heaven"); //unknown size of dst
}
The problem is that the block of code creates an assertion. Is there a way to perform this check on compilation time?
So I want to have the error on compilation (like creating an array with negative size) instead of crashing code if it possible.
If standard C is available, then you can do this:
#define STRCPY(dst, src) \
_Generic(&(dst), \
char(*)[sizeof(dst)]: strlcpy(dst,src,sizeof(dst)) )
Explanation:
You can't use a _Generic expression on an array type, because it is not one of the special cases that is exempt from the "array decay" rule (C17 6.3.2.1 ยง3). So by simply using _Generic((dst), ... in my example, dst would end up as a char* when the expression is evaluated, and then we would lose the information of its original type.
But if we take the address of the array using &, we do utilize one of those special cases and the array decay doesn't happen. Instead we end up with an array pointer, meaning that _Generic will have to check for an array pointer of the expected type and size: char(*)[sizeof(dst)].
As a side-note/safety concern, I never use do-while(0) macros and discourage them, but that's another story.
For compile-time assertion on whether or not dst is an array,
I would use #Lundin solution (or _Static_assert) in case C11 is available.
Else, I would use the following:
#define BUILD_BUG_ON_NON_ARRAY_TYPE(e) (sizeof(struct { int:-!!(((void*)(e)) != ((void*) & (e))); }))
Which basically takes your compile-time evaluated expression ((void*)(dst)) == ((void*) & (dst)) but instead of using it in run time assert just use it in a compile-time assertion manner.
So, overall I would change your macro into:
#define STRCPY(dst, src) do { BUILD_BUG_ON_NON_ARRAY_TYPE(dst); \
strlcpy(dst, src, sizeof(dst)); } while (0)
I've found that my post was closed as duplicated for a while and followed the link mentioned.
The solution is only for GCC, but it's fine for me, because I have night builds on GCC too. So the pre-draft of the code is:
#if defined(__GNUC__)
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#define STRCPY(dst,src) do{__must_be_array(dst);strlcpy(dst, src, sizeof(dst));}while(0)
#else
#define STRCPY(dst,src) do{strlcpy(dst, src, sizeof(dst));}while(0)
#endif
If you want to check it the only way I can think of is:
assert((sizeof(dst)) != (sizeof(void*)));
but it only work if the size of the array is different than the size of the pointer on OPs system

How to check if an array is of constant known size? [duplicate]

The standard array-size macro that is often taught is
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
or some equivalent formation. However, this kind of thing silently succeeds when a pointer is passed in, and gives results that can seem plausible at runtime until things mysteriously fall apart.
It's all-too-easy to make this mistake: a function that has a local array variable is refactored, moving a bit of array manipulation into a new function called with the array as a parameter.
So, the question is: is there a "sanitary" macro to detect misuse of the ARRAYSIZE macro in C, preferably at compile-time? In C++ we'd just use a template specialized for array arguments only; in C, it seems we'll need some way to distinguish arrays and pointers. (If I wanted to reject arrays, for instance, I'd just do e.g. (arr=arr, ...) because array assignment is illegal).
Linux kernel uses a nice implementation of ARRAY_SIZE to deal with this issue:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
with
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
and
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
Of course this is portable only in GNU C as it makes use of two instrinsics:
typeof operator and __builtin_types_compatible_p function. Also it uses their "famous" BUILD_BUG_ON_ZERO macro which is only valid in GNU C.
Assuming a compile time evaluation requirement (which is what we want), I don't know any portable implementation of this macro.
A "semi-portable" implementation (and which would not cover all cases) is:
#define ARRAY_SIZE(arr) \
(sizeof(arr) / sizeof((arr)[0]) + STATIC_EXP(IS_ARRAY(arr)))
with
#define IS_ARRAY(arr) ((void*)&(arr) == &(arr)[0])
#define STATIC_EXP(e) \
(0 * sizeof (struct { int ARRAY_SIZE_FAILED:(2 * (e) - 1);}))
With gcc this gives no warning if argument is an array in -std=c99 -Wall but -pedantic would gives a warning. The reason is IS_ARRAY expression is not an integer constant expression (cast to pointer types and subscript operator are not allowed in integer constant expressions) and the bit-field width in STATIC_EXP requires an integer constant expression.
This version of ARRAYSIZE() returns 0 when arr is a pointer and the size when its a pure array
#include <stdio.h>
#define IS_INDEXABLE(arg) (sizeof(arg[0]))
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
#define ARRAYSIZE(arr) (IS_ARRAY(arr) ? (sizeof(arr) / sizeof(arr[0])) : 0)
int main(void)
{
int a[5];
int *b = a;
int n = 10;
int c[n]; /* a VLA */
printf("%zu\n", ARRAYSIZE(a));
printf("%zu\n", ARRAYSIZE(b));
printf("%zu\n", ARRAYSIZE(c));
return 0;
}
Output:
5
0
10
As pointed out by Ben Jackson, you can force a run-time exception (dividing by 0)
#define IS_INDEXABLE(arg) (sizeof(arg[0]))
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
#define ARRAYSIZE(arr) (sizeof(arr) / (IS_ARRAY(arr) ? sizeof(arr[0]) : 0))
Sadly, you can't force a compile-time error (the address of arg must be compared at run-time)
With C11, we can differentiate arrays and pointers using _Generic, but I have only found a way to do it if you supply the element type:
#define ARRAY_SIZE(A, T) \
_Generic(&(A), \
T **: (void)0, \
default: _Generic(&(A)[0], T *: sizeof(A) / sizeof((A)[0])))
int a[2];
printf("%zu\n", ARRAY_SIZE(a, int));
The macro checks: 1) pointer-to-A is not pointer-to-pointer. 2) pointer-to-elem is pointer-to-T. It evaluates to (void)0 and fails statically with pointers.
It's an imperfect answer, but maybe a reader can improve upon it and get rid of that type parameter!
Modification of bluss's answer using typeof instead of a type parameter:
#define ARRAY_SIZE(A) \
_Generic(&(A), \
typeof((A)[0]) **: (void)0, \
default: sizeof(A) / sizeof((A)[0]))
Here's one possible solution using a GNU extension called statement expressions:
#define ARRAYSIZE(arr) \
({typedef char ARRAYSIZE_CANT_BE_USED_ON_POINTERS[sizeof(arr) == sizeof(void*) ? -1 : 1]; \
sizeof(arr) / sizeof((arr)[0]);})
This uses a static assertion to assert that sizeof(arr) != sizeof(void*). This has an obvious limitation -- you can't use this macro on arrays whose size happens to be exactly one pointer (e.g. a 1-length array of pointers/integers, or maybe a 4-length array of bytes on a 32-bit platform). But those particular instances can be worked around easily enough.
This solution is not portable to platforms which don't support this GNU extension. In those cases, I'd recommend just using the standard macro and not worry about accidentally passing in pointers to the macro.
Here's another one which relies on the gcc typeof extension:
#define ARRAYSIZE(arr) ({typeof (arr) arr ## _is_a_pointer __attribute__((unused)) = {}; \
sizeof(arr) / sizeof(arr[0]);})
This works by attempting to set up an identical object and initializing it with an array designated initializer. If an array is passed, then the compiler is happy. If pointer is passed the compiler complains with:
arraysize.c: In function 'main':
arraysize.c:11: error: array index in non-array initializer
arraysize.c:11: error: (near initialization for 'p_is_a_pointer')
my personal favorite, tried gcc 4.6.3 and 4.9.2:
#define STR_(tokens) # tokens
#define ARRAY_SIZE(array) \
({ \
_Static_assert \
( \
! __builtin_types_compatible_p(typeof(array), typeof(& array[0])), \
"ARRAY_SIZE: " STR_(array) " [expanded from: " # array "] is not an array" \
); \
sizeof(array) / sizeof((array)[0]); \
})
/*
* example
*/
#define not_an_array ((char const *) "not an array")
int main () {
return ARRAY_SIZE(not_an_array);
}
compiler prints
x.c:16:12: error: static assertion failed: "ARRAY_SIZE: ((char const *) \"not an array\") [expanded from: not_an_array] is not an array"
One more example to the collection.
#define LENGTHOF(X) ({ \
const size_t length = (sizeof X / (sizeof X[0] ?: 1)); \
typeof(X[0]) (*should_be_an_array)[length] = &X; \
length; })
Pros:
It works with normal arrays, variable-length arrays, multidimensional
arrays, arrays of zero sized structs
It generates a compilation error (not warning) if you pass any pointer, struct or
union
It does not depend on any of C11's features
It gives you very readable error
Cons:
It depends on some of the gcc extensions: Typeof,
Statement Exprs, and (if you like it) Conditionals
It depends on C99 VLA feature
Awful, yes, but that works and it is portable.
#define ARRAYSIZE(arr) ((sizeof(arr) != sizeof(&arr[0])) ? \
(sizeof(arr)/sizeof(*arr)) : \
-1+0*fprintf(stderr, "\n\n** pointer in ARRAYSIZE at line %d !! **\n\n", __LINE__))
This will not detect anything at compile time but will print out an error message in stderr and return -1 if it is a pointer or if the array length is 1.
==> DEMO <==

C11 _Generic() - How can I suppress gcc code evaluation (Error check) for selections which are not matching with selector

P.S.- I have taken int and int * for simplicity purpose, It can also be struct and struct *.
I am trying to implement a macro to copy data present in one variable to other independent of the variable datatype, In the below solution I am using '_Generic' compiler feature.
program 1:
#include<stdio.h>
#include <string.h>
#define copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void *)&var,sizeof(int));}),\
int *:({memcpy(newVar,(void *)var,sizeof(int));}),default:newVar=var)
int main() {
int data = 2;
int *copy;copy = (int *)malloc(sizeof(int));
copyVar(data,copy);
printf("copied Data=%i",*copy);
}
Program 2:
#include<stdio.h>
#include <string.h>
#define copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void *)&var,sizeof(int));}),\
int *:({memcpy(newVar,(void *)var,sizeof(int));}),default:newVar=var)
int main() {
int data = 2;
int *copy;copy = (int *)malloc(sizeof(int));
copyVar(&data,copy);
printf("copied Data=%i",*copy);
}
Now problem is, 'program 1' get compiled successfully despite some warning.
But while compiling program 2 gcc throwing error:
error: lvalue required as unary '&' operand #define
copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void
*)&var,sizeof(int));}),
and I assume this is due to since _Generic int: selection get preprocessed with one more ampersand
(void *)&&var
why is gcc evaluates all selection?
Your code has various problems: you copy data into an uninitialized pointed, you have superfluous void* casts, you treat _Generic as some sort of compound statement instead of an expression, and so on.
But to answer your question, your code doesn't work because the result of &something is not a lvalue. Since the & operator needs a lvalue, you cannot do & &something. (And you cannot do &&something either because that gets treated as the && operator by the "maximum munch rule".)
So your code doesn't work for the same reason as this code doesn't work:
int x;
int**p = & &x;
gcc tells you that &x is not a lvalue:
lvalue required as unary '&' operand
EDIT - clarification
This _Generic macro, like any macro, works like pre-processor text replacement. So when you have this code in the macro:
_Generic((var), ...
int: ... (void *)&var
int*: ... (void)var
It gets pre-processed as
_Generic((&data), ...
int: ... (void *)& &data
int*: ... (void)&data
And all paths of the _Generic expression are pre-processed. _Generic itself is not part of the pre-processor, but gets evaluated later on, like any expression containing operators. The whole expression is checked for syntactic correctness, even though only one part of the expression is evaluated and executed.
The indented original use of _Generic is with function pointers as here
#define copyVar(var,newVar) \
_Generic((var), \
int: function1, \
int*: function2, \
default:function3)(&(var), &(newVar))
Here the generic expression chooses the function and then this function is applied to whatever are the arguments.
You would have to write the three stub functions that correspond to the three different cases.
If you have them small and nice and as inline in your header file, the optimizer will usually ensure that this mechanism does not have a run time overhead.
This can be solved with a two level _Generic
#define copyVar(var,newVar) \
_Generic((var), \
int : ({ __auto_type _v = var; memcpy(newVar, (void *) _Generic((_v), int: &_v , int *: _v) , sizeof(int));}) , \
int *: ({ __auto_type _v = var; memcpy(newVar, (void *) _v , sizeof(int));}) , \
default: newVar=var \
)

How to check if a parameter is an integral constant expression in a C preprocessor macro?

I'm currently cleaning up an existing C-library to publish it shamelessly.
A preprocessor macro NPOT is used to calculate the next greater power of two for a given integral constant expression at compile time. The macro is normally used in direct initialisations. For all other cases (e.g. using variable parameters), there is an inline function with the same function.
But if the user passes a variable, the algorithm expands to a huge piece of machine code. My question is:
What may I do to prevent a user from passing anything but an integral constant expression to my macro?
#define NPOT(x) complex_algorithm(x)
const int c=10;
int main(void) {
int i=5;
foo = NPOT(5); // works, and does everything it should
foo = NPOT(c); // works also, but blows up the code extremely
foo = NPOT(i); // blows up the code also
}
What I already tried:
Define the macro to #define NPOT(x) complex_algorithm(x ## u). It still works and throws a - even if hardly helpful - compiler error for variable parameters. Unless there is no variable like iu... Dirty, dangerous, don't want it.
Documentation, didn't work for most users.
You can use any expression that needs a constant integral expression and that will then be optimized out.
#define NPOT(X) \
(1 \
? complex_algorithm(X) \
: sizeof(struct { int needs_constant[1 ? 1 : (X)]; }) \
)
eventually you should cast the result of the sizeof to the appropriate integer type, so the return expression is of a type that you'd expect.
I am using an untagged struct here to
have a type so really no temporary is produced
have a unique type such that the expression can be repeated anywhere in the code without causing conflicts
trigger the use of a VLA, which is not allowed inside a struct as of C99:
A member of a structure or union may have any object type other than a
variably modified type.
I am using the ternary ?: with 1 as the selecting expression to ensure that the : is always evaluated for its type, but never evaluated as an expression.
Edit: It seems that gcc accepts VLA inside struct as an extension and doesn't even warn about it, even when I explicitly say -std=c99. This is really a bad idea of them.
For such a weird compiler :) you could use sizeof((int[X]){ 0 }), instead. This is "as forbidden" as the above version, but additionally even gcc complains about it.
#define INTEGRAL_CONST_EXPR(x) ((void) sizeof (struct {int a:(x);}), (x))
This will give a compile error if x is not a integral constant expression.
my_function(INTEGRAL_CONST_EXPR(1 + 2 + 3)); // OK
my_function(INTEGRAL_CONST_EXPR(1.0 + 2 + 3)); // compile error
Note that this solution does not work for initializing a static variable:
static int a = INTEGRAL_CONST_EXPR(2 + 3);
will trigger a compile error because of an expression with , is not a constant expression.
As #JensGustedt put in the comment, an integral constant expression resolving to a negative integer number cannot be used in this solution as bit-field width cannot be negative.

Resources