]>
Commit | Line | Data |
---|---|---|
8d9254fc | 1 | // Copyright (C) 2018-2020 Free Software Foundation, Inc. |
b66e5a95 JW |
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-do run } | |
bce17c39 | 19 | // { dg-xfail-run-if "AIX operator new" { powerpc-ibm-aix* } } |
b66e5a95 JW |
20 | |
21 | #include <new> | |
22 | #include <stdlib.h> | |
23 | #include <testsuite_hooks.h> | |
24 | ||
25 | // PR libstdc++/68210 | |
26 | ||
27 | struct MyBadAlloc: std::bad_alloc { }; | |
28 | ||
29 | static bool new_fail; | |
30 | static bool bad_alloc_thrown; | |
31 | static unsigned new_called; | |
32 | static unsigned delete_called; | |
33 | static unsigned new_vec_called; | |
34 | static unsigned delete_vec_called; | |
35 | static unsigned new_handler_called; | |
36 | ||
37 | static void new_handler () | |
38 | { | |
39 | if (new_handler_called++) | |
40 | throw MyBadAlloc (); | |
41 | } | |
42 | ||
43 | void* operator new (size_t n) | |
44 | { | |
45 | static size_t cntr; | |
46 | ||
47 | ++new_called; | |
48 | ||
49 | for ( ; ; ) { | |
50 | if (void *p = new_fail ? 0 : malloc (n + sizeof n)) { | |
51 | *static_cast<size_t*>(p) = ++cntr; | |
52 | return static_cast<size_t*>(p) + 1; | |
53 | } | |
54 | ||
55 | if (std::new_handler h = std::set_new_handler (0)) { | |
56 | std::set_new_handler (h); | |
57 | h (); | |
58 | } | |
59 | else { | |
60 | bad_alloc_thrown = true; | |
61 | throw MyBadAlloc (); | |
62 | } | |
63 | } | |
64 | } | |
65 | ||
66 | void operator delete (void *p) | |
67 | { | |
68 | ++delete_called; | |
69 | if (p) | |
70 | free (static_cast<size_t*>(p) - 1); | |
71 | } | |
72 | ||
73 | void* operator new[] (size_t n) | |
74 | { | |
75 | ++new_vec_called; | |
76 | return operator new(n); | |
77 | } | |
78 | ||
79 | void operator delete[] (void *p) | |
80 | { | |
81 | ++delete_vec_called; | |
82 | operator delete(p); | |
83 | } | |
84 | ||
85 | #if __cplusplus >= 201402L | |
86 | void operator delete (void *p, std::size_t) | |
87 | { | |
88 | ::operator delete(p); | |
89 | } | |
90 | void operator delete[] (void *p, std::size_t) | |
91 | { | |
92 | ::operator delete[](p); | |
93 | } | |
94 | #endif | |
95 | ||
96 | void init() | |
97 | { | |
98 | new_fail = false; | |
99 | new_called = 0; | |
100 | delete_called = 0; | |
101 | new_vec_called = 0; | |
102 | delete_vec_called = 0; | |
103 | new_handler_called = 0; | |
104 | std::set_new_handler (0); | |
105 | } | |
106 | ||
107 | void | |
108 | test01() | |
109 | { | |
110 | init (); | |
111 | ||
112 | void *p = operator new (1, std::nothrow); | |
113 | ||
114 | VERIFY (p != 0); | |
115 | VERIFY (1 == new_called); | |
116 | VERIFY (0 == new_handler_called); | |
117 | VERIFY (!bad_alloc_thrown); | |
118 | ||
119 | operator delete (p, std::nothrow); | |
120 | VERIFY( 1 == delete_called ); | |
121 | ||
122 | new_fail = true; | |
123 | p = operator new (1, std::nothrow); | |
124 | ||
125 | VERIFY (0 == p); | |
126 | VERIFY (2 == new_called); | |
127 | VERIFY (0 == new_handler_called); | |
128 | VERIFY (bad_alloc_thrown); | |
129 | ||
130 | new_fail = true; | |
131 | bad_alloc_thrown = false; | |
132 | std::set_new_handler (new_handler); | |
133 | p = operator new (1, std::nothrow); | |
134 | ||
135 | VERIFY (0 == p); | |
136 | VERIFY (3 == new_called); | |
137 | VERIFY (2 == new_handler_called); | |
138 | VERIFY (!bad_alloc_thrown); | |
139 | } | |
140 | ||
141 | void | |
142 | test02() | |
143 | { | |
144 | init (); | |
145 | ||
146 | void *p = operator new[] (1, std::nothrow); | |
147 | ||
148 | VERIFY (p != 0); | |
149 | VERIFY (1 == new_called); | |
150 | VERIFY (1 == new_vec_called); | |
151 | VERIFY (0 == new_handler_called); | |
152 | VERIFY (!bad_alloc_thrown); | |
153 | ||
154 | operator delete[] (p, std::nothrow); | |
155 | VERIFY( 1 == delete_called ); | |
156 | VERIFY( 1 == delete_vec_called ); | |
157 | ||
158 | new_fail = true; | |
159 | p = operator new[] (1, std::nothrow); | |
160 | ||
161 | VERIFY (0 == p); | |
162 | VERIFY (2 == new_called); | |
163 | VERIFY (2 == new_vec_called); | |
164 | VERIFY (0 == new_handler_called); | |
165 | VERIFY (bad_alloc_thrown); | |
166 | ||
167 | new_fail = true; | |
168 | bad_alloc_thrown = false; | |
169 | std::set_new_handler (new_handler); | |
170 | p = operator new[] (1, std::nothrow); | |
171 | ||
172 | VERIFY (0 == p); | |
173 | VERIFY (3 == new_called); | |
174 | VERIFY (3 == new_vec_called); | |
175 | VERIFY (2 == new_handler_called); | |
176 | VERIFY (!bad_alloc_thrown); | |
177 | } | |
178 | ||
179 | ||
180 | int main() | |
181 | { | |
182 | test01(); | |
183 | test02(); | |
184 | } |