[clang] [Clang] [Contracts] Design Doc (PR #229978)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 15:11:40 PDT 2026
================
@@ -0,0 +1,943 @@
+# Introduction
+
+This is a high level design documentation for Contracts implementation in Clang.
+This summarized experiences from several implementors in seperate branches.
+
+This is also tend to be some developer policy/guide of contracts for how should clang
+developers continue working on this.
+
+## High Level Developing Style
+
+We plan to implement contracts in different small PRs. We don't want to implement
+contracts in a single PR. Smaller PR helps reviewers to understand the patch and give
+higher quality reviewers. Samller PR is also easier for testers to test and find the
+problems.
+
+The implementation contracts is marked as experimental before we announce it is
+implemented completely.
+
+### ABI
+
+We'd like to keep ABI unstable during the experimental process. We all understand
+ABI's importance. But getting consensus for ABI needs a long time. We prefer to
+move faster instead of waiting the consensus for ABI consensus.
+
+For GCC/libstdc++ interoperability, we need to identify the ABI revision
+which a toolchain targets. We shouldn't assume that one experimental GCC ABI
+will remain unchanged.
+
+### Driver flags
+
+Before we think the support of contracts are minimal usable, users are unable
+to get access to contracts unless users pass `-Xclang` explicitly.
+
+## AST structure
+
+### Contract Stmt
+
+```C++
+class Stmt {
+
+class ContractStmtBitfields {
+ unsigned Invalid : 1;
+};
+};
+
+class ContractStmtBase : public Stmt {
+ Expr *Predicate = nullptr;
+ SourceLocation KeywordLoc, LParenLoc, RParenLoc;
+ // llvm::ArrayRef<const Attr *> Attributes; // The design allows contracts to have attributes but none
+ // contracts attribute are presenting right now.
+};
+
+class ContractAssertStmt : public ContractStmtBase {};
+
+class ContractPreStmt : public ContractStmtBase {};
+
+class ContractPostStmt : public ContractStmtBase {
+ ResultNameDecl *ResultName = nullptr;
+};
+```
+
+Discussion:
+
+We though to use a simple struct to represent `pre` and `post` contracts. But we decided to put all of
+them into Stmt system. The major reason is that now the users can reuse components like
+`TraverseStmt(...)` more easily.
+
+For attributes, as we don't have any attributes for contracts yet, we can save this on first implemenation.
+
+We split them into 3 Stmt kinds so we can save the bits for ResultName for other contracts types.
+
+For `ResultNameDecl`, see following sections.
+
+### FunctionDecl
+
+```C++
+class FunctionContractSequence final
+ : private llvm::TrailingObjects<FunctionContractSequence, ContractStmtBase *> {
+ friend llvm::TrailingObjects<FunctionContractSequence, ContractStmtBase *>;
+ unsigned NumContracts;
+
+ explicit FunctionContractSequence(unsigned N) : NumContracts(N) {}
+
+public:
+ static FunctionContractSequence *Create(
+ ASTContext &Ctx, llvm::ArrayRef<ContractStmtBase *> Contracts);
+
+ llvm::ArrayRef<ContractStmtBase *> contracts() const {
+ return {getTrailingObjects<ContractStmtBase *>(), NumContracts};
+ }
+};
+
+class FunctionDecl : /*...*/ {
+ /*...*/
+private:
+ // The actual contracts of the function.
+ // Even if it is not explicitly written.
+ FunctionContractSequence *Contracts = nullptr;
+
+public:
+ bool hasContracts() const {
+ return Contracts;
+ }
+
+ void setContracts(FunctionContractSequence *ContractsSeq) {
----------------
EricWF wrote:
`FunctionDecl` is one of our most common AST nodes and almost none will have contracts. An unconditional pointer costs 8 bytes per function.
I'd put it in `DeclaratorDecl::ExtInfo` with the other rarely-set fields. Doing that on our branch dropped `sizeof(FunctionDecl)` from 176 to 168. `FD->getContracts()` works the same way.
https://github.com/llvm/llvm-project/pull/229978
More information about the cfe-commits
mailing list