Repository navigation
B2-2: class templates verified in each specialization - #81
Merged
Merged
Conversation
…s own object as nothing, and hold class invariants at reference and pointer parameters.
… for class invariants.
…eturns to its own object.
…ns to its own object, as an argument is.
…urns to its own object.
…assed by reference or pointer.
…s at reference and pointer parameters.
…ependence of their type or operands.
…nd the checks it shares with the parser.
…y in Sema, for the parser and for instantiation.
…tracts with their loops, and trigger marks.
…and keep ghost variables ghost.
…e, named with its arguments.
…a template's type compared with a constant.
…d for those of every redeclaration.
…nd type invariants.
…ch instantiation can rebuild.
…lization, and report members none instantiates.
…are checked where instantiated.
…riant field rewriter's entry point.
… that Sema's own this->field made dead.
…mbers verified once.
This was referenced Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The contracts of a class template's members and its type invariants were ignored with a warning (
-Wcontract-unsupported), so no member of a class template was verified. Now a class template is verified in each specialization the translation unit instantiates, as a function template is (#80): a member's contract is instantiated with the member, and the class's invariants with the class.On the base (#80):
(each error with its source line and caret).
Stacked on #80 (B2-2, the second part of plan item B2: templates verified per instantiation).
Design
InstantiateFunctionContract, lazily: where the member is used or defined, which C++ does only for the members a specialization uses (or every member, for an explicit instantiation definition). So a member no specialization uses is not verified, and is reported:warning: Box<T>::reset: member of a class template is not verified: this translation unit instantiates it in none of the class's specializations.InstantiateClassImplinstantiates them once the specialization is complete, eagerly, as a memberstatic_assertis, with the specialization'sthis(CXXThisScopeRAII), into itsTypeContractInfo, in the potentially-evaluated context of the class's instantiation, so a spec the invariant applies is instantiated too. An invariant is parsed with its class'sthisin scope, so Sema writes a field it names bare asthis->field, which the instantiation rebuilds with the specialization'sthis. That madeActOnTypeInvariantExpr's rewriter of bare fields dead (an instrumented build found it never runs, on any test, doc page, or the forms tried:sizeof,decltype, quantifiers, unions, anonymous members, static members), and it is removed; it wrotethis.fieldwith athisof record type, which an instantiation could not have rebuilt.cv::type_invariant(cv::forall(k, 0, 4, cells[k] >= 0)), declared its binder in the class, which made it a member: an assertions build stopped at the first lookup ofk(Access specifier is AS_none inside a record decl), in an ordinary class too. A binder now belongs to the context around the class (Sema::getContractBinderContext), in the parser and in instantiation.collectFunctionCandidatesvisits, for each class template, the members of each specialization the translation unit instantiates (from its canonical declaration; an explicit instantiation's specialization in a declaration context is collected from its template only) and the pattern's members, for the warning, whichisInstantiateddecides from the instantiated members of the class's specializations, member function templates included. A member is named with its class's arguments (Box<int>::twice,Acc<int>::add<short>), and its diagnostics notein instantiation of member function 'Box<short>::twice' requested here.-Wcontract-unsupportedhas nothing left to report: the warning is removed, and its group stays, so a build that names it still builds.Tests
suite/class_templates.cpp(Z3, with a check that no proof is vacuous):Boxwith a constructor, members, and an invariant in two specializations,Box<signed char>::twicefailing with its note, aBox<int>by reference with its invariant, an out-of-line member definition with a contract under an explicit instantiation (Pair<long>::larger), a member function template (Acc<int>::add<int>,add<short>), a spec template applied in the invariant (Digit<int>), quantified invariants in a class and a class template (Quad,Cells<int>), and the warnings for a member no specialization uses and a class template nothing instantiates.template_contract_errors.cpp: an invariant that does not fit the arguments is an error where the class is instantiated, a member's contract where the member is used, each with Clang's note.template_contracts.cpp: the class template's contracts compile without a warning.The three fail on the base:
class_templates.cppgets the warnings and no verdicts for the class templates, and stops an assertions build atQuad's invariant (Access specifier is AS_none inside a record decl);template_contract_errors.cppgets none of the class template errors it expects;template_contracts.cppgets the warnings it no longer expects.Mutants, each built on an assertions build and run on
class_templates.cpp,template_contract_errors.cpp,template_contracts.cpp,function_templates.cpp,class_invariants.cpp, andtype_invariant_lazy.cpp: 12 of 12 killed; a thirteenth, writing a bare field asthis.fieldagain, found the rewriter dead, which is removed.class_templates,template_contract_errorsclass_templates,template_contract_errorsclass_templates,template_contract_errorsthisclass_templates,template_contract_errors,template_contractsbooltemplate_contract_errors(Holder<Pair>)class_templatesclass_templates(Pair<long>::largeronce)class_templatesclass_templatesclass_templates(Box<T>::reset)class_templates(the note)class_templates(Quad: the assertion)Docs
Box), the rules.Checked
docs_examples.testanddocs_coverage.testpass; the site builds with warnings as errors.