-
Notifications
You must be signed in to change notification settings - Fork 277
CONTRACTS: adding requires and ensures clauses for function pointers #6821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CONTRACTS: adding requires and ensures clauses for function pointers #6821
Conversation
10ab523
to
ef03bb1
Compare
Codecov Report
@@ Coverage Diff @@
## develop #6821 +/- ##
=========================================
Coverage 77.03% 77.03%
=========================================
Files 1594 1594
Lines 185016 185174 +158
=========================================
+ Hits 142520 142647 +127
- Misses 42496 42527 +31
Continue to review full report at Codecov.
|
src/ansi-c/c_expr.h
Outdated
return ret; | ||
} | ||
|
||
/// \copydoc to_function_pointer_obeys_contract_expr_expr(const exprt &expr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate _expr
in copydoc
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/ansi-c/c_typecheck_code.cpp
Outdated
error().source_location = expr.source_location(); | ||
error() << "expected ID_function_pointer_obeys_contract expression in " | ||
"requires_contract/ensures_contract clause, found " | ||
<< id2string(expr.id()) << eom; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick: id2string
is not needed here, operator<<
will take care.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/ansi-c/c_typecheck_code.cpp
Outdated
{ | ||
error().source_location = function_pointer.source_location(); | ||
error() << "first parameter of the clause must have no ternary operator" | ||
<< eom; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing throw 0;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/ansi-c/parser.y
Outdated
{ | ||
$$=$1; | ||
set($$, ID_C_spec_ensures_contract); | ||
exprt tmp = exprt(ID_function_pointer_obeys_contract); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exprt tmp(ID_function_pointer_obeys_contract);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/ansi-c/parser.y
Outdated
{ | ||
$$=$1; | ||
set($$, ID_C_spec_requires_contract); | ||
exprt tmp = exprt(ID_function_pointer_obeys_contract); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exprt tmp(ID_function_pointer_obeys_contract);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
for(auto &expr : requires_contract) | ||
{ | ||
auto &obeys_expr = to_function_pointer_obeys_contract_expr(expr); | ||
replace_symbolt replace(common_replace); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need to take a copy here, just use common_replace
directly two lines later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
for(auto &expr : ensures_contract) | ||
{ | ||
auto &obeys_expr = to_function_pointer_obeys_contract_expr(expr); | ||
replace_symbolt replace(common_replace); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, no need for a copy.
for(auto &expr : requires_contract) | ||
{ | ||
auto &obeys_expr = to_function_pointer_obeys_contract_expr(expr); | ||
replace_symbolt replace(common_replace); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a copy.
for(auto &expr : ensures_contract) | ||
{ | ||
auto &obeys_expr = to_function_pointer_obeys_contract_expr(expr); | ||
replace_symbolt replace(common_replace); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a copy. (And now I'm starting to wonder why a very similar (the same?) code exists multiple times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(And now I'm starting to wonder why a very similar (the same?) code exists multiple times
This is mostly because I'm lazy :). The code is now factored into two separate methods.
Thank you @tautschnig I took into account all your comments. |
ef03bb1
to
136855e
Compare
for(auto &expr : requires_contract) | ||
assert_function_pointer_obeys_contract( | ||
to_function_pointer_obeys_contract_expr(expr), | ||
ID_precondition, | ||
common_replace, | ||
mode, | ||
new_program); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Braces around the body, please.
for(auto &expr : ensures_contract) | ||
assume_function_pointer_obeys_contract( | ||
to_function_pointer_obeys_contract_expr(expr), | ||
ID_postcondition, | ||
common_replace, | ||
new_program); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Braces around the body, please.
for(auto &expr : requires_contract) | ||
assume_function_pointer_obeys_contract( | ||
to_function_pointer_obeys_contract_expr(expr), | ||
ID_precondition, | ||
common_replace, | ||
check); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Braces around body, please.
for(auto &expr : ensures_contract) | ||
assert_function_pointer_obeys_contract( | ||
to_function_pointer_obeys_contract_expr(expr), | ||
ID_postcondition, | ||
common_replace, | ||
function_symbol.mode, | ||
check); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Braces around body, please.
136855e
to
ebe7c4d
Compare
Syntax extensions and typechecking, and simple contract enforcement and replacement logic.
6d37049
to
63cd722
Compare
|
||
#include <memory> | ||
|
||
#include <util/symbol_table.h> | ||
#include <util/invariant.h> | ||
#include <util/namespace.h> | ||
#include <util/std_expr.h> | ||
#include <util/symbol_table.h> | ||
|
||
#include "language.h" | ||
#include "mode.h" | ||
|
||
#include <memory> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to reorder the includes section to match the current clang-format rules, but it makes me feel like the priority is listed in inverse order in the rules (usually we want standard lib includes first then local headers and then other deps).
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '_class.h(>|")$'
Priority: 0
- Regex: '<util/'
Priority: 1
- Regex: '<goto-programs/'
Priority: 2
- Regex: '<.+/.+>'
Priority: 3
- Regex: '^"[^/]+"$'
Priority: 4
- Regex: '<[^/]+>'
Priority: 5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's in that order on purpose (I can say so as this piece of code is my fault). My rationale for placing STL headers last is that it will help surface missing includes that would suddenly bite when a header file is newly used in another place. But maybe that's a bad idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no objections to this new ordering and it's actually good to know if any other include file is inadvertently missing an stl include.
I was just surprised by global reordering effect of adding a single new line in the existing block of #include <utils/*.h>
. Let's keep using the new ordering policy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it does result in some short-term churn, but should lead to eventual consistency. Previously, there were unwritten rules for how includes are to be ordered, but no automated enforcement.
Adding syntax extensions and typechecking for two new contract clauses:
These clauses allow to specify pre and post conditions about function pointers. The first parameter must be a function-pointer-typed lvalue expression, without side effects of disjunctions. The second parameter must be a contract symbol (ie a function symbol that carries a contract). A simple enforcement/replacement : assign said contract to the pointer for assumptions (replace ensures, enforce requires) or check that the pointer is equal to said contract symbol (replace requires, enforce ensures).
Used in combination with
--restrict-function-pointer
and--replace-call-with-contract
they allow to model and use proof assumptions about function pointers.see code example here and command line switches here