From: Vincent Mailhol > Sent: 07 December 2024 13:51 ... > > > It seems to me that the long term solution to this problem are the > > > constexpr functions. > > > > How would constexpr functions help here? (I am a bit sceptical about > > constexpr functions.) > > I was thinking of some of the "side features" of constexpr functions. Namely: > > - std::is_constant_evaluated > Link: https://en.cppreference.com/w/cpp/types/is_constant_evaluated > > - if consteval > Link: https://en.cppreference.com/w/cpp/language/if#Consteval_if > > I did not try it, but looking at these, I believe that this would > allow us to rewrite most of our macros into some constexpr functions. IIRC (and trying to understand the definitions) they are backwards from what the kernel tests are trying to achieve. The kernel wans to add additional compile-time tests where possible. This is often restricted to checking values that are compile time constants (for some definition of constant). The C++ 'constexpr' is about determining the context in which a function is called. Remember in C 'static int x = expr;' requires that 'expr' is a constant so that the asm can contain 'x: .word value', but C++ is perfectly willing to add an entry to the 'global constructors' and call a function for you. This is not useful default behaviour. The 'constexpr' stuff seems to be about detecting some of these cases so the function can return a different value - and then possibly be optimised away. The kernel is trying to get some test coverage at compile time without affecting run-time. The compile-time checks all get more complicated because things like initialisers have to be 'integer constant expressions' rather than the more relaxed 'compile time constant' (array bounds probably do need to be the former). This is (probably) what stops ({ expr; }) being used for initialisers even when the value is a compile time constant. Relaxing that rule would be useful. Then there is the brain-dead definition of _Static_assert() that makes it pretty near completely useless (I can't remember Linus's words) for anything non-trivial. To be useful it would need to be deferred until after the optimiser has done all its processing an only trigger if the call hasn't been optimised away and the condition is either non-constant or false. clang's 'infinite wisdom' decided to unconditionally output the cpp output of the expression in the error message (even when there was a caller provided message). When min() was using it that could be a few hundred bytes of impenetrable text in a normal call - never mind the nested ones that hit 10+MB because of a requirement to return 'constant integer expressions'. It would also be useful to have a 'warning' form (or even an 'info' that isn't an error even with -Werror). Then you get _Generic(). WTF do the unselected cases not only have to be valid C but also get checked for some warnings (like -Wsign-compare and 'unsigned >= 0'). ... > I was invited to WG14 this September. For now, I am only lurking. The > thing I have in mind right now is to write a paper to allow the use of > static_assert() in expressions (i.e. make it return 0 on success). > That should be a relatively small change, but would bring a nice > quality of life improvement. Adding gcc's ({ expr; }) to the standard and allowing its output to be as 'constant' as anything in 'expr' would solve a lot of issues. You need to be able to have: if (x) static_assert(y) for static_assert() to be usable as the main method of reporting these sort on messages. The best one in the kernel (ab)uses the message for calling a deprecated function. There are other things that get annoying. I understand why offsetof() needs to be a 'compile time constant', but that should only be for constant input. There is no reason why offsetof(x, y[expression]) should be invalid C for a non-constant expression. (Although I've had issues even with a constant expression with a certain compiler I'm forced to use sometimes.) David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)