Skip to content

Commit d1d1b3a

Browse files
Merge pull request gcc-mirror#55 from NinaRanns/noexcept_observe
noexcept_observe
2 parents b65afb1 + 34bd732 commit d1d1b3a

File tree

7 files changed

+122
-11
lines changed

7 files changed

+122
-11
lines changed

gcc/c-family/c.opt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1929,9 +1929,12 @@ Enum(p2900_semantic) String(quick_enforce) Value(5)
19291929
EnumValue
19301930
Enum(p2900_semantic) String(noexcept_enforce) Value(6)
19311931

1932+
EnumValue
1933+
Enum(p2900_semantic) String(noexcept_observe) Value(7)
1934+
19321935
fcontract-evaluation-semantic=
19331936
C++ Joined RejectNegative Enum(p2900_semantic) Var(flag_contract_evaluation_semantic) Init (3)
1934-
-fcontract-evaluation-semantic=[ignore|observe|enforce|quick_enforce|noexcept_enforce] Select the contract evaluation semantic (defaults to enforce).
1937+
-fcontract-evaluation-semantic=[ignore|observe|enforce|quick_enforce|noexcept_enforce|noexcept_observe] Select the contract evaluation semantic (defaults to enforce).
19351938

19361939
fcontract-checks-outlined
19371940
C++ Var(flag_contract_checks_outlined) Init(1)

gcc/cp/contracts.cc

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,6 +2171,8 @@ get_evaluation_semantic(tree contract)
21712171
return CES_QUICK;
21722172
case CCS_NOEXCEPT_ENFORCE:
21732173
return CES_NOEXCEPT_ENFORCE;
2174+
case CCS_NOEXCEPT_OBSERVE:
2175+
return CES_NOEXCEPT_OBSERVE;
21742176
}
21752177
}
21762178

@@ -2375,12 +2377,14 @@ build_contract_check (tree contract)
23752377
finish_if_stmt_cond (cond, if_stmt);
23762378
/* Using the P2900 names here c++2a ENFORCE=NEVER, OBSERVE=MAYBE. */
23772379
if (semantic == CCS_ENFORCE || semantic == CCS_OBSERVE
2378-
|| semantic == CCS_NOEXCEPT_ENFORCE)
2380+
|| semantic == CCS_NOEXCEPT_ENFORCE
2381+
|| semantic == CCS_NOEXCEPT_OBSERVE)
23792382
{
23802383
tree violation = build_contract_violation (contract,
23812384
/*is_const*/true);
2382-
build_contract_handler_call (violation,
2383-
semantic == CCS_NOEXCEPT_ENFORCE);
2385+
bool noexcept_wrap = (semantic == CCS_NOEXCEPT_ENFORCE)
2386+
|| (semantic == CCS_NOEXCEPT_OBSERVE);
2387+
build_contract_handler_call (violation, noexcept_wrap);
23842388
}
23852389

23862390
if (semantic == CCS_QUICK)
@@ -2417,7 +2421,8 @@ build_contract_check (tree contract)
24172421
violation object or handler. */
24182422
tree excp_ = NULL_TREE;
24192423
if (semantic == CCS_ENFORCE || semantic == CCS_OBSERVE
2420-
|| semantic ==CCS_NOEXCEPT_ENFORCE)
2424+
|| semantic ==CCS_NOEXCEPT_ENFORCE
2425+
|| semantic == CCS_NOEXCEPT_OBSERVE)
24212426
{
24222427
excp_ = build_decl (loc, VAR_DECL, NULL, boolean_type_node);
24232428
/* compiler-generated. */
@@ -2433,7 +2438,8 @@ build_contract_check (tree contract)
24332438

24342439
tree violation = NULL_TREE;
24352440
if (semantic == CCS_ENFORCE || semantic == CCS_OBSERVE
2436-
|| semantic == CCS_NOEXCEPT_ENFORCE)
2441+
|| semantic == CCS_NOEXCEPT_ENFORCE
2442+
|| semantic == CCS_NOEXCEPT_OBSERVE)
24372443
violation = build_contract_violation (contract, /*is_const*/false);
24382444

24392445
/* Wrap the contract check in a try-catch. */
@@ -2446,7 +2452,8 @@ build_contract_check (tree contract)
24462452
tree handler = begin_handler ();
24472453
finish_handler_parms (NULL_TREE, handler); /* catch (...) */
24482454
if (semantic == CCS_ENFORCE || semantic == CCS_OBSERVE
2449-
|| semantic == CCS_NOEXCEPT_ENFORCE)
2455+
|| semantic == CCS_NOEXCEPT_ENFORCE
2456+
|| semantic == CCS_NOEXCEPT_OBSERVE)
24502457
{
24512458
/* Update the violation object type. */
24522459
tree v_type = get_pseudo_contract_violation_type ();
@@ -2457,7 +2464,9 @@ build_contract_check (tree contract)
24572464
r = cp_build_init_expr (r, build_int_cst (integer_type_node,
24582465
CDM_EVAL_EXCEPTION));
24592466
finish_expr_stmt (r);
2460-
build_contract_handler_call (violation, semantic == CCS_NOEXCEPT_ENFORCE);
2467+
bool noexcept_wrap = (semantic == CCS_NOEXCEPT_ENFORCE)
2468+
|| (semantic == CCS_NOEXCEPT_OBSERVE);
2469+
build_contract_handler_call (violation, noexcept_wrap);
24612470
/* Note we had an exception. */
24622471
finish_expr_stmt (cp_build_init_expr (excp_, boolean_true_node));
24632472
}
@@ -2476,7 +2485,8 @@ build_contract_check (tree contract)
24762485
finish_if_stmt_cond (cond, if_not_cond);
24772486

