C++ Logo


Advanced search

Re: [wg14/wg21 liaison] P2961R1 syntax for Contracts: viable for C?

From: Timur Doumler <cpp_at_[hidden]>
Date: Sun, 8 Oct 2023 14:02:08 +0300
Hi Martin,

I think this is just one of those cases where C and C++ have different priorities and unfortunately it is impossible to make everyone happy.

In C++, context-sensitive keywords are common, and in this particular case, using context-sensitive keywords for `pre` and `post` allow us to use any identifier we want without breaking any existing code. The keywords `pre` and `post` have been chosen carefully and gained strong consensus (see P1344R1 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1344r1.md>). Replacing them with longer, "uglier" keywords in C++ so that C can have a non-context-sensitive keyword that doesn't start with an underscore is a tradeoff that simply doesn't make sense for C++ and it doesn't have any realistic chance of gaining consensus in SG21 from my perspective.

I do care about C compatibility (which is why I started that thread), but I think that using _Pre and _Post in C is a reasonable compromise, at least for now. This gives you the ability to #define pre _Pre for newer compilers and thus have code with Contracts shared between C and C++, while at the same time macro away Contracts entirely for backwards-compatibility with older compilers. Yes, the macroing away might no longer be possible with post-C++26 extensions, but even then, both code sharing between C and C++ and backwards-compatibility with older compilers can be achieved by wrapping the Contract annotations themselves into macros, like we do for many other features already. This isn't ideal but seems like a reasonable compromise to me. And you are of course free to propose a syntax for the post-C++ extensions that is more compatible with function-like macros than the solutions proposed so far – if such a paper materialises, we will consider it in SG21.

To me, this compromise sounds doable, consistent with what we've done before for other features shared between C and C++, and still better than using [[ ... ]] which apparently in C has the notion of "this is token-ignorable". At least for newer compilers that know about Contracts, token-ignoring Contracts is not something that I would want to allow or encourage. Attributes in C are all either for enabling/disabling warnings or for giving optimisation hints to the backend. Contracts are not like that at all. They are a core language feature and there is nothing "optional" about them – in the sense that an implementation shouldn't be allowed to just not implement them and still be conforming.

Anyway, I hope this makes sense, but if I'm missing something please let me know!


> On 8 Oct 2023, at 09:17, Martin Uecker <ma.uecker_at_[hidden]> wrote:
> Am Samstag, dem 07.10.2023 um 18:35 +0300 schrieb Timur Doumler via Liaison:
>> Right. I see.
>> In this case you are right, P2961 as proposed for C++26 seems fully compatible with function-like-macro-ing it away in C if you so desire. The planned post-C++26 extensions are not, but we can deal with that later.
> I agree, when it is understood that the extensions
> are problematic.
>> So it seems to me now that — possible post-C++26 extensions aside — the P2961 syntax is actually *more* backwards compatible than the P2935 (attribute-like) syntax. With P2961, you can adopt the same syntax in C using _Pre and _Post as the keywords and then do something along the lines of
>> #define pre _Pre
>> #else
>> #define pre(...) // nothing
>> #endif
>> And then you can use standard Contract syntax even with an old compiler! On the other hand, with P2935 (attribute-like syntax), you can't do that, you'd have to wait for your compiler to know at least to ignore the colon inside [[ ... ]] which it doesn't currently do (all major compilers issue a parse error).
>> @Martin: considering the above, do you have any more thoughts on this?
> There is still the issue that "pre" and "post" will collide
> with existing code.
> And context sensitive keywords do not currently exist and
> are also problematic. _Pre and _Post would work, but our
> general goal is to then transition to lower case keywords
> later (as we did already for many in C23), and I am not
> sure this works for "pre" and "post".
> But these issues have been pointed out by others before.
> Martin
>> Cheers,
>> Timur
>>> On 7 Oct 2023, at 17:44, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote:
>>> On Sat, 7 Oct 2023 at 17:37, Ville Voutilainen
>>> <ville.voutilainen_at_[hidden]> wrote:
>>>>> Wait, not quite:, there is the syntax for return values in postconditions which is not a future extension – that's being proposed now:
>>>>> int f()
>>>>> post (ret: ret >= 0);
>>>>> Is that colon in there compatible with function-like macros? Because that's not valid function call syntax at least.
>>>> Of course it is, the argument list of a macro is just a token or
>>>> multiple tokens. Thus:
>>>> #define post(X)
>>>> void f(int x, int y)
>>>> post(ret: ret >= 0)
>>>> {
>>>> (void)x;
>>>> (void)y;
>>>> }
>>>> https://wandbox.org/permlink/JavMNfd6kGjF9f13
>>> And, for what it's worth, I can make that
>>> post([[]]}}}][][]]]]]]}}}()();;::;;)
>>> which is a parentheses-balanced token sequence and thus a valid
>>> invocation of that function-like macro,
>>> but otherwise contains stuff that's not fathomably valid in any
>>> hypothetical future version of C++, but the macro
>>> slurps it just fine.
>> _______________________________________________
>> Liaison mailing list
>> Liaison_at_[hidden]
>> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison
>> Link to this post: http://lists.isocpp.org/liaison/2023/10/1294.php

Received on 2023-10-08 11:02:11