value_init_workaround_test.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright 2010, Niels Dekker.
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Test program for the boost::value_initialized<T> workaround.
  8. //
  9. // 17 June 2010 (Created) Niels Dekker
  10. // Switch the workaround off, before inluding "value_init.hpp".
  11. #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0
  12. #include <boost/utility/value_init.hpp>
  13. #include <iostream> // For cout.
  14. #include <cstdlib> // For EXIT_SUCCESS and EXIT_FAILURE.
  15. namespace
  16. {
  17. struct empty_struct
  18. {
  19. };
  20. // A POD aggregate struct derived from an empty struct.
  21. // Similar to struct Foo1 from Microsoft Visual C++ bug report 484295,
  22. // "VC++ does not value-initialize members of derived classes without
  23. // user-declared constructor", reported in 2009 by Sylvester Hesp:
  24. // https://connect.microsoft.com/VisualStudio/feedback/details/484295
  25. struct derived_struct: empty_struct
  26. {
  27. int data;
  28. };
  29. bool is_value_initialized(const derived_struct& arg)
  30. {
  31. return arg.data == 0;
  32. }
  33. class virtual_destructor_holder
  34. {
  35. public:
  36. int i;
  37. virtual ~virtual_destructor_holder()
  38. {
  39. }
  40. };
  41. bool is_value_initialized(const virtual_destructor_holder& arg)
  42. {
  43. return arg.i == 0;
  44. }
  45. // Equivalent to the Stats class from GCC Bug 33916,
  46. // "Default constructor fails to initialize array members", reported in 2007 by
  47. // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
  48. // and fixed for GCC 4.2.4.
  49. class private_int_array_pair
  50. {
  51. friend bool is_value_initialized(const private_int_array_pair& arg);
  52. private:
  53. int first[12];
  54. int second[12];
  55. };
  56. bool is_value_initialized(const private_int_array_pair& arg)
  57. {
  58. for ( unsigned i = 0; i < 12; ++i)
  59. {
  60. if ( (arg.first[i] != 0) || (arg.second[i] != 0) )
  61. {
  62. return false;
  63. }
  64. }
  65. return true;
  66. }
  67. struct int_pair_struct
  68. {
  69. int first;
  70. int second;
  71. };
  72. typedef int int_pair_struct::*ptr_to_member_type;
  73. struct ptr_to_member_struct
  74. {
  75. ptr_to_member_type data;
  76. };
  77. bool is_value_initialized(const ptr_to_member_struct& arg)
  78. {
  79. return arg.data == 0;
  80. }
  81. template <typename T>
  82. bool is_value_initialized(const T(& arg)[2])
  83. {
  84. return
  85. is_value_initialized(arg[0]) &&
  86. is_value_initialized(arg[1]);
  87. }
  88. template <typename T>
  89. bool is_value_initialized(const boost::value_initialized<T>& arg)
  90. {
  91. return is_value_initialized(arg.data());
  92. }
  93. // Returns zero when the specified object is value-initializated, and one otherwise.
  94. // Prints a message to standard output if the value-initialization has failed.
  95. template <class T>
  96. unsigned failed_to_value_initialized(const T& object, const char *const object_name)
  97. {
  98. if ( is_value_initialized(object) )
  99. {
  100. return 0u;
  101. }
  102. else
  103. {
  104. std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl;
  105. return 1u;
  106. }
  107. }
  108. // A macro that passed both the name and the value of the specified object to
  109. // the function above here.
  110. #define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value)
  111. // Equivalent to the dirty_stack() function from GCC Bug 33916,
  112. // "Default constructor fails to initialize array members", reported in 2007 by
  113. // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
  114. void dirty_stack()
  115. {
  116. unsigned char array_on_stack[4096];
  117. for (unsigned i = 0; i < sizeof(array_on_stack); ++i)
  118. {
  119. array_on_stack[i] = 0x11;
  120. }
  121. }
  122. }
  123. int main()
  124. {
  125. dirty_stack();
  126. // TODO More types may be added later.
  127. const unsigned num_failures =
  128. FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<derived_struct>()) +
  129. FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<virtual_destructor_holder[2]>()) +
  130. FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<private_int_array_pair>()) +
  131. FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<ptr_to_member_struct>());
  132. #ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
  133. // One or more failures are expected.
  134. return num_failures > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
  135. #else
  136. // No failures are expected.
  137. return num_failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
  138. #endif
  139. }