| Deutsch English Français Italiano |
|
<e4c6a99e1aa3a28e6f8f6176a6cc6678954156a2@i2pn2.org> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!weretis.net!feeder9.news.weretis.net!i2pn.org!i2pn2.org!.POSTED!not-for-mail
From: Richard Damon <richard@damon-family.org>
Newsgroups: comp.lang.c
Subject: Re: Is it possible to generate a compile time error from an inline
function?
Date: Sat, 13 Jul 2024 14:07:58 -0400
Organization: i2pn2 (i2pn.org)
Message-ID: <e4c6a99e1aa3a28e6f8f6176a6cc6678954156a2@i2pn2.org>
References: <v6tu04$klr$1@news.muc.de> <v6u5lq$3krbn$1@dont-email.me>
<v6uc4i$1rfr$1@news.muc.de>
<fb9c29d418c137a633f136a36a128ea57532adad@i2pn2.org>
<v6uf3v$1rfr$2@news.muc.de>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sat, 13 Jul 2024 18:07:58 -0000 (UTC)
Injection-Info: i2pn2.org;
logging-data="3137773"; mail-complaints-to="usenet@i2pn2.org";
posting-account="diqKR1lalukngNWEqoq9/uFtbkm5U+w3w6FQ0yesrXg";
User-Agent: Mozilla Thunderbird
X-Spam-Checker-Version: SpamAssassin 4.0.0
In-Reply-To: <v6uf3v$1rfr$2@news.muc.de>
Content-Language: en-US
Bytes: 5897
Lines: 115
On 7/13/24 1:56 PM, Alan Mackenzie wrote:
> Hello, Richard.
>
> Richard Damon <richard@damon-family.org> wrote:
>> On 7/13/24 1:05 PM, Alan Mackenzie wrote:
>>> Hello, David.
>
>>> Many thanks for the reply! It's just what I was looking for.
>
>>> David Brown <david.brown@hesbynett.no> 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. :-)
>
>
>> In C++, I would use constexpr and static_assert to do this, and your
>> compiler might allow its use in C as an extension.
>
> C++ isn't an option.
The question being since most C compilers are also C++ compilers, they
somethings accept this sort of C++ism as an extension.
>
>> If not, in C you could use just _Static_assert, perhaps in the expansion
>> of a macro that generates the expression that does the testing.
>
> Yes, that's an even better idea, thanks. Looking it up in
> https://en.cppreference.com, _Static_assert has existed in C since C11,
> that spelling being deprecated in favour of static_assert in C23. I just
> need to check the project I'm working in doesn't still support C < C11.
>
If the compiler doesn't support some form of static assert, you cam make
one yourself with a macro.
#define static_assert(x) extern int _static_assert[(x) ? 1 : -1]
Possible adding whatever hacks you want to make the variable unique, (or
make it a typedef, or whatever). (a typedef doesn't add an external
symbol that is never used, so might be clearer, but needs something to
make the name unique)
The key idea is a array of negative size is a constraint error, so if x
is false you get the error.