Skip to content

Commit f3be01c

Browse files
Merge pull request #31 from iains/contracts-nonattr-add-eval-semantic-opt
Contracts nonattr add eval semantic opt
2 parents ced6d6c + cff51bf commit f3be01c

File tree

3 files changed

+70
-33
lines changed

3 files changed

+70
-33
lines changed

gcc/c-family/c.opt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,25 @@ fcontract-semantic=
18401840
C++ Joined RejectNegative
18411841
-fcontract-semantic=<level>:<semantic> Specify the concrete semantics for level.
18421842

1843+
Enum
1844+
Name(p2900_semantic) Type(int) UnknownError(unrecognized contract evaluation semantic %qs)
1845+
1846+
EnumValue
1847+
Enum(p2900_semantic) String(ignore) Value(1)
1848+
1849+
EnumValue
1850+
Enum(p2900_semantic) String(enforce) Value(3)
1851+
1852+
EnumValue
1853+
Enum(p2900_semantic) String(observe) Value(4)
1854+
1855+
EnumValue
1856+
Enum(p2900_semantic) String(quick_enforce) Value(5)
1857+
1858+
fcontract-evaluation-semantic=
1859+
C++ Joined RejectNegative Enum(p2900_semantic) Var(flag_contract_evaluation_semantic) Init (3)
1860+
-fcontract-evaluation-semantic=[ignore,observe,enforce,quick_enforce] Select the contract evaluation semantic (defaults to enforce).
1861+
18431862
fcontract-disable-optimized-checks
18441863
C++ Var(flag_contract_disable_optimized_checks) Init(0)
18451864
-fcontract-disable-optimized-checks Disable optimisation of contract checks.

gcc/cp/contracts.cc

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ along with GCC; see the file COPYING3. If not see
146146
#include "stor-layout.h"
147147
#include "intl.h"
148148
#include "cgraph.h"
149+
#include "opts.h"
149150

