1 1.1 mrg /* Unit tests for hash-map.h. 2 1.1 mrg Copyright (C) 2015-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify it under 7 1.1 mrg the terms of the GNU General Public License as published by the Free 8 1.1 mrg Software Foundation; either version 3, or (at your option) any later 9 1.1 mrg version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 1.1 mrg for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License 17 1.1 mrg along with GCC; see the file COPYING3. If not see 18 1.1 mrg <http://www.gnu.org/licenses/>. */ 19 1.1 mrg 20 1.1 mrg #include "config.h" 21 1.1 mrg #include "system.h" 22 1.1 mrg #include "coretypes.h" 23 1.1 mrg #include "tm.h" 24 1.1 mrg #include "opts.h" 25 1.1 mrg #include "hash-set.h" 26 1.1 mrg #include "fixed-value.h" 27 1.1 mrg #include "alias.h" 28 1.1 mrg #include "flags.h" 29 1.1 mrg #include "symtab.h" 30 1.1 mrg #include "tree-core.h" 31 1.1 mrg #include "stor-layout.h" 32 1.1 mrg #include "tree.h" 33 1.1 mrg #include "stringpool.h" 34 1.1 mrg #include "selftest.h" 35 1.1 mrg 36 1.1 mrg #if CHECKING_P 37 1.1 mrg 38 1.1 mrg namespace selftest { 39 1.1 mrg 40 1.1 mrg /* Construct a hash_map <const char *, int> and verify that 41 1.1 mrg various operations work correctly. */ 42 1.1 mrg 43 1.1 mrg static void 44 1.1 mrg test_map_of_strings_to_int () 45 1.1 mrg { 46 1.1 mrg hash_map <const char *, int> m; 47 1.1 mrg 48 1.1 mrg const char *ostrich = "ostrich"; 49 1.1 mrg const char *elephant = "elephant"; 50 1.1 mrg const char *ant = "ant"; 51 1.1 mrg const char *spider = "spider"; 52 1.1 mrg const char *millipede = "Illacme plenipes"; 53 1.1 mrg const char *eric = "half a bee"; 54 1.1 mrg 55 1.1 mrg /* A fresh hash_map should be empty. */ 56 1.1 mrg ASSERT_TRUE (m.is_empty ()); 57 1.1 mrg ASSERT_EQ (NULL, m.get (ostrich)); 58 1.1 mrg 59 1.1 mrg /* Populate the hash_map. */ 60 1.1 mrg ASSERT_EQ (false, m.put (ostrich, 2)); 61 1.1 mrg ASSERT_EQ (false, m.put (elephant, 4)); 62 1.1 mrg ASSERT_EQ (false, m.put (ant, 6)); 63 1.1 mrg ASSERT_EQ (false, m.put (spider, 8)); 64 1.1 mrg ASSERT_EQ (false, m.put (millipede, 750)); 65 1.1 mrg ASSERT_EQ (false, m.put (eric, 3)); 66 1.1 mrg 67 1.1 mrg /* Verify that we can recover the stored values. */ 68 1.1 mrg ASSERT_EQ (6, m.elements ()); 69 1.1 mrg ASSERT_EQ (2, *m.get (ostrich)); 70 1.1 mrg ASSERT_EQ (4, *m.get (elephant)); 71 1.1 mrg ASSERT_EQ (6, *m.get (ant)); 72 1.1 mrg ASSERT_EQ (8, *m.get (spider)); 73 1.1 mrg ASSERT_EQ (750, *m.get (millipede)); 74 1.1 mrg ASSERT_EQ (3, *m.get (eric)); 75 1.1 mrg 76 1.1 mrg /* Verify removing an item. */ 77 1.1 mrg m.remove (eric); 78 1.1 mrg ASSERT_EQ (5, m.elements ()); 79 1.1 mrg ASSERT_EQ (NULL, m.get (eric)); 80 1.1 mrg 81 1.1 mrg m.remove (eric); 82 1.1 mrg ASSERT_EQ (5, m.elements ()); 83 1.1 mrg ASSERT_EQ (NULL, m.get (eric)); 84 1.1 mrg 85 1.1 mrg /* A plain char * key is hashed based on its value (address), rather 86 1.1 mrg than the string it points to. */ 87 1.1 mrg char *another_ant = static_cast <char *> (xcalloc (4, 1)); 88 1.1 mrg another_ant[0] = 'a'; 89 1.1 mrg another_ant[1] = 'n'; 90 1.1 mrg another_ant[2] = 't'; 91 1.1 mrg another_ant[3] = 0; 92 1.1 mrg ASSERT_NE (ant, another_ant); 93 1.1 mrg unsigned prev_size = m.elements (); 94 1.1 mrg ASSERT_EQ (false, m.put (another_ant, 7)); 95 1.1 mrg ASSERT_EQ (prev_size + 1, m.elements ()); 96 1.1 mrg 97 1.1 mrg /* Need to use string_hash or nofree_string_hash key types to hash 98 1.1 mrg based on the string contents. */ 99 1.1 mrg hash_map <nofree_string_hash, int> string_map; 100 1.1 mrg ASSERT_EQ (false, string_map.put (ant, 1)); 101 1.1 mrg ASSERT_EQ (1, string_map.elements ()); 102 1.1 mrg ASSERT_EQ (true, string_map.put (another_ant, 5)); 103 1.1 mrg ASSERT_EQ (1, string_map.elements ()); 104 1.1 mrg 105 1.1 mrg free (another_ant); 106 1.1 mrg } 107 1.1 mrg 108 1.1 mrg /* Construct a hash_map using int_hash and verify that 109 1.1 mrg various operations work correctly. */ 110 1.1 mrg 111 1.1 mrg static void 112 1.1 mrg test_map_of_int_to_strings () 113 1.1 mrg { 114 1.1 mrg const int EMPTY = -1; 115 1.1 mrg const int DELETED = -2; 116 1.1 mrg typedef int_hash <int, EMPTY, DELETED> int_hash_t; 117 1.1 mrg hash_map <int_hash_t, const char *> m; 118 1.1 mrg 119 1.1 mrg const char *ostrich = "ostrich"; 120 1.1 mrg const char *elephant = "elephant"; 121 1.1 mrg const char *ant = "ant"; 122 1.1 mrg const char *spider = "spider"; 123 1.1 mrg const char *millipede = "Illacme plenipes"; 124 1.1 mrg const char *eric = "half a bee"; 125 1.1 mrg 126 1.1 mrg /* A fresh hash_map should be empty. */ 127 1.1 mrg ASSERT_EQ (0, m.elements ()); 128 1.1 mrg ASSERT_EQ (NULL, m.get (2)); 129 1.1 mrg 130 1.1 mrg /* Populate the hash_map. */ 131 1.1 mrg ASSERT_EQ (false, m.put (2, ostrich)); 132 1.1 mrg ASSERT_EQ (false, m.put (4, elephant)); 133 1.1 mrg ASSERT_EQ (false, m.put (6, ant)); 134 1.1 mrg ASSERT_EQ (false, m.put (8, spider)); 135 1.1 mrg ASSERT_EQ (false, m.put (750, millipede)); 136 1.1 mrg ASSERT_EQ (false, m.put (3, eric)); 137 1.1 mrg 138 1.1 mrg /* Verify that we can recover the stored values. */ 139 1.1 mrg ASSERT_EQ (6, m.elements ()); 140 1.1 mrg ASSERT_EQ (*m.get (2), ostrich); 141 1.1 mrg ASSERT_EQ (*m.get (4), elephant); 142 1.1 mrg ASSERT_EQ (*m.get (6), ant); 143 1.1 mrg ASSERT_EQ (*m.get (8), spider); 144 1.1 mrg ASSERT_EQ (*m.get (750), millipede); 145 1.1 mrg ASSERT_EQ (*m.get (3), eric); 146 1.1 mrg } 147 1.1 mrg 148 1.1 mrg typedef class hash_map_test_val_t 149 1.1 mrg { 150 1.1 mrg public: 151 1.1 mrg static int ndefault; 152 1.1 mrg static int ncopy; 153 1.1 mrg static int nassign; 154 1.1 mrg static int ndtor; 155 1.1 mrg 156 1.1 mrg hash_map_test_val_t () 157 1.1 mrg : ptr (&ptr) 158 1.1 mrg { 159 1.1 mrg ++ndefault; 160 1.1 mrg } 161 1.1 mrg 162 1.1 mrg hash_map_test_val_t (const hash_map_test_val_t &rhs) 163 1.1 mrg : ptr (&ptr) 164 1.1 mrg { 165 1.1 mrg ++ncopy; 166 1.1 mrg gcc_assert (rhs.ptr == &rhs.ptr); 167 1.1 mrg } 168 1.1 mrg 169 1.1 mrg hash_map_test_val_t& operator= (const hash_map_test_val_t &rhs) 170 1.1 mrg { 171 1.1 mrg ++nassign; 172 1.1 mrg gcc_assert (ptr == &ptr); 173 1.1 mrg gcc_assert (rhs.ptr == &rhs.ptr); 174 1.1 mrg return *this; 175 1.1 mrg } 176 1.1 mrg 177 1.1 mrg ~hash_map_test_val_t () 178 1.1 mrg { 179 1.1 mrg gcc_assert (ptr == &ptr); 180 1.1 mrg ++ndtor; 181 1.1 mrg } 182 1.1 mrg 183 1.1 mrg void *ptr; 184 1.1 mrg } val_t; 185 1.1 mrg 186 1.1 mrg int val_t::ndefault; 187 1.1 mrg int val_t::ncopy; 188 1.1 mrg int val_t::nassign; 189 1.1 mrg int val_t::ndtor; 190 1.1 mrg 191 1.1 mrg static void 192 1.1 mrg test_map_of_type_with_ctor_and_dtor () 193 1.1 mrg { 194 1.1 mrg typedef hash_map <void *, val_t> Map; 195 1.1 mrg 196 1.1 mrg { 197 1.1 mrg /* Test default ctor. */ 198 1.1 mrg Map m; 199 1.1 mrg (void)&m; 200 1.1 mrg } 201 1.1 mrg 202 1.1 mrg ASSERT_TRUE (val_t::ndefault == 0); 203 1.1 mrg ASSERT_TRUE (val_t::ncopy == 0); 204 1.1 mrg ASSERT_TRUE (val_t::nassign == 0); 205 1.1 mrg ASSERT_TRUE (val_t::ndtor == 0); 206 1.1 mrg 207 1.1 mrg { 208 1.1 mrg /* Test single insertion. */ 209 1.1 mrg Map m; 210 1.1 mrg void *p = &p; 211 1.1 mrg m.get_or_insert (p); 212 1.1 mrg } 213 1.1 mrg 214 1.1 mrg ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor); 215 1.1 mrg 216 1.1 mrg { 217 1.1 mrg /* Test copy ctor. */ 218 1.1 mrg Map m1; 219 1.1 mrg void *p = &p; 220 1.1 mrg val_t &rv1 = m1.get_or_insert (p); 221 1.1 mrg 222 1.1 mrg int ncopy = val_t::ncopy; 223 1.1 mrg int nassign = val_t::nassign; 224 1.1 mrg 225 1.1 mrg Map m2 (m1); 226 1.1 mrg val_t *pv2 = m2.get (p); 227 1.1 mrg 228 1.1 mrg ASSERT_TRUE (ncopy + 1 == val_t::ncopy); 229 1.1 mrg ASSERT_TRUE (nassign == val_t::nassign); 230 1.1 mrg 231 1.1 mrg ASSERT_TRUE (&rv1 != pv2); 232 1.1 mrg } 233 1.1 mrg 234 1.1 mrg ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor); 235 1.1 mrg 236 1.1 mrg #if 0 /* Avoid testing until bug 90959 is fixed. */ 237 1.1 mrg { 238 1.1 mrg /* Test copy assignment into an empty map. */ 239 1.1 mrg Map m1; 240 1.1 mrg void *p = &p; 241 1.1 mrg val_t &rv1 = m1.get_or_insert (p); 242 1.1 mrg 243 1.1 mrg int ncopy = val_t::ncopy; 244 1.1 mrg int nassign = val_t::nassign; 245 1.1 mrg 246 1.1 mrg Map m2; 247 1.1 mrg m2 = m1; 248 1.1 mrg val_t *pv2 = m2.get (p); 249 1.1 mrg 250 1.1 mrg ASSERT_TRUE (ncopy == val_t::ncopy); 251 1.1 mrg ASSERT_TRUE (nassign + 1 == val_t::nassign); 252 1.1 mrg 253 1.1 mrg ASSERT_TRUE (&rv1 != pv2); 254 1.1 mrg } 255 1.1 mrg 256 1.1 mrg ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor); 257 1.1 mrg 258 1.1 mrg #endif 259 1.1 mrg 260 1.1 mrg { 261 1.1 mrg Map m; 262 1.1 mrg void *p = &p, *q = &q; 263 1.1 mrg val_t &v1 = m.get_or_insert (p); 264 1.1 mrg val_t &v2 = m.get_or_insert (q); 265 1.1 mrg 266 1.1 mrg ASSERT_TRUE (v1.ptr == &v1.ptr && &v2.ptr == v2.ptr); 267 1.1 mrg } 268 1.1 mrg 269 1.1 mrg ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor); 270 1.1 mrg 271 1.1 mrg { 272 1.1 mrg Map m; 273 1.1 mrg void *p = &p, *q = &q; 274 1.1 mrg m.get_or_insert (p); 275 1.1 mrg m.remove (p); 276 1.1 mrg m.get_or_insert (q); 277 1.1 mrg m.remove (q); 278 1.1 mrg 279 1.1 mrg ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor); 280 1.1 mrg } 281 1.1 mrg 282 1.1 mrg 283 1.1 mrg /* Verify basic construction and destruction of Value objects. */ 284 1.1 mrg { 285 1.1 mrg /* Configure, arbitrary. */ 286 1.1 mrg const size_t N_init = 0; 287 1.1 mrg const int N_elem = 28; 288 1.1 mrg 289 1.1 mrg void *a[N_elem]; 290 1.1 mrg for (size_t i = 0; i < N_elem; ++i) 291 1.1 mrg a[i] = &a[i]; 292 1.1 mrg 293 1.1 mrg val_t::ndefault = 0; 294 1.1 mrg val_t::ncopy = 0; 295 1.1 mrg val_t::nassign = 0; 296 1.1 mrg val_t::ndtor = 0; 297 1.1 mrg Map m (N_init); 298 1.1 mrg ASSERT_EQ (val_t::ndefault 299 1.1 mrg + val_t::ncopy 300 1.1 mrg + val_t::nassign 301 1.1 mrg + val_t::ndtor, 0); 302 1.1 mrg 303 1.1 mrg for (int i = 0; i < N_elem; ++i) 304 1.1 mrg { 305 1.1 mrg m.get_or_insert (a[i]); 306 1.1 mrg ASSERT_EQ (val_t::ndefault, 1 + i); 307 1.1 mrg ASSERT_EQ (val_t::ncopy, 0); 308 1.1 mrg ASSERT_EQ (val_t::nassign, 0); 309 1.1 mrg ASSERT_EQ (val_t::ndtor, i); 310 1.1 mrg 311 1.1 mrg m.remove (a[i]); 312 1.1 mrg ASSERT_EQ (val_t::ndefault, 1 + i); 313 1.1 mrg ASSERT_EQ (val_t::ncopy, 0); 314 1.1 mrg ASSERT_EQ (val_t::nassign, 0); 315 1.1 mrg ASSERT_EQ (val_t::ndtor, 1 + i); 316 1.1 mrg } 317 1.1 mrg } 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg /* Verify aspects of 'hash_table::expand', in particular that it doesn't leak 321 1.1 mrg Value objects. */ 322 1.1 mrg 323 1.1 mrg static void 324 1.1 mrg test_map_of_type_with_ctor_and_dtor_expand (bool remove_some_inline) 325 1.1 mrg { 326 1.1 mrg /* Configure, so that hash table expansion triggers a few times. */ 327 1.1 mrg const size_t N_init = 0; 328 1.1 mrg const int N_elem = 70; 329 1.1 mrg size_t expand_c_expected = 4; 330 1.1 mrg size_t expand_c = 0; 331 1.1 mrg 332 1.1 mrg /* For stability of this testing, we need all Key values 'k' to produce 333 1.1 mrg unique hash values 'Traits::hash (k)', as otherwise the dynamic 334 1.1 mrg insert/remove behavior may diverge across different architectures. This 335 1.1 mrg is, for example, a problem when using the standard 'pointer_hash::hash', 336 1.1 mrg which is simply doing a 'k >> 3' operation, which is fine on 64-bit 337 1.1 mrg architectures, but on 32-bit architectures produces the same hash value 338 1.1 mrg for subsequent 'a[i] = &a[i]' array elements. Therefore, use an 339 1.1 mrg 'int_hash'. */ 340 1.1 mrg 341 1.1 mrg int a[N_elem]; 342 1.1 mrg for (size_t i = 0; i < N_elem; ++i) 343 1.1 mrg a[i] = i; 344 1.1 mrg 345 1.1 mrg const int EMPTY = -1; 346 1.1 mrg const int DELETED = -2; 347 1.1 mrg typedef hash_map<int_hash<int, EMPTY, DELETED>, val_t> Map; 348 1.1 mrg 349 1.1 mrg /* Note that we are starting with a fresh 'Map'. Even if an existing one has 350 1.1 mrg been cleared out completely, there remain 'deleted' elements, and these 351 1.1 mrg would disturb the following logic, where we don't have access to the 352 1.1 mrg actual 'm_n_deleted' value. */ 353 1.1 mrg size_t m_n_deleted = 0; 354 1.1 mrg 355 1.1 mrg val_t::ndefault = 0; 356 1.1 mrg val_t::ncopy = 0; 357 1.1 mrg val_t::nassign = 0; 358 1.1 mrg val_t::ndtor = 0; 359 1.1 mrg Map m (N_init); 360 1.1 mrg 361 1.1 mrg /* In the following, in particular related to 'expand', we're adapting from 362 1.1 mrg the internal logic of 'hash_table', glossing over "some details" not 363 1.1 mrg relevant for this testing here. */ 364 1.1 mrg 365 1.1 mrg /* Per 'hash_table::hash_table'. */ 366 1.1 mrg size_t m_size; 367 1.1 mrg { 368 1.1 mrg unsigned int size_prime_index_ = hash_table_higher_prime_index (N_init); 369 1.1 mrg m_size = prime_tab[size_prime_index_].prime; 370 1.1 mrg } 371 1.1 mrg 372 1.1 mrg int n_expand_moved = 0; 373 1.1 mrg 374 1.1 mrg for (int i = 0; i < N_elem; ++i) 375 1.1 mrg { 376 1.1 mrg size_t elts = m.elements (); 377 1.1 mrg 378 1.1 mrg /* Per 'hash_table::find_slot_with_hash'. */ 379 1.1 mrg size_t m_n_elements = elts + m_n_deleted; 380 1.1 mrg bool expand = m_size * 3 <= m_n_elements * 4; 381 1.1 mrg 382 1.1 mrg m.get_or_insert (a[i]); 383 1.1 mrg if (expand) 384 1.1 mrg { 385 1.1 mrg ++expand_c; 386 1.1 mrg 387 1.1 mrg /* Per 'hash_table::expand'. */ 388 1.1 mrg { 389 1.1 mrg unsigned int nindex = hash_table_higher_prime_index (elts * 2); 390 1.1 mrg m_size = prime_tab[nindex].prime; 391 1.1 mrg } 392 1.1 mrg m_n_deleted = 0; 393 1.1 mrg 394 1.1 mrg /* All non-deleted elements have been moved. */ 395 1.1 mrg n_expand_moved += i; 396 1.1 mrg if (remove_some_inline) 397 1.1 mrg n_expand_moved -= (i + 2) / 3; 398 1.1 mrg } 399 1.1 mrg 400 1.1 mrg ASSERT_EQ (val_t::ndefault, 1 + i); 401 1.1 mrg ASSERT_EQ (val_t::ncopy, n_expand_moved); 402 1.1 mrg ASSERT_EQ (val_t::nassign, 0); 403 1.1 mrg if (remove_some_inline) 404 1.1 mrg ASSERT_EQ (val_t::ndtor, n_expand_moved + (i + 2) / 3); 405 1.1 mrg else 406 1.1 mrg ASSERT_EQ (val_t::ndtor, n_expand_moved); 407 1.1 mrg 408 1.1 mrg /* Remove some inline. This never triggers an 'expand' here, but via 409 1.1 mrg 'm_n_deleted' does influence any following one. */ 410 1.1 mrg if (remove_some_inline 411 1.1 mrg && !(i % 3)) 412 1.1 mrg { 413 1.1 mrg m.remove (a[i]); 414 1.1 mrg /* Per 'hash_table::remove_elt_with_hash'. */ 415 1.1 mrg m_n_deleted++; 416 1.1 mrg 417 1.1 mrg ASSERT_EQ (val_t::ndefault, 1 + i); 418 1.1 mrg ASSERT_EQ (val_t::ncopy, n_expand_moved); 419 1.1 mrg ASSERT_EQ (val_t::nassign, 0); 420 1.1 mrg ASSERT_EQ (val_t::ndtor, n_expand_moved + 1 + (i + 2) / 3); 421 1.1 mrg } 422 1.1 mrg } 423 1.1 mrg ASSERT_EQ (expand_c, expand_c_expected); 424 1.1 mrg 425 1.1 mrg int ndefault = val_t::ndefault; 426 1.1 mrg int ncopy = val_t::ncopy; 427 1.1 mrg int nassign = val_t::nassign; 428 1.1 mrg int ndtor = val_t::ndtor; 429 1.1 mrg 430 1.1 mrg for (int i = 0; i < N_elem; ++i) 431 1.1 mrg { 432 1.1 mrg if (remove_some_inline 433 1.1 mrg && !(i % 3)) 434 1.1 mrg continue; 435 1.1 mrg 436 1.1 mrg m.remove (a[i]); 437 1.1 mrg ++ndtor; 438 1.1 mrg ASSERT_EQ (val_t::ndefault, ndefault); 439 1.1 mrg ASSERT_EQ (val_t::ncopy, ncopy); 440 1.1 mrg ASSERT_EQ (val_t::nassign, nassign); 441 1.1 mrg ASSERT_EQ (val_t::ndtor, ndtor); 442 1.1 mrg } 443 1.1 mrg ASSERT_EQ (val_t::ndefault + val_t::ncopy, val_t::ndtor); 444 1.1 mrg } 445 1.1 mrg 446 1.1 mrg /* Test calling empty on a hash_map that has a key type with non-zero 447 1.1 mrg "empty" value. */ 448 1.1 mrg 449 1.1 mrg static void 450 1.1 mrg test_nonzero_empty_key () 451 1.1 mrg { 452 1.1 mrg typedef int_hash<int, INT_MIN, INT_MAX> IntHash; 453 1.1 mrg hash_map<int, int, simple_hashmap_traits<IntHash, int> > x; 454 1.1 mrg 455 1.1 mrg for (int i = 1; i != 32; ++i) 456 1.1 mrg x.put (i, i); 457 1.1 mrg 458 1.1 mrg ASSERT_EQ (x.get (0), NULL); 459 1.1 mrg ASSERT_EQ (*x.get (1), 1); 460 1.1 mrg 461 1.1 mrg x.empty (); 462 1.1 mrg 463 1.1 mrg ASSERT_EQ (x.get (0), NULL); 464 1.1 mrg ASSERT_EQ (x.get (1), NULL); 465 1.1 mrg } 466 1.1 mrg 467 1.1 mrg /* Run all of the selftests within this file. */ 468 1.1 mrg 469 1.1 mrg void 470 1.1 mrg hash_map_tests_cc_tests () 471 1.1 mrg { 472 1.1 mrg test_map_of_strings_to_int (); 473 1.1 mrg test_map_of_int_to_strings (); 474 1.1 mrg test_map_of_type_with_ctor_and_dtor (); 475 1.1 mrg test_map_of_type_with_ctor_and_dtor_expand (false); 476 1.1 mrg test_map_of_type_with_ctor_and_dtor_expand (true); 477 1.1 mrg test_nonzero_empty_key (); 478 1.1 mrg } 479 1.1 mrg 480 1.1 mrg } // namespace selftest 481 1.1 mrg 482 1.1 mrg #endif /* CHECKING_P */ 483