• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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