I put together an alternative function contract and invariant mechanism in C using CBMC and custom macros that effectively allows me to perform formal methods in C using compositional verification. The reason why I chose C is because of its relative simplicity and relative ease of building tooling around it. C++ contracts provide some feature parity, and would let me take advantage of some of the features in C++ relative to C.
I hope that the contract proposal is workshopped and simplified so it can be proposed again for a future version. Its current form is unsuitable, but it deserves a second chance with a simpler implementation. Contracts would narrow the safety gap between C++ and languages such as Ada / SPARK.
[–] uecker 4 days ago
[–] Surac 4 days ago
[–] nanolith 3 days ago
https://www.bsdcan.org/2026/timetable/timetable-Model-Checki...
That link has the slides and some example code. There's also a live stream on YouTube.
Regarding features I miss from C++, I like the concept of generics. I don't like the implementation in C++. I also find C's _Generic facility to be limited, especially when building containers that perform hygienic type erasure. This feature isn't enough for me to go back to C++ on its own, but it is something I'm exploring in a new language I'm writing.
[–] uecker 2 days ago
[–] locknitpicker 4 days ago
Yes they would be.
Except that's not the contracts that they tried to force down C++'s throats.
The current contracts proposals features things like throwing exceptions in contract predicates, leaves out basic features such as function pointers, and not to mention that the contract specification alone covers around 5-10% of C++ specification and still glances over most details as being implementation defined.
As everyone is attacking Stroustrup as this master mind behind this opposition, perhaps people should devote some time to read one of the many papers pointing out the many flaws in the proposal. Stroustrup himself features as the coauthor of a few of them. Why is this not a technical discussion but a witch hunt?
[–] materielle 4 days ago
It’s weird that major features are designed from start to finish without even having so much as a demo.
It feels like there should be a back and forth process between committee proposal -> experimental impl in a major compiler -> community feedback, and so on.
It sounds like it’s basically the waterfall approach to language design? They write a glorious spec and chuck it out to the world, and hope that compilers can implement it and people actually find it useful. Example: modules.
[–] locknitpicker 4 days ago
Not necessarily. In broad terms, Boost is considered a staging ground for features proposed to C++. Compiler projects also keep up with the standards.
In this case the concept guys continuously dropped the ball on this requirement though. One of the papers pointing the many flaws in the proposal calls out this shortcoming, where contracts have neither a workable reference implementation nor an adequate specification. In fact, they handwaved a lot over details with vague calls to "implementation-defined".
[–] MFHava 3 days ago
I have no idea where you read that but it is a blatant lie - easily disproven by the way: N5046 which is pretty close to the C++26 DIS has 2668 pages. P2900R14 has a total of 114 pages, of which ~56 pages are dedicated to proposed wording.
Wording is presented as a diff to the working draft and contains extensive copies of the existing text that is either amended, modified or removed. (Aka: there are no 56 pages of wording).
[–] twhitmore 4 days ago
I think the ISO panel made the right call. The real world consider memory safety & execution integrity to already be critical issues (and C++ no longer to be viable), and they are correct. The WG has its priorities wrong.
[–] uecker 4 days ago
[–] saghm 4 days ago
[–] uecker 4 days ago
[–] saghm 4 days ago
> one can write fairly safe C code
In practice, pretty much every C/C++ codebase in existence has ended up having memory safety issues, even very widely used ones with a lot of scrutiny over the years.
> while Rust code in practice is also far from perfectly safe and also introduces new supply chain risks.
You're conflating "does not have one notoriously dangerous type of safety issue" and "does not have any safety issues", which is a disingenuous characterization of what I said. You were the one who introduced the comparison to memory safety in Rust and C++, and now you're moving the goalposts as an attempt to rebut my disagreement.
[–] uecker 3 days ago
[–] uecker 3 days ago
You don't have to agree, but this is how I see it.
[–] saghm 3 days ago
That is explicitly not what I'm claiming. You seem to think that I think "memory safety" is equivalent to "safety", which is what I've repeatedly told you is not what I'm saying. That's conflation. It's not clear why you'd expect me to read more details you give after repeatedly ignoring what I'm saying and putting words in my mouth that I'm not saying, so I have to assume at this point you're posturing for other readers rather than actually trying to communicate with me in any reasonable way.
[–] tkz1312 4 days ago
[–] nanolith 3 days ago
Contracts are annotations, much like types are. What makes contracts powerful is the tool that examines this annotation, as is the case with types. A type checker, such as an H-M type checker, can only perform limited checks. It's possible to use a dependent type checker with dependent types, but this is undecidable, and it requires a proof assistant and human guided tactics to resolve. In practice, this is expensive, and when automation such as LLMs are used, one currently gets tactic soup that is difficult to understand, which defeats the purpose.
A model checker, such as CBMC or ESBMC, can work with contracts to verify specification that would be difficult to verify without contracts. Model checkers can already verify memory safety and even the absence of memory leaks across an entire program. However, model checking grows exponentially expensive as we add more code to be verified. Contracts give us the ability to perform compositional verification, which allows us to verify codebases into the millions of lines of code or larger by breaking down this verification into many small model checks, stitching these together with contracts and invariants. Contracts and invariants complement type checking and significantly extend it. It's possible to use contracts and invariants to add these checks to an untyped language or a minimally typed language such as C. If my precondition includes the data invariant, "property_valid_widget(x)", then effectively, this also type checks x. This works even if I've completely erased the type and later recast it.
The "real world" doesn't currently have a solution for reducing general software safety issues -- which goes far beyond memory safety -- other than formal methods. Practical and efficient ways to formally verify software is within our reach, and is already being done with other languages. I do this today with C / CBMC using contracts and invariants. I get memory safety, specification safety, and a guarantee of no memory leaks. This can also be done with C++, Rust, Java, and other languages using similar techniques. While it is true that Rust and Java both have basic memory safety in place, they also both can harbor vulnerabilities that could be resolved with function contracts and model checking.
Contracts are more than useful; they give visibility of developer intent to model checkers and similar tools. This visibility makes software significantly safer than borrow checking or type checking can alone.
Can you tell us more how you use cbmc with macros? I am also exploring this.
I also wonder what feature from C++ you miss in C?