On 22/09/2019 17:20, Manfred wrote:
> On 9/18/2019 12:04 PM, David Brown wrote:
>> I use this:
>>
>> // Non-existent function called if it is known at compile-time that an
>> // assume will fail
>> extern void __attribute__((error("Assume failed"))) assumeFailed(void);
>>
>> // The compiler can assume that "x" is true, and optimise or warn
>> // accordingly
>> // If the compiler can see that the assume will fail, it gives an error
>> #define assume(x) \
>> do { \
>> if (__builtin_constant_p(x)) { \
>> if (!(x)) { \
>> assumeFailed(); \
>> } \
>> } \
>> if (!(x)) __builtin_unreachable(); \
>> } while (0)
>
> I am not an expert in gcc builtins, so I may be wrong, however it looks
> like there might be a small risk in that it suffers from the common
> problem with macros, i.e. 'x' is evaluated a number of times.
My understanding (through tests and a rough understanding of what the
builtin does, but not through documentation in the manual) is that
__builtin_constant_p() does not evaluate the expression. If it is true,
then it doesn't matter that "x" is evaluated several times - after all,
it is a compile-time constant. So "x" is only evaluated once in cases
where it may matter.
> The risk is small because obviously this kind of expression is not meant
> to have side effects on the argument, but still..
>
Agreed.
It is always important to consider whether there are multiple
evaluations in a macro, and whether it is relevant. Although it does
not matter in this case, in general it is a good idea to write something
like this:
#define assume(x) \
do { \
const auto xx = x; \
if (__builtin_constant_p(xx)) { \
if (!(xx)) { \
assumeFailed(); \
} \
} \
if (!(xx)) __builtin_unreachable(); \
} while (0)
For C, use "const __auto_type xx = x;" - it's a gcc extension, but so
are the builtins.