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