Path: ...!news.mixmin.net!news2.arglkargh.de!news.karotte.org!news.space.net!news.muc.de!.POSTED.news.muc.de!not-for-mail From: Alan Mackenzie Newsgroups: comp.lang.c Subject: Re: Is it possible to generate a compile time error from an inline function? Date: Sat, 13 Jul 2024 17:05:22 -0000 (UTC) Organization: muc.de e.V. Message-ID: References: Injection-Date: Sat, 13 Jul 2024 17:05:22 -0000 (UTC) Injection-Info: news.muc.de; posting-host="news.muc.de:2001:608:1000::2"; logging-data="60923"; mail-complaints-to="news-admin@muc.de" User-Agent: tin/2.6.3-20231224 ("Banff") (FreeBSD/14.0-RELEASE-p5 (amd64)) Bytes: 4020 Lines: 82 Hello, David. Many thanks for the reply! It's just what I was looking for. David Brown wrote: > On 13/07/2024 15:04, Alan Mackenzie wrote: >> Hello, comp.lang.c. >> >> What I want to do is check the validity of (constant) arguments to an >> inline function, and output a compiler error if they are invalid. >> >> In particular, I have: >> >> u32 __always_inline ACM_BITFIELD (u8 a[], int offset, int length) >> >> , which is to extract a bitfield of LENGTH bits, starting at bit number >> OFFSET in the array of bytes A. OFFSET and LENGTH will be known at >> compile time. >> >> For the sake of run time efficiency, I wish to impose the restrictions >> that either (i) the bitfield will be contained entirely within a byte; or >> (ii) the bitfield will be a number of consecutive whole bytes (maximum 32 >> bits). >> >> So, for example, if the code called >> >> foo = ACM_BITFIELD (bar, 14, 4); >> >> , I would like to output the compiler message "Invalid arguments 14, 4, >> to ACM_BITFIELD", since this bitfield straddles two bytes. >> >> Is there any way I can do this in C? (Before anybody asks, yes I have >> looked at doing it with macros, but that seems impractical, if it's even >> possible.) >> >> Thanks! >> > C does not have a way to force checks for this kind of thing at compile > time. But if you are using an optimising compiler, you can perhaps rely > on dead-code elimination along with link-time checks. > For example, declare a function "compile_time_error()" but do not define > it anywhere. Then add a check : > if (length > 8) compile_time_error(); > As long as your check is not too complicated in relation to your > compiler's optimisation abilities, if it knows the value of "length" at > compile time it and can see it is no more than 8, the call to > compile_time_error() will be eliminated. If not, the call will be kept > and your link will fail as the function does not exist. This might be the way to go. The number of erroneous calls to ACM_BITFIELD is expected to be low. The check is just there to make it difficult for the optimisations in the function to create nonsense. But if there are ~30 calls to the function, it would then be difficult to located the erroneous one. So, perhaps .... > If you are using gcc (or, I expect, clang), you can go further. > First, define the compile_time_error() function with an error attribute: > extern void __attribute__((error("Compile time error"))) > compile_time_error(void); > Then if the call is not eliminated, you will get an error message at > compile time rather than waiting for link time. > Add a "__attribute__((always_inline))" attribute to your bitfield > function - if it is used in a context that is not inlined, that will > show up as an error. > You might also find the gcc built-in function __builtin_constant_p(...) > useful to determine if an expression value is known at compile time, in > case you want to add run-time checking for complex cases. Thanks, these are all things I didn't know. I will look them up in the GCC manual. :-) -- Alan Mackenzie (Nuremberg, Germany).