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
18namespace
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
127int 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

source code of boost/libs/utility/value_init_workaround_test.cpp