C++ Logo

liaison

Advanced search

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

From: Martin Uecker <ma.uecker_at_[hidden]>
Date: Fri, 06 Oct 2023 17:04:03 +0200
Am Freitag, dem 06.10.2023 um 17:45 +0300 schrieb Timur Doumler:
> Hi Martin,
>
> That's interesting, thanks. It is important to note that in C++, neither of the candidate syntaxes is backwards-compatible in the way you describe. The attribute-like P2935 syntax is:
>
> [[ pre : expression ]]
> [[ post optional-name-for-return-value : expression ]]
> [[ assert : expression ]]
>
> That does not follow the standard attribute grammar, which in C++ is:
>
> [[ attribute-token ]]
> [[ attribute-token ( parameter-clause ) ]]
>
> because the colon is not allowed in standard attribute grammar. So in C++, even if we choose P2935 (the attribute-like syntax), a pre-Contracts compiler is still *required* to diagnose a
> syntax error if it sees a contract. That's why we call P2935 the attribute-*like* syntax, it's *like* an attribute because it has [[ ... ]] , but isn't actually an attribute because it
> doesn't follow attribute grammar.
>
> So for C++, the option to have a backwards-compatible syntax isn't even on the table anymore (we discussed this option in SG21 – it would require us to put parentheses around the expression
> and would forbid having anything between the pre/post/assert and that parenthesised expression – and that's just too limiting for this feature) so it's simply not a consideration for us.
>
> I understand that in C, the situation is different because you're allowed to token-ignore anything between [[ ... ]] even if it features a colon.

I am not entirely sure. In practice compilers also fail to process this.

And, yes, exactly for this reason, I actually believe that attributes would have been
the best choice for C.

But I think P2935 would still be ok because only a minor changes to compilers
would be required to make this work. If it is clear that contracts with such
syntax are likely to come, people could make these changes now to reduce
issues later.


Martin


>
> Cheers,
> Timur
>
> > On 6 Oct 2023, at 17:30, Martin Uecker <ma.uecker_at_[hidden]> wrote:
> >
> > Am Freitag, dem 06.10.2023 um 09:40 +0300 schrieb Ville Voutilainen:
> > > On Fri, 6 Oct 2023 at 08:31, Martin Uecker <ma.uecker_at_[hidden]> wrote:
> > > > To be honest, I think it is a mistake also for C++. I believe
> > > > that even for C++ people will end up trying to introduce this into
> > > > existing code and then are forced to make it ignorable by wrapping it
> > > > into #ifdef or macros. The end result would neither be nice
> > > > nor ignorable.
> > >
> > > Sure, but that's no different from conditionally adopting any other
> > > new language facility that
> > > the older implementations don't recognize. Which for C++ is almost
> > > every new language facility.
> > > We have standardized feature-detection macros, even, to help with
> > > preprocessor-based conditional
> > > migration.
> >
> > The difference is that this seems to be a feature which could be
> > usefully be added to an existing codebase incrementally. That
> > does not make too much sense for every new feature.
> >
> > >
> > > > > It wouldn't cause me loss of sleep if C compilers were allowed to
> > > > > completely ignore a contract annotation.
> > > > > Fixing syntax errors when using a compiler that doesn't ignore them is
> > > > > compatible with compilers that would
> > > > > ignore the annotations.
> > > >
> > > > Right. And especially in a context where headers are shared, the
> > > > scenario that for some transition time (probably decades) the code
> > > > needs be processed also by compilers not supporting contracts seems
> > > > very likely.
> > > >
> > > > For C I think it would be important to have a syntax that is ignorable.
> > >
> > > Just to make sure I understand.. in effect, to make the feature
> > > optional? So as to not hoist
> > > its burden on implementations that don't want it?
> >
> > No, I would make it mandatory for new C versions. But a useful goal for
> > C could be to make the code acceptable to older compilers that do
> > not have full support for it during a transition time without needing
> > preprocessor wrappers.
> >
> >
> > >
> > > > A syntax as proposed here (it seems, correct me if I am wrong) such
> > > > as:
> > > >
> > > > void f(int x)
> > > > pre <audit> (x > 0);
> > > >
> > > > would be a pretty bad choice for C.
> > >
> > > The <audit> part is at this point hypothetical. I'm curious why you
> > > think that's a bad choice.
> >
> > One problem is introducing a three letter keyword. Yes, _Pre would
> > be an option, but if we want to transition to "pre" this would still
> > be a problem later.
> >
> > The next problem is that this syntax can not be hidden behind a macro.
> > This would work for:
> >
> > _Pre (<audit>, (x > 0))
> >
> > Also some attribute-like mechanism would work
> >
> > [[ __pre__ (x > 0) ]]
> >
> > where the parsing context could allow a compiler to treat the
> > keywords specially.
> >
> > So there is no fundamental problem with this syntax. It is just that
> > it is not really designed for a feature that can be phased in gradually
> > into existing code. But this is exactly how contracts would be most
> > useful in C: By enhancing existing code step by step.
> >
> > > If I understand things correctly, it's novel for C to have function
> > > parameters be in scope
> > > after leaving a function declarator and before a function definition
> > > begins. In C++, that hasn't
> > > been novel for ages, with trailing return types,
> > > noexcept-specifications, and constraints all
> > > using function parameters.
> >
> > This is also true, but I think this is not a major issue.
> >
> > Martin
>


Received on 2023-10-06 15:04:07