Skip to content

Commit e60c745

Browse files
Merge pull request gcc-mirror#106 from NinaRanns/P3290
P3290 - no cassert bit yet
2 parents 0efe9c4 + fb5762d commit e60c745

14 files changed

+525
-18
lines changed

gcc/cp/contracts.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ enum constract_assertion_kind {
103103
CAK_INVALID = 0 ,
104104
CAK_PRE = 1 ,
105105
CAK_POST = 2 ,
106-
CAK_ASSERT = 3
106+
CAK_ASSERT = 3,
107+
CAK_MANUAL = 4,
108+
CAK_CASSERT = 5,
107109
};
108110

109111
/* Per P2900R11. */
@@ -118,6 +120,7 @@ enum contract_evaluation_semantic {
118120
};
119121

120122
enum constract_detection_mode {
123+
CDM_UNSPECIFIED = 0,
121124
CDM_PREDICATE_FALSE = 1,
122125
CDM_EVAL_EXCEPTION = 2
123126
};

libstdc++-v3/include/std/contracts

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
4242

4343
namespace contracts
4444
{
45+
46+
// From P3290
47+
struct __location_info{
48+
std::source_location _M_source_location;
49+
explicit __location_info(std::source_location __location)
50+
: _M_source_location(__location){}
51+
};
52+
53+
[[noreturn]] void handle_enforced_contract_violation(
54+
const char*,
55+
const std::source_location &__location = std::source_location::current());
56+
57+
[[noreturn]] void handle_enforced_contract_violation(
58+
const std::nothrow_t&,
59+
const char*,
60+
const std::source_location &__location = std::source_location::current()) noexcept;
61+
62+
void handle_observed_contract_violation(
63+
const char*,
64+
const std::source_location &__location = std::source_location::current());
65+
66+
void handle_observed_contract_violation(
67+
const std::nothrow_t&,
68+
const char*,
69+
const std::source_location &__location = std::source_location::current()) noexcept;
70+
71+
[[noreturn]] void handle_quick_enforced_contract_violation(
72+
const char*,
73+
const std::source_location &__location = std::source_location::current()) noexcept;
74+
75+
4576
// From P2900R11
4677
enum class assertion_kind {
4778
pre = 1,
4879
post = 2,
49-
assert = 3
80+
assert = 3,
81+
// From P3290
82+
manual = 4,
83+
cassert = 5
5084
/* to be extended with implementation−defined values and by future extensions */
51-
/* Implementation−defined values should have a minimum value of 1000. */
52-
};
85+
/* Implementation−defined values should have a minimum value of 1000. */
86+
};
5387

5488
enum class evaluation_semantic {
5589
ignore = 1,
@@ -64,6 +98,8 @@ namespace contracts
6498
};
6599

66100
enum class detection_mode {
101+
// From P3290
102+
unspecified = 0,
67103
predicate_false = 1,
68104
evaluation_exception = 2
69105
/* to be extended with implementation−defined values and by future extensions
@@ -73,23 +109,57 @@ namespace contracts
73109
using __vendor_ext = void;
74110

75111
class contract_violation {
76-
int version;
112+
int _M_version;
77113
__vendor_ext* _M_ext;
78114
const char* _M_comment;
79115
detection_mode _M_detection_mode;
80116
assertion_kind _M_assertion_kind;
81117
std::source_location _M_source_location;
82118
evaluation_semantic _M_evaluation_semantic;
119+
120+
contract_violation(evaluation_semantic __semantic,
121+
const std::source_location &__location,
122+
const char* __comment):
123+
_M_version(0),
124+
_M_ext(nullptr),
125+
_M_comment(__comment),
126+
_M_detection_mode(detection_mode::unspecified),
127+
_M_assertion_kind(assertion_kind::manual),
128+
_M_source_location(__location),
129+
_M_evaluation_semantic(__semantic)
130+
{
131+
132+
}
133+
134+
friend void handle_enforced_contract_violation(
135+
const char*,
136+
const std::source_location &);
137+
138+
friend void handle_enforced_contract_violation(
139+
const std::nothrow_t&,
140+
const char*,
141+
const std::source_location &) noexcept;
142+
143+
friend void handle_observed_contract_violation(
144+
const char*,
145+
const std::source_location &);
146+
147+
friend void handle_observed_contract_violation(
148+
const std::nothrow_t&,
149+
const char*,
150+
const std::source_location &) noexcept;
151+
152+
friend void handle_quick_enforced_contract_violation(
153+
const char*,
154+
const std::source_location &) noexcept;
155+
83156
public:
84157
// cannot be copied or moved
85158
contract_violation(const contract_violation&) = delete;
86159

87160
// cannot be assigned to
88161
contract_violation& operator=(const contract_violation&) = delete;
89162

90-
/* see below */
91-
~ contract_violation();
92-
93163
const char* comment() const noexcept { return _M_comment; }
94164
detection_mode mode() const noexcept { return _M_detection_mode; }
95165
std::exception_ptr evaluation_exception () const noexcept {
@@ -104,10 +174,11 @@ namespace contracts
104174
assertion_kind kind() const noexcept { return _M_assertion_kind; }
105175
std::source_location location() const noexcept { return _M_source_location; }
106176
evaluation_semantic semantic() const noexcept { return _M_evaluation_semantic; }
107-
};
177+
};
108178

