• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
is_value_initialized(const derived_struct & arg)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;
~virtual_destructor_holder()44     virtual ~virtual_destructor_holder()
45     {
46     }
47   };
48 
is_value_initialized(const virtual_destructor_holder & arg)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 
is_value_initialized(const private_int_array_pair & arg)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   struct int_pair_struct
79   {
80     int first;
81     int second;
82   };
83 
84   typedef int int_pair_struct::*ptr_to_member_type;
85 
86   struct ptr_to_member_struct
87   {
88     ptr_to_member_type data;
89   };
90 
is_value_initialized(const ptr_to_member_struct & arg)91   bool is_value_initialized(const ptr_to_member_struct& arg)
92   {
93     return arg.data == 0;
94   }
95 
96   template <typename T>
is_value_initialized(const T (& arg)[2])97   bool is_value_initialized(const T(& arg)[2])
98   {
99     return
100       is_value_initialized(arg[0]) &&
101       is_value_initialized(arg[1]);
102   }
103 
104   template <typename T>
is_value_initialized(const boost::value_initialized<T> & arg)105   bool is_value_initialized(const boost::value_initialized<T>& arg)
106   {
107     return is_value_initialized(arg.data());
108   }
109 
110   // Returns zero when the specified object is value-initializated, and one otherwise.
111   // Prints a message to standard output if the value-initialization has failed.
112   template <class T>
failed_to_value_initialized(const T & object,const char * const object_name)113   unsigned failed_to_value_initialized(const T& object, const char *const object_name)
114   {
115     if ( is_value_initialized(object) )
116     {
117       return 0u;
118     }
119     else
120     {
121       std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl;
122       return 1u;
123     }
124   }
125 
126 // A macro that passed both the name and the value of the specified object to
127 // the function above here.
128 #define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value)
129 
130   // Equivalent to the dirty_stack() function from GCC Bug 33916,
131   // "Default constructor fails to initialize array members", reported in 2007 by
132   // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
dirty_stack()133   void dirty_stack()
134   {
135     unsigned char array_on_stack[4096];
136     for (unsigned i = 0; i < sizeof(array_on_stack); ++i)
137     {
138       array_on_stack[i] = 0x11;
139     }
140   }
141 
142 }
143 
144 
main()145 int main()
146 {
147   dirty_stack();
148 
149   // TODO More types may be added later.
150   const unsigned num_failures =
151     FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<derived_struct>()) +
152     FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<virtual_destructor_holder[2]>()) +
153     FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<private_int_array_pair>()) +
154     FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<ptr_to_member_struct>());
155 
156 #ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
157   // One or more failures are expected.
158   return num_failures > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
159 #else
160   // No failures are expected.
161   return num_failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
162 #endif
163 }
164