150151
const int max_custom_roles = 32;
151152
static contract_role contract_build_roles[max_custom_roles] = {
@@ -761,8 +762,14 @@ grok_contract (tree attribute, tree mode, tree result, cp_expr condition,
761762
else
762763
contract = build4_loc (loc, code, type, mode, NULL_TREE, NULL_TREE, result);
763764

764-
/* Determine the concrete semantic. */
765-
set_contract_semantic (contract, compute_concrete_semantic (contract));
765+
/* Determine the evaluation semantic:
766+
First, apply the c++2a rules
767+
FIXME: this is a convenience to avoid updating many tests. */
768+
contract_semantic semantic = compute_concrete_semantic (contract);
769+
if (flag_contracts_nonattr
770+
&& OPTION_SET_P (flag_contract_evaluation_semantic))
771+
semantic = static_cast<contract_semantic>(flag_contract_evaluation_semantic);
772+
set_contract_semantic (contract, semantic);
766773

767774
/* If the contract is deferred, don't do anything with the condition. */
768775
if (TREE_CODE (condition) == DEFERRED_PARSE)
@@ -1881,13 +1888,22 @@ get_contract_role_name (tree contract)
18811888
/* Build C++20 contract_violation layout compatible object. */
18821889

18831890
static tree
1884-
build_contract_violation_cpp20 (tree contract, contract_continuation cmode)
1891+
build_contract_violation_cpp20 (tree contract)
18851892
{
18861893
expanded_location loc = expand_location (EXPR_LOCATION (contract));
18871894
const char *function = fndecl_name (DECL_ORIGIN (current_function_decl));
18881895
const char *level = get_contract_level_name (contract);
18891896
const char *role = get_contract_role_name (contract);
18901897

1898+
/* Get the continuation mode. */
1899+
contract_continuation cmode;
1900+
switch (get_contract_semantic (contract))
1901+
{
1902+
case CCS_NEVER: cmode = NEVER_CONTINUE; break;
1903+
case CCS_MAYBE: cmode = MAYBE_CONTINUE; break;
1904+
default: gcc_unreachable ();
1905+
}
1906+
18911907
/* Must match the type layout in get_pseudo_contract_violation_type. */
18921908
tree ctor = build_constructor_va
18931909
(init_list_type_node, 7,
@@ -1923,8 +1939,7 @@ get_contract_assertion_kind(tree contract)
19231939
gcc_unreachable ();
19241940
}
19251941

1926-
/* Get constract_evaluation_semantic of the specified contract. Used when building
1927-
P2900R7 contract_violation object. */
1942+
/* Get contract_evaluation_semantic of the specified contract. */
19281943
static int
19291944
get_evaluation_semantic(tree contract)
19301945
{
@@ -1937,16 +1952,17 @@ get_evaluation_semantic(tree contract)
19371952
return CES_OBSERVE;
19381953
}
19391954

1955+
/* Used when building P2900R10 contract_violation object. Note that we do not
1956+
build such objects unless we are going to use them - so that we should not
1957+
get asked for 'ignore' or 'quick'. */
19401958
switch (semantic)
19411959
{
19421960
default:
19431961
gcc_unreachable ();
1944-
case CCS_MAYBE:
1962+
case CCS_OBSERVE:
19451963
return CES_OBSERVE;
1946-
break;
1947-
case CCS_NEVER:
1964+
case CCS_ENFORCE:
19481965
return CES_ENFORCE;
1949-
break;
19501966
}
19511967
}
19521968

@@ -1979,12 +1995,12 @@ build_contract_violation_P2900 (tree contract)
19791995
/* Return a VAR_DECL to pass to handle_contract_violation. */
19801996

19811997
static tree
1982-
build_contract_violation (tree contract, contract_continuation cmode)
1998+
build_contract_violation (tree contract)
19831999
{
19842000
if (flag_contracts_nonattr)
19852001
return build_contract_violation_P2900(contract);
19862002

1987-
return build_contract_violation_cpp20(contract, cmode);
2003+
return build_contract_violation_cpp20(contract);
19882004
}
19892005

19902006
/* Return handle_contract_violation(), declaring it if needed. */
@@ -2054,10 +2070,9 @@ declare_handle_contract_violation ()
20542070
/* Build the call to handle_contract_violation for CONTRACT. */
20552071

20562072
static void
2057-
build_contract_handler_call (tree contract,
2058-
contract_continuation cmode)
2073+
build_contract_handler_call (tree contract)
20592074
{
2060-
tree violation = build_contract_violation (contract, cmode);
2075+
tree violation = build_contract_violation (contract);
20612076
tree violation_fn = declare_handle_contract_violation ();
20622077
tree call = build_call_n (violation_fn, 1, build_address (violation));
20632078
finish_expr_stmt (call);
@@ -2094,17 +2109,17 @@ build_contract_check (tree contract)
20942109
tf_warning_or_error);
20952110
finish_if_stmt_cond (cond, if_stmt);
20962111

2097-
/* Get the continuation mode. */
2098-
contract_continuation cmode;
2099-
switch (semantic)
2112+
/* Using the P2900 names here c++24 ENFORCE=NEVER, OBSERVE=MAYBE. */
2113+
if (semantic == CCS_ENFORCE || semantic == CCS_OBSERVE)
2114+
build_contract_handler_call (contract);
2115+
if (semantic == CCS_QUICK)
21002116
{
2101-
case CCS_NEVER: cmode = NEVER_CONTINUE; break;
2102-
case CCS_MAYBE: cmode = MAYBE_CONTINUE; break;
2103-
default: gcc_unreachable ();
2117+
tree fn = builtin_decl_explicit (BUILT_IN_ABORT);
2118+
releasing_vec vec;
2119+
finish_expr_stmt (finish_call_expr (fn, &vec, false, false,
2120+
tf_warning_or_error));
21042121
}
2105-
2106-
build_contract_handler_call (contract, cmode);
2107-
if (cmode == NEVER_CONTINUE)
2122+
else if (semantic == CCS_ENFORCE)
21082123
finish_expr_stmt (build_call_a (terminate_fn, 0, nullptr));
21092124

21102125
finish_then_clause (if_stmt);

gcc/cp/contracts.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ enum contract_level
3636

3737
enum contract_semantic
3838
{
39-
CCS_INVALID,
40-
CCS_IGNORE,
41-
CCS_ASSUME,
42-
CCS_NEVER,
43-
CCS_MAYBE
39+
CCS_INVALID = 0,
40+
CCS_IGNORE = 1,
41+
CCS_ASSUME = 2,
42+
CCS_NEVER = 3,
43+
CCS_ENFORCE = CCS_NEVER,
44+
CCS_MAYBE = 4,
45+
CCS_OBSERVE = CCS_MAYBE,
46+
CCS_QUICK = 5
4447
};
4548

46-
4749
/* True if the contract is unchecked. */
4850

4951
inline bool
@@ -86,14 +88,15 @@ enum constract_assertion_kind {
8688
CAK_ASSERT = 3
8789
};
8890

89-
enum constract_evaluation_semantic {
91+
enum contract_evaluation_semantic {
9092
CES_INVALID = 0,
91-
CES_ENFORCE = 1 ,
92-
CES_OBSERVE = 2
93+
CES_ENFORCE = 1,
94+
CES_OBSERVE = 2,
95+
CES_QUICK = 3
9396
};
9497

9598
enum constract_detection_mode {
96-
CDM_PREDICATE_FALSE = 1 ,
99+
CDM_PREDICATE_FALSE = 1,
97100
CDM_EVAL_EXCEPTION = 2
98101
};
99102

0 commit comments

Comments
 (0)