109179
void invoke_default_contract_violation_handler(const contract_violation&) noexcept;
110180

181+
111182
} // namespace contracts
112183

113184
_GLIBCXX_END_NAMESPACE_VERSION

libstdc++-v3/src/experimental/contract26.cc

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,14 @@ void __handle_contract_violation(const std::contracts::contract_violation &viola
5151
case std::contracts::assertion_kind::assert:
5252
std::cerr << " assert";
5353
break;
54+
case std::contracts::assertion_kind::cassert:
55+
std::cerr << " cassert";
56+
break;
57+
case std::contracts::assertion_kind::manual:
58+
std::cerr << " manual";
59+
break;
5460
default:
55-
std::cerr << " unknown" << (int) violation.semantic();
61+
std::cerr << " unknown: " << (int) violation.kind();
5662
}
5763
delimiter = ", ";
5864

@@ -66,7 +72,7 @@ void __handle_contract_violation(const std::contracts::contract_violation &viola
6672
std::cerr << " observe";
6773
break;
6874
default:
69-
std::cerr << " unknown" << (int) violation.semantic();
75+
std::cerr << " unknown: " << (int) violation.semantic();
7076
}
7177
delimiter = ", ";
7278

@@ -79,8 +85,11 @@ void __handle_contract_violation(const std::contracts::contract_violation &viola
7985
case std::contracts::detection_mode::evaluation_exception:
8086
std::cerr << " evaluation_exception";
8187
break;
88+
case std::contracts::detection_mode::unspecified:
89+
std::cerr << " unspecified";
90+
break;
8291
default:
83-
std::cerr << "unknown";
92+
std::cerr << " unknown: " << (int) violation.mode();
8493
}
8594
delimiter = ", ";
8695

@@ -111,6 +120,12 @@ void __handle_contract_violation(const std::contracts::contract_violation &viola
111120
#endif
112121
}
113122