24782487
if (semantic == CCS_ENFORCE || semantic == CCS_OBSERVE
2479-
|| semantic == CCS_NOEXCEPT_ENFORCE)
2488+
|| semantic == CCS_NOEXCEPT_ENFORCE
2489+
|| semantic == CCS_NOEXCEPT_OBSERVE)
24802490
{
24812491
tree if_not_excp = begin_if_stmt ();
24822492
cond = build_x_unary_op (loc, TRUTH_NOT_EXPR, excp_, NULL_TREE,

gcc/cp/contracts.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ enum contract_level
3838
CCS_NEVER -> enforce
3939
CCS_QUICK -> quick_enforce
4040
CCS_NOEXCEPT_ENFORCE -> noexcept_enforce
41+
CCS_NOEXCEPT_OBSERVE -> noexcept_observe
4142
*/
4243

4344
enum contract_semantic
@@ -50,7 +51,8 @@ enum contract_semantic
5051
CCS_MAYBE = 4,
5152
CCS_OBSERVE = CCS_MAYBE,
5253
CCS_QUICK = 5,
53-
CCS_NOEXCEPT_ENFORCE
54+
CCS_NOEXCEPT_ENFORCE,
55+
CCS_NOEXCEPT_OBSERVE
5456
};
5557

5658
/* True if the contract is unchecked. */
@@ -102,7 +104,8 @@ enum contract_evaluation_semantic {
102104
CES_OBSERVE = 2,
103105
CES_ENFORCE = 3,
104106
CES_QUICK = 4,
105-
CES_NOEXCEPT_ENFORCE =5
107+
CES_NOEXCEPT_ENFORCE = 5,
108+
CES_NOEXCEPT_OBSERVE = 6
106109
};
107110

108111
enum constract_detection_mode {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test that there is no crash with default contract violation handler and noexcept_observe
2+
// { dg-do compile }
3+
// { dg-options "-std=c++2a -fcontracts -fcontracts-nonattr -fcontract-evaluation-semantic=noexcept_observe " }
4+
5+
6+
void f(int i) pre(i > 0){}
7+
8+
int main()
9+
{
10+
f(0);
11+
}
12+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//Test that a throwing violation handler causes termination with noexcept-observe
2+
// { dg-do run }
3+
// { dg-options "-std=c++2a -fcontracts -fcontracts-nonattr -fcontract-evaluation-semantic=noexcept_observe " }
4+
#include <experimental/contract>
5+
#include <exception>
6+
#include <cstdlib>
7+
8+
void my_term()
9+
{
10+
try { throw; }
11+
catch(int) { std::exit(0); }
12+
}
13+
void handle_contract_violation(const std::experimental::contract_violation& violation)
14+
{
15+
throw 1;
16+
}
17+
18+
struct X
19+
{
20+
void f(const int x) pre(x>1) post(x>3) {
21+
int i = 1;
22+
}
23+
};
24+
25+
int main()
26+
{
27+
std::set_terminate (my_term);
28+
try
29+
{
30+
X x;
31+
x.f(-42);
32+
} catch (...) {
33+
}
34+
// We should not get here
35+
return 1;
36+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//Test that a throwing violation handler causes termination with noexcept-observe
2+
// { dg-do run }
3+
// { dg-options "-std=c++2a -fcontracts -fcontracts-nonattr -fcontract-evaluation-semantic=noexcept_observe " }
4+
#include <experimental/contract>
5+
#include <exception>
6+
#include <cstdlib>
7+
8+
void my_term()
9+
{
10+
try { throw; }
11+
catch(int) { std::exit(0); }
12+
}
13+
14+
void handle_contract_violation(const std::experimental::contract_violation& violation)
15+
{
16+
throw 1;
17+
}
18+
19+
void f(int x) pre(x >= 0)
20+
{
21+
}
22+
23+
int main()
24+
{
25+
std::set_terminate (my_term);
26+
try
27+
{
28+
f(-42);
29+
} catch (...) {}
30+
// We should not get here
31+
return 1;
32+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//Test that noexcept-observe with a non throwing violation handler has
2+
// observe semantics
3+
// { dg-do run }
4+
// { dg-options "-std=c++2a -fcontracts -fcontracts-nonattr -fcontract-evaluation-semantic=noexcept_observe " }
5+
6+
int f(const int a, const int b) pre (a > 2) post(r : r > 2){ return 1;};
7+
8+
int main(int, char**)
9+
{
10+
f(1,1);
11+
return 0;
12+
}
13+
14+
// { dg-output "contract violation in function f at .*: a > 2.*(\n|\r\n|\r)" }
15+
// { dg-output "contract violation in function f at .*: r > 2.*(\n|\r\n|\r)" }

0 commit comments

Comments
 (0)