1// (C) Copyright Niels Dekker 2010. 2// Use, modification and distribution are subject to the 3// Boost Software License, Version 1.0. (See accompanying file 4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6// See http://www.boost.org/libs/config for most recent version. 7 8// MACRO: BOOST_NO_COMPLETE_VALUE_INITIALIZATION 9// TITLE: No complete value-initialization 10// DESCRIPTION: The C++ compiler does not to have implemented value-initialization completely. 11// See also boost/libs/utility/value_init.htm#compiler_issues 12 13#include <iostream> 14 15// This test checks various forms of value-initialization: 16// - doing subobject initialization inside a constructor 17// - creating a temporary object by T() 18// - creating a heap object by doing new T() 19// It checks various DefaultConstructible types, including fundamental types, 20// enum, union, pointer types, array types, POD and non-POD class types. For 21// each type of object, a helper function is_value_initialized(const T&) tells 22// whether the object is value-initialized. 23// 24// Note: It appeared insufficient to just check a single POD and a single 25// non-POD class type, because some compilers correctly value-initialize some 26// POD and some non-POD objects, while failing to value-initialize others. 27// 28// The test returns the number of encountered value-initialization failures. 29 30namespace boost_no_complete_value_initialization 31{ 32 enum enum_type { negative_number = -1, magic_number = 42 }; 33 34 class incomplete_class; 35 36 typedef int (*function_ptr_type)(int); 37 typedef int (incomplete_class::*member_function_ptr_type)(int); 38 39 // A POD struct. 40 struct pod_struct 41 { 42 enum_type e; 43 bool b; 44 char c; 45 unsigned char uc; 46 short s; 47 int i; 48 unsigned u; 49 long l; 50 float f; 51 double d; 52 long double ld; 53 void* p; 54 }; 55 56 bool is_value_initialized(const pod_struct& arg) 57 { 58 return 59 arg.b == 0 && 60 arg.e == 0 && 61 arg.c == 0 && 62 arg.uc == 0 && 63 arg.s == 0 && 64 arg.i == 0 && 65 arg.u == 0 && 66 arg.l == 0 && 67 arg.f == 0 && 68 arg.d == 0 && 69 arg.p == 0; 70 } 71 72 // A POD struct derived from another POD struct. 73 struct derived_pod_struct: pod_struct 74 { 75 int derived_data; 76 }; 77 78 bool is_value_initialized(const derived_pod_struct& arg) 79 { 80 const pod_struct& base_subobject = arg; 81 return arg.derived_data == 0 && is_value_initialized(base_subobject); 82 } 83 84 85 struct empty_struct 86 { 87 }; 88 89 90 // A POD aggregate struct derived from an empty struct. 91 // Similar to struct Foo1 from Microsoft Visual C++ bug report 484295, 92 // "VC++ does not value-initialize members of derived classes without 93 // user-declared constructor", reported in 2009 by Sylvester Hesp: 94 // https://connect.microsoft.com/VisualStudio/feedback/details/484295 95 struct derived_struct: empty_struct 96 { 97 int data; 98 }; 99 100 bool is_value_initialized(const derived_struct& arg) 101 { 102 return arg.data == 0; 103 } 104 105 106 // A struct, having a bit-field. 107 struct bit_field_struct 108 { 109 bool b : 1; 110 char c : 7; 111 unsigned u: 8 * sizeof(unsigned) - 1; 112 }; 113 114 bool is_value_initialized(const bit_field_struct& arg) 115 { 116 return arg.b == false && arg.c == '\0'&& arg.u == 0U; 117 } 118 119 // A struct, having a function pointer. 120 struct function_ptr_struct 121 { 122 function_ptr_type data; 123 }; 124 125 bool is_value_initialized(const function_ptr_struct& arg) 126 { 127 return arg.data == 0; 128 } 129 130 // A struct, having a member function pointer. 131 struct member_function_ptr_struct 132 { 133 member_function_ptr_type data; 134 }; 135 136 bool is_value_initialized(const member_function_ptr_struct& arg) 137 { 138 return arg.data == 0; 139 } 140 141 struct int_pair_struct 142 { 143 int first; 144 int second; 145 }; 146 147 typedef int int_pair_struct::*ptr_to_member_type; 148 149 struct ptr_to_member_struct 150 { 151 ptr_to_member_type data; 152 }; 153 154 bool is_value_initialized(const ptr_to_member_struct& arg) 155 { 156 return arg.data == 0; 157 } 158 159 // A struct, having an int. Equivalent to the struct TData, from CodeGear bug 160 // report 51854, "Value-initialization: POD struct should be zero-initialized", 161 // reported by me (Niels Dekker, LKEB) in 2007: 162 // http://qc.embarcadero.com/wc/qcmain.aspx?d=51854 163 struct int_struct 164 { 165 int data; 166 }; 167 168 bool is_value_initialized(const int_struct& arg) 169 { 170 return arg.data == 0; 171 } 172 173 174 // A struct, having an int_struct. 175 struct int_struct_holder 176 { 177 int_struct data; 178 }; 179 180 bool is_value_initialized(const int_struct_holder& arg) 181 { 182 return is_value_initialized(arg.data); 183 } 184 185 186 // A struct derived from int_struct. 187 struct derived_int_struct: int_struct 188 { 189 }; 190 191 bool is_value_initialized(const derived_int_struct& arg) 192 { 193 return arg.data == 0; 194 } 195 196 197 struct char_array_struct 198 { 199 char data[42]; 200 }; 201 202 bool is_value_initialized(const char_array_struct& arg) 203 { 204 for ( unsigned i = 0; i < sizeof(arg.data); ++i) 205 { 206 if ( arg.data[i] != 0 ) 207 { 208 return false; 209 } 210 } 211 return true; 212 } 213 214 215 class private_int_holder 216 { 217 private: 218 int m_data; 219 220 friend bool is_value_initialized(const private_int_holder& arg) 221 { 222 return arg.m_data == 0; 223 } 224 }; 225 226 227 // Equivalent to the Stats class from GCC Bug 33916, 228 // "Default constructor fails to initialize array members", reported in 2007 by 229 // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 230 class private_int_array_pair 231 { 232 friend bool is_value_initialized(const private_int_array_pair& arg); 233 private: 234 int first[12]; 235 int second[12]; 236 }; 237 238 bool is_value_initialized(const private_int_array_pair& arg) 239 { 240 for ( unsigned i = 0; i < 12; ++i) 241 { 242 if ( (arg.first[i] != 0) || (arg.second[i] != 0) ) 243 { 244 return false; 245 } 246 } 247 return true; 248 } 249 250 251 union pod_struct_and_int_union 252 { 253 pod_struct first; 254 int second; 255 }; 256 257 bool is_value_initialized(const pod_struct_and_int_union& arg) 258 { 259 // When a union is zero-initialized, its first non-static 260 // named data member is zero-initialized ([dcl.init]). 261 return is_value_initialized(arg.first); 262 } 263 264 265 union int_and_pod_struct_union 266 { 267 int first; 268 pod_struct second; 269 }; 270 271 bool is_value_initialized(const int_and_pod_struct_union& arg) 272 { 273 return arg.first == 0; 274 } 275 276 277 // A class that holds a "magic" enum value. 278 // Note: This is not a POD class, because it has a user-defined 279 // default constructor. 280 class enum_holder 281 { 282 enum_type m_enum; 283 public: 284 285 enum_holder() 286 : 287 m_enum(magic_number) 288 { 289 } 290 291 bool is_value_initialized() const 292 { 293 return m_enum == magic_number; 294 } 295 }; 296 297 bool is_value_initialized(const enum_holder& arg) 298 { 299 return arg.is_value_initialized(); 300 } 301 302 303 // An aggregate struct of a non-POD class and an int. 304 // Similar to struct A from Microsoft Visual C++ bug report 100744, 305 // "Value-initialization in new-expression", reported in 2005 by 306 // Pavel Kuznetsov (MetaCommunications Engineering): 307 // https://connect.microsoft.com/VisualStudio/feedback/details/100744 308 struct enum_holder_and_int 309 { 310 enum_holder e; 311 int i; 312 }; 313 314 bool is_value_initialized(const enum_holder_and_int& arg) 315 { 316 return arg.e.is_value_initialized() && arg.i == 0; 317 } 318 319 class user_defined_copy_constructor_holder 320 { 321 public: 322 int data; 323 324 user_defined_copy_constructor_holder() 325 : 326 data(0) 327 { 328 } 329 330 user_defined_copy_constructor_holder(const user_defined_copy_constructor_holder& arg) 331 : 332 data(arg.data) 333 { 334 } 335 }; 336 337 // An aggregate struct that has a data member which has a user-defined 338 // copy constructor and a data member of a scalar type. 339 // Similar to struct B from Microsoft Visual C++ bug report 499606, 340 // "Presence of copy constructor breaks member class initialization", 341 // reported in 2009 by Alex Vakulenko: 342 // https://connect.microsoft.com/VisualStudio/feedback/details/499606 343 struct user_defined_copy_constructor_holder_and_int 344 { 345 user_defined_copy_constructor_holder first; 346 int second; 347 }; 348 349 bool is_value_initialized(const user_defined_copy_constructor_holder_and_int& arg) 350 { 351 return arg.first.data == 0 && arg.second == 0; 352 } 353 354 355 // An class that has a private and a protected int data member. 356 class private_and_protected_int 357 { 358 private: 359 int private_int; 360 protected: 361 int protected_int; 362 public: 363 friend bool is_value_initialized(const private_and_protected_int& arg) 364 { 365 return arg.private_int == 0 && arg.protected_int == 0; 366 } 367 }; 368 369 370 class user_defined_destructor_holder 371 { 372 public: 373 int i; 374 ~user_defined_destructor_holder() 375 { 376 } 377 }; 378 379 bool is_value_initialized(const user_defined_destructor_holder& arg) 380 { 381 return arg.i == 0; 382 } 383 384 385 class virtual_destructor_holder 386 { 387 public: 388 int i; 389 virtual ~virtual_destructor_holder() 390 { 391 } 392 }; 393 394 bool is_value_initialized(const virtual_destructor_holder& arg) 395 { 396 return arg.i == 0; 397 } 398 399 400 // A class that is not a POD type. 401 class non_pod_class 402 { 403 private: 404 enum_holder m_enum_holder; 405 406 public: 407 int i; 408 409 virtual bool is_value_initialized() const 410 { 411 return m_enum_holder.is_value_initialized() && i == 0; 412 } 413 414 virtual ~non_pod_class() {} 415 }; 416 417 bool is_value_initialized(const non_pod_class& arg) 418 { 419 return arg.is_value_initialized(); 420 } 421 422 423 typedef char _2d_char_array_type[3][4]; 424 425 bool is_value_initialized(const _2d_char_array_type& arg) 426 { 427 for(unsigned i = 0; i < sizeof(_2d_char_array_type); ++i) 428 { 429 if ((*arg)[i] != 0) 430 { 431 return false; 432 } 433 } 434 return true; 435 } 436 437 typedef char _3d_char_array_type[5][6][7]; 438 439 bool is_value_initialized(const _3d_char_array_type& arg) 440 { 441 for(unsigned i = 0; i < sizeof(_3d_char_array_type); ++i) 442 { 443 if ((**arg)[i] != 0) 444 { 445 return false; 446 } 447 } 448 return true; 449 } 450 451 452 453 // Tells whether an object of a scalar type T is value-initialized. 454 template <class T> 455 bool is_value_initialized(const T& arg) 456 { 457 return arg == 0; 458 } 459 460 461 // Wraps a heap object that it has allocated by doing new T(). 462 template <class T> 463 class heap_object_wrapper 464 { 465 private: 466 T* const m_ptr; 467 468 // The following function is intentionally left unimplemented 469 // (as if deleted, "= delete", in C++0x): 470 void operator=(heap_object_wrapper); 471 472 public: 473 heap_object_wrapper() 474 : 475 m_ptr(new T()) 476 { 477 } 478 479 ~heap_object_wrapper() 480 { 481 delete m_ptr; 482 } 483 484 // The copy-constructor is intentionally left unimplemented. 485 heap_object_wrapper(const heap_object_wrapper&); 486 487 bool is_wrapped_object_value_initialized() const 488 { 489 return (m_ptr != 0) && is_value_initialized(*m_ptr); 490 } 491 }; 492 493 template <class T> 494 bool is_value_initialized(const heap_object_wrapper<T>& arg) 495 { 496 return arg.is_wrapped_object_value_initialized(); 497 } 498 499 500 // Returns zero when the specified object is value-initializated, and one otherwise. 501 // Prints a message to standard output if the value-initialization has failed. 502 template <class T> 503 unsigned failed_to_value_initialized(const T& object, const char *const object_name) 504 { 505 if ( is_value_initialized(object) ) 506 { 507 return 0u; 508 } 509 else 510 { 511 std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl; 512 return 1u; 513 } 514 } 515 516// A macro that passed both the name and the value of the specified object to 517// the function above here. 518#define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value) 519 520 521 // value_initializer initializes each of its data members by means 522 // of an empty set of parentheses, and allows checking whether 523 // each of them is indeed value-initialized, as specified by 524 // the C++ Standard ([dcl.init]). 525 // 526 // Note: its base class, int_struct, is there to try to reproduce GCC Bug 30111, 527 // "Value-initialization of POD base class doesn't initialize members", reported 528 // by Jonathan Wakely in 2006: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 529 class value_initializer: private int_struct 530 { 531 private: 532 enum_holder m_enum_holder; 533 enum_holder m_enum_holder_array[2]; 534 enum_type m_enum; 535 enum_type m_enum_array[2]; 536 bool m_bool; 537 bool m_bool_array[2]; 538 char m_char; 539 char m_char_array[2]; 540 _2d_char_array_type m_2d_char_array; 541 _3d_char_array_type m_3d_char_array; 542 unsigned char m_unsigned_char; 543 unsigned char m_unsigned_char_array[2]; 544 short m_short; 545 short m_short_array[2]; 546 int m_int; 547 int m_int_array[2]; 548 unsigned m_unsigned; 549 unsigned m_unsigned_array[2]; 550 long m_long; 551 long m_long_array[2]; 552 float m_float; 553 float m_float_array[2]; 554 double m_double; 555 double m_double_array[2]; 556 long double m_long_double; 557 long double m_long_double_array[2]; 558 void* m_void_ptr; 559 void* m_void_ptr_array[2]; 560 function_ptr_type m_function_ptr; 561 function_ptr_type m_function_ptr_array[2]; 562 function_ptr_struct m_function_ptr_struct; 563 function_ptr_struct m_function_ptr_struct_array[2]; 564 member_function_ptr_type m_member_function_ptr; 565 member_function_ptr_type m_member_function_ptr_array[2]; 566 member_function_ptr_struct m_member_function_ptr_struct; 567 member_function_ptr_struct m_member_function_ptr_struct_array[2]; 568 ptr_to_member_type m_ptr_to_member; 569 ptr_to_member_type m_ptr_to_member_array[2]; 570 ptr_to_member_struct m_ptr_to_member_struct; 571 ptr_to_member_struct m_ptr_to_member_struct_array[2]; 572 bit_field_struct m_bit_field_struct; 573 bit_field_struct m_bit_field_struct_array[2]; 574 int_struct m_int_struct; 575 int_struct m_int_struct_array[2]; 576 int_struct m_int_struct_holder; 577 int_struct m_int_struct_holder_array[2]; 578 pod_struct m_pod_struct; 579 pod_struct m_pod_struct_array[2]; 580 derived_pod_struct m_derived_pod_struct; 581 derived_pod_struct m_derived_pod_struct_array[2]; 582 derived_struct m_derived_struct; 583 derived_struct m_derived_struct_array[2]; 584 derived_int_struct m_derived_int_struct; 585 derived_int_struct m_derived_int_struct_array[2]; 586 private_int_holder m_private_int_holder; 587 private_int_holder m_private_int_holder_array[2]; 588 char_array_struct m_char_array_struct; 589 char_array_struct m_char_array_struct_array[2]; 590 private_int_array_pair m_private_int_array_pair; 591 private_int_array_pair m_private_int_array_pair_array[2]; 592 enum_holder_and_int m_enum_holder_and_int; 593 enum_holder_and_int m_enum_holder_and_int_array[2]; 594 private_and_protected_int m_private_and_protected_int; 595 private_and_protected_int m_private_and_protected_int_array[2]; 596 user_defined_copy_constructor_holder_and_int m_user_defined_copy_constructor_holder_and_int; 597 user_defined_copy_constructor_holder_and_int m_user_defined_copy_constructor_holder_and_int_array[2]; 598 user_defined_destructor_holder m_user_defined_destructor_holder; 599 user_defined_destructor_holder m_user_defined_destructor_holder_array[2]; 600 virtual_destructor_holder m_virtual_destructor_holder; 601 virtual_destructor_holder m_virtual_destructor_holder_array[2]; 602 non_pod_class m_non_pod; 603 non_pod_class m_non_pod_array[2]; 604 pod_struct_and_int_union m_pod_struct_and_int_union; 605 pod_struct_and_int_union m_pod_struct_and_int_union_array[2]; 606 int_and_pod_struct_union m_int_and_pod_struct_union; 607 int_and_pod_struct_union m_int_and_pod_struct_union_array[2]; 608 609 public: 610 // Default constructor. Tries to value-initialize its base subobject and all 611 // of its data.members. 612 value_initializer() 613 : 614 // Note: CodeGear/Borland may produce a warning, W8039, for each data member 615 // whose type is an array type, saying "Constructor initializer list ignored". 616 // If it does, it probably won't value-initialize those arrays, as reported 617 // by me (Niels Dekker, LKEB) in 2010, report 83751, "Value-initialization: 618 // arrays should have each element value-initialized", 619 // http://qc.embarcadero.com/wc/qcmain.aspx?d=83751 620 // On the other hand, Microsoft Visual C++ may produce warnings of type C4351, 621 // saying "new behavior: elements of array '...' will be default initialized", 622 // which is actually the right behavior! 623 int_struct(), 624 m_enum_holder(), 625 m_enum_holder_array(), 626 m_enum(), 627 m_enum_array(), 628 m_bool(), 629 m_bool_array(), 630 m_char(), 631 m_char_array(), 632 m_2d_char_array(), 633 m_3d_char_array(), 634 m_unsigned_char(), 635 m_unsigned_char_array(), 636 m_short(), 637 m_short_array(), 638 m_int(), 639 m_int_array(), 640 m_unsigned(), 641 m_unsigned_array(), 642 m_long(), 643 m_long_array(), 644 m_float(), 645 m_float_array(), 646 m_double(), 647 m_double_array(), 648 m_long_double(), 649 m_long_double_array(), 650 m_void_ptr(), 651 m_void_ptr_array(), 652 m_function_ptr(), 653 m_function_ptr_array(), 654 m_function_ptr_struct(), 655 m_function_ptr_struct_array(), 656 m_member_function_ptr(), 657 m_member_function_ptr_array(), 658 m_member_function_ptr_struct(), 659 m_member_function_ptr_struct_array(), 660 m_ptr_to_member(), 661 m_ptr_to_member_array(), 662 m_ptr_to_member_struct(), 663 m_ptr_to_member_struct_array(), 664 m_bit_field_struct(), 665 m_bit_field_struct_array(), 666 m_int_struct(), 667 m_int_struct_array(), 668 m_int_struct_holder(), 669 m_int_struct_holder_array(), 670 m_pod_struct(), 671 m_pod_struct_array(), 672 m_derived_pod_struct(), 673 m_derived_pod_struct_array(), 674 m_derived_struct(), 675 m_derived_struct_array(), 676 m_derived_int_struct(), 677 m_derived_int_struct_array(), 678 m_private_int_holder(), 679 m_private_int_holder_array(), 680 m_char_array_struct(), 681 m_char_array_struct_array(), 682 m_private_int_array_pair(), 683 m_private_int_array_pair_array(), 684 m_enum_holder_and_int(), 685 m_enum_holder_and_int_array(), 686 m_private_and_protected_int(), 687 m_private_and_protected_int_array(), 688 m_user_defined_copy_constructor_holder_and_int(), 689 m_user_defined_copy_constructor_holder_and_int_array(), 690 m_user_defined_destructor_holder(), 691 m_user_defined_destructor_holder_array(), 692 m_virtual_destructor_holder(), 693 m_virtual_destructor_holder_array(), 694 m_non_pod(), 695 m_non_pod_array(), 696 m_pod_struct_and_int_union(), 697 m_pod_struct_and_int_union_array(), 698 m_int_and_pod_struct_union(), 699 m_int_and_pod_struct_union_array() 700 { 701 } 702 703 // Returns the number of failures. 704 unsigned check_value_initialization_of_subobjects() const 705 { 706 const unsigned num_failures = 707 FAILED_TO_VALUE_INITIALIZE(int_struct::data) + 708 FAILED_TO_VALUE_INITIALIZE(m_enum_holder) + 709 FAILED_TO_VALUE_INITIALIZE(m_enum_holder_array[0]) + 710 FAILED_TO_VALUE_INITIALIZE(m_enum_holder_array[1]) + 711 FAILED_TO_VALUE_INITIALIZE(m_enum) + 712 FAILED_TO_VALUE_INITIALIZE(m_enum_array[0]) + 713 FAILED_TO_VALUE_INITIALIZE(m_enum_array[1]) + 714 FAILED_TO_VALUE_INITIALIZE(m_bool) + 715 FAILED_TO_VALUE_INITIALIZE(m_bool_array[0]) + 716 FAILED_TO_VALUE_INITIALIZE(m_bool_array[1]) + 717 FAILED_TO_VALUE_INITIALIZE(m_char) + 718 FAILED_TO_VALUE_INITIALIZE(m_char_array[0]) + 719 FAILED_TO_VALUE_INITIALIZE(m_char_array[1]) + 720 FAILED_TO_VALUE_INITIALIZE(m_2d_char_array) + 721 FAILED_TO_VALUE_INITIALIZE(m_3d_char_array) + 722 FAILED_TO_VALUE_INITIALIZE(m_unsigned_char) + 723 FAILED_TO_VALUE_INITIALIZE(m_unsigned_char_array[0]) + 724 FAILED_TO_VALUE_INITIALIZE(m_unsigned_char_array[1]) + 725 FAILED_TO_VALUE_INITIALIZE(m_short) + 726 FAILED_TO_VALUE_INITIALIZE(m_short_array[0]) + 727 FAILED_TO_VALUE_INITIALIZE(m_short_array[1]) + 728 FAILED_TO_VALUE_INITIALIZE(m_int) + 729 FAILED_TO_VALUE_INITIALIZE(m_int_array[0]) + 730 FAILED_TO_VALUE_INITIALIZE(m_int_array[1]) + 731 FAILED_TO_VALUE_INITIALIZE(m_unsigned) + 732 FAILED_TO_VALUE_INITIALIZE(m_unsigned_array[0]) + 733 FAILED_TO_VALUE_INITIALIZE(m_unsigned_array[1]) + 734 FAILED_TO_VALUE_INITIALIZE(m_long) + 735 FAILED_TO_VALUE_INITIALIZE(m_long_array[0]) + 736 FAILED_TO_VALUE_INITIALIZE(m_long_array[1]) + 737 FAILED_TO_VALUE_INITIALIZE(m_float) + 738 FAILED_TO_VALUE_INITIALIZE(m_float_array[0]) + 739 FAILED_TO_VALUE_INITIALIZE(m_float_array[1]) + 740 FAILED_TO_VALUE_INITIALIZE(m_double) + 741 FAILED_TO_VALUE_INITIALIZE(m_double_array[0]) + 742 FAILED_TO_VALUE_INITIALIZE(m_double_array[1]) + 743 FAILED_TO_VALUE_INITIALIZE(m_long_double) + 744 FAILED_TO_VALUE_INITIALIZE(m_long_double_array[0]) + 745 FAILED_TO_VALUE_INITIALIZE(m_long_double_array[1]) + 746 FAILED_TO_VALUE_INITIALIZE(m_void_ptr) + 747 FAILED_TO_VALUE_INITIALIZE(m_void_ptr_array[0]) + 748 FAILED_TO_VALUE_INITIALIZE(m_void_ptr_array[1]) + 749 FAILED_TO_VALUE_INITIALIZE(m_function_ptr) + 750 FAILED_TO_VALUE_INITIALIZE(m_function_ptr_array[0]) + 751 FAILED_TO_VALUE_INITIALIZE(m_function_ptr_array[1]) + 752 FAILED_TO_VALUE_INITIALIZE(m_function_ptr_struct) + 753 FAILED_TO_VALUE_INITIALIZE(m_function_ptr_struct_array[0]) + 754 FAILED_TO_VALUE_INITIALIZE(m_function_ptr_struct_array[1]) + 755 FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr) + 756 FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_array[0]) + 757 FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_array[1]) + 758 FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_struct) + 759 FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_struct_array[0]) + 760 FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_struct_array[1]) + 761 FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member) + 762 FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_array[0]) + 763 FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_array[1]) + 764 FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_struct) + 765 FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_struct_array[0]) + 766 FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_struct_array[1]) + 767 FAILED_TO_VALUE_INITIALIZE(m_bit_field_struct) + 768 FAILED_TO_VALUE_INITIALIZE(m_bit_field_struct_array[0]) + 769 FAILED_TO_VALUE_INITIALIZE(m_bit_field_struct_array[1]) + 770 FAILED_TO_VALUE_INITIALIZE(m_int_struct) + 771 FAILED_TO_VALUE_INITIALIZE(m_int_struct_array[0]) + 772 FAILED_TO_VALUE_INITIALIZE(m_int_struct_array[1]) + 773 FAILED_TO_VALUE_INITIALIZE(m_int_struct_holder) + 774 FAILED_TO_VALUE_INITIALIZE(m_int_struct_holder_array[0]) + 775 FAILED_TO_VALUE_INITIALIZE(m_int_struct_holder_array[1]) + 776 FAILED_TO_VALUE_INITIALIZE(m_pod_struct) + 777 FAILED_TO_VALUE_INITIALIZE(m_pod_struct_array[0]) + 778 FAILED_TO_VALUE_INITIALIZE(m_pod_struct_array[1]) + 779 FAILED_TO_VALUE_INITIALIZE(m_derived_pod_struct) + 780 FAILED_TO_VALUE_INITIALIZE(m_derived_pod_struct_array[0]) + 781 FAILED_TO_VALUE_INITIALIZE(m_derived_pod_struct_array[1]) + 782 FAILED_TO_VALUE_INITIALIZE(m_derived_struct) + 783 FAILED_TO_VALUE_INITIALIZE(m_derived_struct_array[0]) + 784 FAILED_TO_VALUE_INITIALIZE(m_derived_struct_array[1]) + 785 FAILED_TO_VALUE_INITIALIZE(m_derived_int_struct) + 786 FAILED_TO_VALUE_INITIALIZE(m_derived_int_struct_array[0]) + 787 FAILED_TO_VALUE_INITIALIZE(m_derived_int_struct_array[1]) + 788 FAILED_TO_VALUE_INITIALIZE(m_private_int_holder) + 789 FAILED_TO_VALUE_INITIALIZE(m_private_int_holder_array[0]) + 790 FAILED_TO_VALUE_INITIALIZE(m_private_int_holder_array[1]) + 791 FAILED_TO_VALUE_INITIALIZE(m_char_array_struct) + 792 FAILED_TO_VALUE_INITIALIZE(m_char_array_struct_array[0]) + 793 FAILED_TO_VALUE_INITIALIZE(m_char_array_struct_array[1]) + 794 FAILED_TO_VALUE_INITIALIZE(m_private_int_array_pair) + 795 FAILED_TO_VALUE_INITIALIZE(m_private_int_array_pair_array[0]) + 796 FAILED_TO_VALUE_INITIALIZE(m_private_int_array_pair_array[1]) + 797 FAILED_TO_VALUE_INITIALIZE(m_enum_holder_and_int) + 798 FAILED_TO_VALUE_INITIALIZE(m_enum_holder_and_int_array[0]) + 799 FAILED_TO_VALUE_INITIALIZE(m_enum_holder_and_int_array[1]) + 800 FAILED_TO_VALUE_INITIALIZE(m_private_and_protected_int) + 801 FAILED_TO_VALUE_INITIALIZE(m_private_and_protected_int_array[0]) + 802 FAILED_TO_VALUE_INITIALIZE(m_private_and_protected_int_array[1]) + 803 FAILED_TO_VALUE_INITIALIZE(m_user_defined_copy_constructor_holder_and_int) + 804 FAILED_TO_VALUE_INITIALIZE(m_user_defined_copy_constructor_holder_and_int_array[0]) + 805 FAILED_TO_VALUE_INITIALIZE(m_user_defined_copy_constructor_holder_and_int_array[1]) + 806 FAILED_TO_VALUE_INITIALIZE(m_user_defined_destructor_holder) + 807 FAILED_TO_VALUE_INITIALIZE(m_user_defined_destructor_holder_array[0]) + 808 FAILED_TO_VALUE_INITIALIZE(m_user_defined_destructor_holder_array[1]) + 809 FAILED_TO_VALUE_INITIALIZE(m_virtual_destructor_holder) + 810 FAILED_TO_VALUE_INITIALIZE(m_virtual_destructor_holder_array[0]) + 811 FAILED_TO_VALUE_INITIALIZE(m_virtual_destructor_holder_array[1]) + 812 FAILED_TO_VALUE_INITIALIZE(m_non_pod) + 813 FAILED_TO_VALUE_INITIALIZE(m_non_pod_array[0]) + 814 FAILED_TO_VALUE_INITIALIZE(m_non_pod_array[1]) + 815 FAILED_TO_VALUE_INITIALIZE(m_pod_struct_and_int_union) + 816 FAILED_TO_VALUE_INITIALIZE(m_pod_struct_and_int_union_array[0]) + 817 FAILED_TO_VALUE_INITIALIZE(m_pod_struct_and_int_union_array[1]) + 818 FAILED_TO_VALUE_INITIALIZE(m_int_and_pod_struct_union) + 819 FAILED_TO_VALUE_INITIALIZE(m_int_and_pod_struct_union_array[0]) + 820 FAILED_TO_VALUE_INITIALIZE(m_int_and_pod_struct_union_array[1]); 821 return num_failures; 822 } 823 }; 824 825 // Checks value-initialization of a number of small temporary objects. 826 // Returns the number of failures. 827 unsigned check_value_initialization_of_temporaries() 828 { 829 typedef long double long_double_type; 830 typedef unsigned char unsigned_char_type; 831 typedef void* void_ptr_type; 832 833 const unsigned num_failures = 834 FAILED_TO_VALUE_INITIALIZE(enum_holder()) + 835 FAILED_TO_VALUE_INITIALIZE(enum_type()) + 836 FAILED_TO_VALUE_INITIALIZE(bool()) + 837 FAILED_TO_VALUE_INITIALIZE(char()) + 838 FAILED_TO_VALUE_INITIALIZE(unsigned_char_type()) + 839 FAILED_TO_VALUE_INITIALIZE(short()) + 840 FAILED_TO_VALUE_INITIALIZE(int()) + 841 FAILED_TO_VALUE_INITIALIZE(unsigned()) + 842 FAILED_TO_VALUE_INITIALIZE(long()) + 843 FAILED_TO_VALUE_INITIALIZE(float()) + 844 FAILED_TO_VALUE_INITIALIZE(double()) + 845 FAILED_TO_VALUE_INITIALIZE(long_double_type()) + 846 FAILED_TO_VALUE_INITIALIZE(void_ptr_type()) + 847 FAILED_TO_VALUE_INITIALIZE(bit_field_struct()) + 848 FAILED_TO_VALUE_INITIALIZE(function_ptr_type()) + 849 FAILED_TO_VALUE_INITIALIZE(function_ptr_struct()) + 850 FAILED_TO_VALUE_INITIALIZE(member_function_ptr_type()) + 851 FAILED_TO_VALUE_INITIALIZE(member_function_ptr_struct()) + 852 FAILED_TO_VALUE_INITIALIZE(ptr_to_member_type()) + 853 FAILED_TO_VALUE_INITIALIZE(ptr_to_member_struct()) + 854 FAILED_TO_VALUE_INITIALIZE(int_struct()) + 855 FAILED_TO_VALUE_INITIALIZE(int_struct_holder()) + 856 FAILED_TO_VALUE_INITIALIZE(pod_struct()) + 857 FAILED_TO_VALUE_INITIALIZE(derived_pod_struct()) + 858 FAILED_TO_VALUE_INITIALIZE(derived_struct()) + 859 FAILED_TO_VALUE_INITIALIZE(derived_int_struct()) + 860 FAILED_TO_VALUE_INITIALIZE(private_int_holder()) + 861 FAILED_TO_VALUE_INITIALIZE(char_array_struct()) + 862 FAILED_TO_VALUE_INITIALIZE(private_int_array_pair()) + 863 // IBM's XL V10.1.0.0 may fail to value-initialize a temporary of a non-POD 864 // type like enum_holder_and_int, virtual_destructor_holder, or non_pod_class, 865 // as appeared at the Boost Config/trunk regression page in April 2010. 866 // Michael Wong (IBM Canada Ltd) confirmed the issue to me (Niels Dekker, LKEB), 867 // and gave it high priority. 868 FAILED_TO_VALUE_INITIALIZE(enum_holder_and_int()) + 869 FAILED_TO_VALUE_INITIALIZE(private_and_protected_int()) + 870 FAILED_TO_VALUE_INITIALIZE(user_defined_copy_constructor_holder_and_int()) + 871 // The following line, doing user_defined_destructor_holder(), causes 872 // a compilation error on Embarcadero 2010 (Borland/CodeGear 6.21), 873 // as reported by me (Niels Dekker, LKEB) in 2010, bug report 83851, 874 // "Value-initialized temporary triggers internal backend error C1798", 875 // http://qc.embarcadero.com/wc/qcmain.aspx?d=83851 876 FAILED_TO_VALUE_INITIALIZE(user_defined_destructor_holder()) + 877 FAILED_TO_VALUE_INITIALIZE(virtual_destructor_holder()) + 878 FAILED_TO_VALUE_INITIALIZE(non_pod_class()) + 879 FAILED_TO_VALUE_INITIALIZE(pod_struct_and_int_union()) + 880 FAILED_TO_VALUE_INITIALIZE(int_and_pod_struct_union()); 881 return num_failures; 882 } 883 884 // Checks value-initialization of small heap objects. 885 // Returns the number of failures. 886 unsigned check_value_initialization_of_heap_objects() 887 { 888 const unsigned num_failures = 889 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<enum_holder>() ) + 890 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<enum_type>() ) + 891 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<bool>() ) + 892 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<char>() ) + 893 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<unsigned char>() ) + 894 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<short>() ) + 895 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int>() ) + 896 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<unsigned>() ) + 897 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<long>() ) + 898 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<float>() ) + 899 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<double>() ) + 900 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<long double>() ) + 901 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<void*>() ) + 902 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<function_ptr_type>() ) + 903 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<function_ptr_struct>() ) + 904 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<member_function_ptr_type>() ) + 905 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<member_function_ptr_struct>() ) + 906 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<ptr_to_member_type>() ) + 907 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<ptr_to_member_struct>() ) + 908 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<bit_field_struct>() ) + 909 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int_struct>() ) + 910 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int_struct>() ) + 911 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<pod_struct>() ) + 912 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<derived_pod_struct>() ) + 913 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<derived_struct>() ) + 914 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<derived_int_struct>() ) + 915 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<char_array_struct>() ) + 916 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<private_int_holder>() ) + 917 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<private_int_array_pair>() ) + 918 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<enum_holder_and_int>() ) + 919 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<private_and_protected_int>() ) + 920 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<user_defined_copy_constructor_holder_and_int>() ) + 921 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<user_defined_destructor_holder>() ) + 922 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<virtual_destructor_holder>() ) + 923 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<non_pod_class>() ) + 924 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<pod_struct_and_int_union>() ) + 925 FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int_and_pod_struct_union>() ); 926 return num_failures; 927 } 928 929 // Equivalent to the dirty_stack() function from GCC Bug 33916, 930 // "Default constructor fails to initialize array members", reported in 2007 by 931 // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 932 void dirty_stack() 933 { 934 unsigned char array_on_stack[sizeof(value_initializer) + 256]; 935 for (unsigned i = 0; i < sizeof(array_on_stack); ++i) 936 { 937 array_on_stack[i] = 0x11; 938 } 939 } 940 941 942 // Checks value-initialization of the subobjects of a temporary object, 943 // an object on the stack, an object on the heap; furthermore it checks 944 // value-initialization of a number of smaller temporary objects and 945 // heap objects. 946 int test() 947 { 948 unsigned total_num_failures = 0; 949 950 dirty_stack(); 951 const unsigned num_failures_of_subobjects_of_a_temporary = 952 value_initializer().check_value_initialization_of_subobjects(); 953 954 total_num_failures += num_failures_of_subobjects_of_a_temporary; 955 if ( total_num_failures > 0 ) 956 { 957 std::cout << "- Number of subobject initialization failures of a temporary: " 958 << num_failures_of_subobjects_of_a_temporary << std::endl; 959 } 960 dirty_stack(); 961 value_initializer object_on_stack; 962 const unsigned num_failures_of_subobjects_on_stack = 963 object_on_stack.check_value_initialization_of_subobjects(); 964 965 total_num_failures += num_failures_of_subobjects_on_stack; 966 if ( total_num_failures > 0 ) 967 { 968 std::cout << "- Number of subobject initialization failures on the stack: " 969 << num_failures_of_subobjects_on_stack << std::endl; 970 } 971 const value_initializer* const ptr = new value_initializer(); 972 const unsigned num_failures_of_subobjects_on_heap = ptr->check_value_initialization_of_subobjects(); 973 delete ptr; 974 975 total_num_failures += num_failures_of_subobjects_on_heap; 976 if ( total_num_failures > 0 ) 977 { 978 std::cout << "- Number of subobject initialization failures on the heap: " 979 << num_failures_of_subobjects_on_heap << std::endl; 980 } 981 982 dirty_stack(); 983 const unsigned num_failures_of_temporaries = check_value_initialization_of_temporaries(); 984 985 total_num_failures += num_failures_of_temporaries; 986 if ( total_num_failures > 0 ) 987 { 988 std::cout << "- Number of initialization failures of temporary objects: " 989 << num_failures_of_temporaries << std::endl; 990 } 991 992 const unsigned num_failures_of_heap_objects = check_value_initialization_of_heap_objects(); 993 994 total_num_failures += num_failures_of_heap_objects; 995 if ( total_num_failures > 0 ) 996 { 997 std::cout << "- Number of failures of heap objects: " 998 << num_failures_of_heap_objects << std::endl; 999 } 1000 1001 if ( total_num_failures > 0 ) 1002 { 1003 std::cout << "-- Total number of initialization failures (" 1004 << num_failures_of_subobjects_of_a_temporary << '+' 1005 << num_failures_of_subobjects_on_stack << '+' 1006 << num_failures_of_subobjects_on_heap << '+' 1007 << num_failures_of_temporaries << '+' 1008 << num_failures_of_heap_objects << "): " 1009 << total_num_failures 1010 << "\nDetected by boost_no_complete_value_initialization::test() revision 32." 1011 << std::endl; 1012 } 1013 return static_cast<int>(total_num_failures); 1014 } 1015 1016} // End of namespace. 1017