123+
__attribute__ ((weak)) void
124+
handle_contract_violation (const std::contracts::contract_violation &violation)
125+
{
126+
return __handle_contract_violation(violation);
127+
}
128+
114129
namespace std _GLIBCXX_VISIBILITY(default)
115130
{
116131
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -120,18 +135,58 @@ namespace contracts
120135

121136
void invoke_default_contract_violation_handler(const std::contracts::contract_violation& violation) noexcept
122137
{
123-
return __handle_contract_violation(violation);
138+
__handle_contract_violation(violation);
124139
}
125140

141+
// From P3290
142+
[[noreturn]] void handle_enforced_contract_violation(
143+
const char* __comment,
144+
const std::source_location &__location)
145+
{
146+
contract_violation __violation{evaluation_semantic::enforce, __location, __comment};
147+
handle_contract_violation(__violation);
148+
std::terminate();
126149
}
150+
151+
[[noreturn]] void handle_enforced_contract_violation(
152+
const std::nothrow_t&,
153+
const char* __comment,
154+
const std::source_location &__location) noexcept
155+
{
156+
contract_violation __violation{evaluation_semantic::enforce, __location, __comment};
157+
handle_contract_violation(__violation);
158+
std::terminate();
127159
}
128160

129-
__attribute__ ((weak)) void
130-
handle_contract_violation (const std::contracts::contract_violation &violation)
161+
162+
void handle_observed_contract_violation(
163+
const char* __comment,
164+
const std::source_location &__location)
131165
{
132-
return __handle_contract_violation(violation);
166+
contract_violation __violation{evaluation_semantic::observe, __location, __comment};
167+
handle_contract_violation(__violation);
133168
}
134169

170+
void handle_observed_contract_violation(
171+
const std::nothrow_t&,
172+
const char* __comment,
173+
const std::source_location &__location) noexcept
174+
{
175+
contract_violation __violation{evaluation_semantic::observe, __location, __comment};
176+
handle_contract_violation(__violation);
177+
}
178+
179+
[[noreturn]] void handle_quick_enforced_contract_violation(
180+
const char*,
181+
const std::source_location &) noexcept
182+
{
183+
std::terminate();
184+
}
185+
186+
}
187+
}
188+
189+
135190
#if _GLIBCXX_INLINE_VERSION
136191
// The compiler expects the contract_violation class to be in an unversioned
137192
// namespace, so provide a forwarding function with the expected symbol name.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
//
3+
// This file is part of the GNU ISO C++ Library. This library is free
4+
// software; you can redistribute it and/or modify it under the
5+
// terms of the GNU General Public License as published by the
6+
// Free Software Foundation; either version 3, or (at your option)
7+
// any later version.
8+
9+
// This library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License along
15+
// with this library; see the file COPYING3. If not see
16+
// <http://www.gnu.org/licenses/>.
17+
18+
// { dg-options "-g0 -fcontracts -fcontracts-nonattr -fcontract-evaluation-semantic=observe" }
19+
// { dg-do run { target c++2a } }
20+
21+
#include <contracts>
22+
#include <exception>
23+
#include <cstdlib>
24+
25+
void my_term()
26+
{
27+
std::exit(0);
28+
}
29+
30+
31+
int main()
32+
{
33+
std::set_terminate (my_term);
34+
35+
std::contracts::handle_quick_enforced_contract_violation("test comment");
36+
// We should not get here
37+
return 1;
38+
}
39+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
//
3+
// This file is part of the GNU ISO C++ Library. This library is free
4+
// software; you can redistribute it and/or modify it under the
5+
// terms of the GNU General Public License as published by the
6+
// Free Software Foundation; either version 3, or (at your option)
7+
// any later version.
8+
9+
// This library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License along
15+
// with this library; see the file COPYING3. If not see
16+
// <http://www.gnu.org/licenses/>.
17+
18+
// { dg-options "-g0 -fcontracts -fcontracts-nonattr -fcontract-evaluation-semantic=observe" }
19+
// { dg-do run { target c++2a } }
20+
21+
#include <contracts>
22+
#include <exception>
23+
#include <testsuite_hooks.h>
24+
25+
struct MyException{};
26+
27+
void handle_contract_violation(const std::contracts::contract_violation& v)
28+
{
29+
invoke_default_contract_violation_handler(v);
30+
throw MyException{};
31+
}
32+
33+
34+
int main()
35+
{
36+
bool exception_thrown = false;
37+
try {
38+
std::contracts::handle_enforced_contract_violation("test comment");
39+
}
40+
catch(MyException)
41+
{
42+
exception_thrown = true;
43+
}
44+
VERIFY( exception_thrown == true);
45+
}
46+
// { dg-output "contract violation in function int main.* at .*:38: test comment.*" }
47+
// { dg-output "assertion_kind: manual, semantic: enforce, mode: unspecified, terminating: yes" }

0 commit comments

Comments
 (0)