boost_no_com_value_init.ipp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  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. // See http://www.boost.org/libs/config for most recent version.
  6. // MACRO: BOOST_NO_COMPLETE_VALUE_INITIALIZATION
  7. // TITLE: No complete value-initialization
  8. // DESCRIPTION: The C++ compiler does not to have implemented value-initialization completely.
  9. // See also boost/libs/utility/value_init.htm#compiler_issues
  10. #include <iostream>
  11. // This test checks various forms of value-initialization:
  12. // - doing subobject initialization inside a constructor
  13. // - creating a temporary object by T()
  14. // - creating a heap object by doing new T()
  15. // It checks various DefaultConstructible types, including fundamental types,
  16. // enum, union, pointer types, array types, POD and non-POD class types. For
  17. // each type of object, a helper function is_value_initialized(const T&) tells
  18. // whether the object is value-initialized.
  19. //
  20. // Note: It appeared insufficient to just check a single POD and a single
  21. // non-POD class type, because some compilers correctly value-initialize some
  22. // POD and some non-POD objects, while failing to value-initialize others.
  23. //
  24. // The test returns the number of encountered value-initialization failures.
  25. namespace boost_no_complete_value_initialization
  26. {
  27. enum enum_type { negative_number = -1, magic_number = 42 };
  28. class incomplete_class;
  29. typedef int (*function_ptr_type)(int);
  30. typedef int (incomplete_class::*member_function_ptr_type)(int);
  31. // A POD struct.
  32. struct pod_struct
  33. {
  34. enum_type e;
  35. bool b;
  36. char c;
  37. unsigned char uc;
  38. short s;
  39. int i;
  40. unsigned u;
  41. long l;
  42. float f;
  43. double d;
  44. long double ld;
  45. void* p;
  46. };
  47. bool is_value_initialized(const pod_struct& arg)
  48. {
  49. return
  50. arg.b == 0 &&
  51. arg.e == 0 &&
  52. arg.c == 0 &&
  53. arg.uc == 0 &&
  54. arg.s == 0 &&
  55. arg.i == 0 &&
  56. arg.u == 0 &&
  57. arg.l == 0 &&
  58. arg.f == 0 &&
  59. arg.d == 0 &&
  60. arg.p == 0;
  61. }
  62. // A POD struct derived from another POD struct.
  63. struct derived_pod_struct: pod_struct
  64. {
  65. int derived_data;
  66. };
  67. bool is_value_initialized(const derived_pod_struct& arg)
  68. {
  69. const pod_struct& base_subobject = arg;
  70. return arg.derived_data == 0 && is_value_initialized(base_subobject);
  71. }
  72. struct empty_struct
  73. {
  74. };
  75. // A POD aggregate struct derived from an empty struct.
  76. // Similar to struct Foo1 from Microsoft Visual C++ bug report 484295,
  77. // "VC++ does not value-initialize members of derived classes without
  78. // user-declared constructor", reported in 2009 by Sylvester Hesp:
  79. // https://connect.microsoft.com/VisualStudio/feedback/details/484295
  80. struct derived_struct: empty_struct
  81. {
  82. int data;
  83. };
  84. bool is_value_initialized(const derived_struct& arg)
  85. {
  86. return arg.data == 0;
  87. }
  88. // A struct, having a bit-field.
  89. struct bit_field_struct
  90. {
  91. bool b : 1;
  92. char c : 7;
  93. unsigned u: 8 * sizeof(unsigned) - 1;
  94. };
  95. bool is_value_initialized(const bit_field_struct& arg)
  96. {
  97. return arg.b == false && arg.c == '\0'&& arg.u == 0U;
  98. }
  99. // A struct, having a function pointer.
  100. struct function_ptr_struct
  101. {
  102. function_ptr_type data;
  103. };
  104. bool is_value_initialized(const function_ptr_struct& arg)
  105. {
  106. return arg.data == 0;
  107. }
  108. // A struct, having a member function pointer.
  109. struct member_function_ptr_struct
  110. {
  111. member_function_ptr_type data;
  112. };
  113. bool is_value_initialized(const member_function_ptr_struct& arg)
  114. {
  115. return arg.data == 0;
  116. }
  117. struct int_pair_struct
  118. {
  119. int first;
  120. int second;
  121. };
  122. typedef int int_pair_struct::*ptr_to_member_type;
  123. struct ptr_to_member_struct
  124. {
  125. ptr_to_member_type data;
  126. };
  127. bool is_value_initialized(const ptr_to_member_struct& arg)
  128. {
  129. return arg.data == 0;
  130. }
  131. // A struct, having an int. Equivalent to the struct TData, from CodeGear bug
  132. // report 51854, "Value-initialization: POD struct should be zero-initialized",
  133. // reported by me (Niels Dekker, LKEB) in 2007:
  134. // http://qc.embarcadero.com/wc/qcmain.aspx?d=51854
  135. struct int_struct
  136. {
  137. int data;
  138. };
  139. bool is_value_initialized(const int_struct& arg)
  140. {
  141. return arg.data == 0;
  142. }
  143. // A struct, having an int_struct.
  144. struct int_struct_holder
  145. {
  146. int_struct data;
  147. };
  148. bool is_value_initialized(const int_struct_holder& arg)
  149. {
  150. return is_value_initialized(arg.data);
  151. }
  152. // A struct derived from int_struct.
  153. struct derived_int_struct: int_struct
  154. {
  155. };
  156. bool is_value_initialized(const derived_int_struct& arg)
  157. {
  158. return arg.data == 0;
  159. }
  160. struct char_array_struct
  161. {
  162. char data[42];
  163. };
  164. bool is_value_initialized(const char_array_struct& arg)
  165. {
  166. for ( unsigned i = 0; i < sizeof(arg.data); ++i)
  167. {
  168. if ( arg.data[i] != 0 )
  169. {
  170. return false;
  171. }
  172. }
  173. return true;
  174. }
  175. class private_int_holder
  176. {
  177. private:
  178. int m_data;
  179. friend bool is_value_initialized(const private_int_holder& arg)
  180. {
  181. return arg.m_data == 0;
  182. }
  183. };
  184. // Equivalent to the Stats class from GCC Bug 33916,
  185. // "Default constructor fails to initialize array members", reported in 2007 by
  186. // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
  187. class private_int_array_pair
  188. {
  189. friend bool is_value_initialized(const private_int_array_pair& arg);
  190. private:
  191. int first[12];
  192. int second[12];
  193. };
  194. bool is_value_initialized(const private_int_array_pair& arg)
  195. {
  196. for ( unsigned i = 0; i < 12; ++i)
  197. {
  198. if ( (arg.first[i] != 0) || (arg.second[i] != 0) )
  199. {
  200. return false;
  201. }
  202. }
  203. return true;
  204. }
  205. union pod_struct_and_int_union
  206. {
  207. pod_struct first;
  208. int second;
  209. };
  210. bool is_value_initialized(const pod_struct_and_int_union& arg)
  211. {
  212. // When a union is zero-initialized, its first non-static
  213. // named data member is zero-initialized ([dcl.init]).
  214. return is_value_initialized(arg.first);
  215. }
  216. union int_and_pod_struct_union
  217. {
  218. int first;
  219. pod_struct second;
  220. };
  221. bool is_value_initialized(const int_and_pod_struct_union& arg)
  222. {
  223. return arg.first == 0;
  224. }
  225. // A class that holds a "magic" enum value.
  226. // Note: This is not a POD class, because it has a user-defined
  227. // default constructor.
  228. class enum_holder
  229. {
  230. enum_type m_enum;
  231. public:
  232. enum_holder()
  233. :
  234. m_enum(magic_number)
  235. {
  236. }
  237. bool is_value_initialized() const
  238. {
  239. return m_enum == magic_number;
  240. }
  241. };
  242. bool is_value_initialized(const enum_holder& arg)
  243. {
  244. return arg.is_value_initialized();
  245. }
  246. // An aggregate struct of a non-POD class and an int.
  247. // Similar to struct A from Microsoft Visual C++ bug report 100744,
  248. // "Value-initialization in new-expression", reported in 2005 by
  249. // Pavel Kuznetsov (MetaCommunications Engineering):
  250. // https://connect.microsoft.com/VisualStudio/feedback/details/100744
  251. struct enum_holder_and_int
  252. {
  253. enum_holder e;
  254. int i;
  255. };
  256. bool is_value_initialized(const enum_holder_and_int& arg)
  257. {
  258. return arg.e.is_value_initialized() && arg.i == 0;
  259. }
  260. class user_defined_copy_constructor_holder
  261. {
  262. public:
  263. int data;
  264. user_defined_copy_constructor_holder()
  265. :
  266. data(0)
  267. {
  268. }
  269. user_defined_copy_constructor_holder(const user_defined_copy_constructor_holder& arg)
  270. :
  271. data(arg.data)
  272. {
  273. }
  274. };
  275. // An aggregate struct that has a data member which has a user-defined
  276. // copy constructor and a data member of a scalar type.
  277. // Similar to struct B from Microsoft Visual C++ bug report 499606,
  278. // "Presence of copy constructor breaks member class initialization",
  279. // reported in 2009 by Alex Vakulenko:
  280. // https://connect.microsoft.com/VisualStudio/feedback/details/499606
  281. struct user_defined_copy_constructor_holder_and_int
  282. {
  283. user_defined_copy_constructor_holder first;
  284. int second;
  285. };
  286. bool is_value_initialized(const user_defined_copy_constructor_holder_and_int& arg)
  287. {
  288. return arg.first.data == 0 && arg.second == 0;
  289. }
  290. // An class that has a private and a protected int data member.
  291. class private_and_protected_int
  292. {
  293. private:
  294. int private_int;
  295. protected:
  296. int protected_int;
  297. public:
  298. friend bool is_value_initialized(const private_and_protected_int& arg)
  299. {
  300. return arg.private_int == 0 && arg.protected_int == 0;
  301. }
  302. };
  303. class user_defined_destructor_holder
  304. {
  305. public:
  306. int i;
  307. ~user_defined_destructor_holder()
  308. {
  309. }
  310. };
  311. bool is_value_initialized(const user_defined_destructor_holder& arg)
  312. {
  313. return arg.i == 0;
  314. }
  315. class virtual_destructor_holder
  316. {
  317. public:
  318. int i;
  319. virtual ~virtual_destructor_holder()
  320. {
  321. }
  322. };
  323. bool is_value_initialized(const virtual_destructor_holder& arg)
  324. {
  325. return arg.i == 0;
  326. }
  327. // A class that is not a POD type.
  328. class non_pod_class
  329. {
  330. private:
  331. enum_holder m_enum_holder;
  332. public:
  333. int i;
  334. virtual bool is_value_initialized() const
  335. {
  336. return m_enum_holder.is_value_initialized() && i == 0;
  337. }
  338. virtual ~non_pod_class() {}
  339. };
  340. bool is_value_initialized(const non_pod_class& arg)
  341. {
  342. return arg.is_value_initialized();
  343. }
  344. typedef char _2d_char_array_type[3][4];
  345. bool is_value_initialized(const _2d_char_array_type& arg)
  346. {
  347. for(unsigned i = 0; i < sizeof(_2d_char_array_type); ++i)
  348. {
  349. if ((*arg)[i] != 0)
  350. {
  351. return false;
  352. }
  353. }
  354. return true;
  355. }
  356. typedef char _3d_char_array_type[5][6][7];
  357. bool is_value_initialized(const _3d_char_array_type& arg)
  358. {
  359. for(unsigned i = 0; i < sizeof(_3d_char_array_type); ++i)
  360. {
  361. if ((**arg)[i] != 0)
  362. {
  363. return false;
  364. }
  365. }
  366. return true;
  367. }
  368. // Tells whether an object of a scalar type T is value-initialized.
  369. template <class T>
  370. bool is_value_initialized(const T& arg)
  371. {
  372. return arg == 0;
  373. }
  374. // Wraps a heap object that it has allocated by doing new T().
  375. template <class T>
  376. class heap_object_wrapper
  377. {
  378. private:
  379. T* const m_ptr;
  380. // The following function is intentionally left unimplemented
  381. // (as if deleted, "= delete", in C++0x):
  382. void operator=(heap_object_wrapper);
  383. public:
  384. heap_object_wrapper()
  385. :
  386. m_ptr(new T())
  387. {
  388. }
  389. ~heap_object_wrapper()
  390. {
  391. delete m_ptr;
  392. }
  393. // The copy-constructor is intentionally left unimplemented.
  394. heap_object_wrapper(const heap_object_wrapper&);
  395. bool is_wrapped_object_value_initialized() const
  396. {
  397. return (m_ptr != 0) && is_value_initialized(*m_ptr);
  398. }
  399. };
  400. template <class T>
  401. bool is_value_initialized(const heap_object_wrapper<T>& arg)
  402. {
  403. return arg.is_wrapped_object_value_initialized();
  404. }
  405. // Returns zero when the specified object is value-initializated, and one otherwise.
  406. // Prints a message to standard output if the value-initialization has failed.
  407. template <class T>
  408. unsigned failed_to_value_initialized(const T& object, const char *const object_name)
  409. {
  410. if ( is_value_initialized(object) )
  411. {
  412. return 0u;
  413. }
  414. else
  415. {
  416. std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl;
  417. return 1u;
  418. }
  419. }
  420. // A macro that passed both the name and the value of the specified object to
  421. // the function above here.
  422. #define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value)
  423. // value_initializer initializes each of its data members by means
  424. // of an empty set of parentheses, and allows checking whether
  425. // each of them is indeed value-initialized, as specified by
  426. // the C++ Standard ([dcl.init]).
  427. //
  428. // Note: its base class, int_struct, is there to try to reproduce GCC Bug 30111,
  429. // "Value-initialization of POD base class doesn't initialize members", reported
  430. // by Jonathan Wakely in 2006: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111
  431. class value_initializer: private int_struct
  432. {
  433. private:
  434. enum_holder m_enum_holder;
  435. enum_holder m_enum_holder_array[2];
  436. enum_type m_enum;
  437. enum_type m_enum_array[2];
  438. bool m_bool;
  439. bool m_bool_array[2];
  440. char m_char;
  441. char m_char_array[2];
  442. _2d_char_array_type m_2d_char_array;
  443. _3d_char_array_type m_3d_char_array;
  444. unsigned char m_unsigned_char;
  445. unsigned char m_unsigned_char_array[2];
  446. short m_short;
  447. short m_short_array[2];
  448. int m_int;
  449. int m_int_array[2];
  450. unsigned m_unsigned;
  451. unsigned m_unsigned_array[2];
  452. long m_long;
  453. long m_long_array[2];
  454. float m_float;
  455. float m_float_array[2];
  456. double m_double;
  457. double m_double_array[2];
  458. long double m_long_double;
  459. long double m_long_double_array[2];
  460. void* m_void_ptr;
  461. void* m_void_ptr_array[2];
  462. function_ptr_type m_function_ptr;
  463. function_ptr_type m_function_ptr_array[2];
  464. function_ptr_struct m_function_ptr_struct;
  465. function_ptr_struct m_function_ptr_struct_array[2];
  466. member_function_ptr_type m_member_function_ptr;
  467. member_function_ptr_type m_member_function_ptr_array[2];
  468. member_function_ptr_struct m_member_function_ptr_struct;
  469. member_function_ptr_struct m_member_function_ptr_struct_array[2];
  470. ptr_to_member_type m_ptr_to_member;
  471. ptr_to_member_type m_ptr_to_member_array[2];
  472. ptr_to_member_struct m_ptr_to_member_struct;
  473. ptr_to_member_struct m_ptr_to_member_struct_array[2];
  474. bit_field_struct m_bit_field_struct;
  475. bit_field_struct m_bit_field_struct_array[2];
  476. int_struct m_int_struct;
  477. int_struct m_int_struct_array[2];
  478. int_struct m_int_struct_holder;
  479. int_struct m_int_struct_holder_array[2];
  480. pod_struct m_pod_struct;
  481. pod_struct m_pod_struct_array[2];
  482. derived_pod_struct m_derived_pod_struct;
  483. derived_pod_struct m_derived_pod_struct_array[2];
  484. derived_struct m_derived_struct;
  485. derived_struct m_derived_struct_array[2];
  486. derived_int_struct m_derived_int_struct;
  487. derived_int_struct m_derived_int_struct_array[2];
  488. private_int_holder m_private_int_holder;
  489. private_int_holder m_private_int_holder_array[2];
  490. char_array_struct m_char_array_struct;
  491. char_array_struct m_char_array_struct_array[2];
  492. private_int_array_pair m_private_int_array_pair;
  493. private_int_array_pair m_private_int_array_pair_array[2];
  494. enum_holder_and_int m_enum_holder_and_int;
  495. enum_holder_and_int m_enum_holder_and_int_array[2];
  496. private_and_protected_int m_private_and_protected_int;
  497. private_and_protected_int m_private_and_protected_int_array[2];
  498. user_defined_copy_constructor_holder_and_int m_user_defined_copy_constructor_holder_and_int;
  499. user_defined_copy_constructor_holder_and_int m_user_defined_copy_constructor_holder_and_int_array[2];
  500. user_defined_destructor_holder m_user_defined_destructor_holder;
  501. user_defined_destructor_holder m_user_defined_destructor_holder_array[2];
  502. virtual_destructor_holder m_virtual_destructor_holder;
  503. virtual_destructor_holder m_virtual_destructor_holder_array[2];
  504. non_pod_class m_non_pod;
  505. non_pod_class m_non_pod_array[2];
  506. pod_struct_and_int_union m_pod_struct_and_int_union;
  507. pod_struct_and_int_union m_pod_struct_and_int_union_array[2];
  508. int_and_pod_struct_union m_int_and_pod_struct_union;
  509. int_and_pod_struct_union m_int_and_pod_struct_union_array[2];
  510. public:
  511. // Default constructor. Tries to value-initialize its base subobject and all
  512. // of its data.members.
  513. value_initializer()
  514. :
  515. // Note: CodeGear/Borland may produce a warning, W8039, for each data member
  516. // whose type is an array type, saying "Constructor initializer list ignored".
  517. // If it does, it probably won't value-initialize those arrays, as reported
  518. // by me (Niels Dekker, LKEB) in 2010, report 83751, "Value-initialization:
  519. // arrays should have each element value-initialized",
  520. // http://qc.embarcadero.com/wc/qcmain.aspx?d=83751
  521. // On the other hand, Microsoft Visual C++ may produce warnings of type C4351,
  522. // saying "new behavior: elements of array '...' will be default initialized",
  523. // which is actually the right behavior!
  524. int_struct(),
  525. m_enum_holder(),
  526. m_enum_holder_array(),
  527. m_enum(),
  528. m_enum_array(),
  529. m_bool(),
  530. m_bool_array(),
  531. m_char(),
  532. m_char_array(),
  533. m_2d_char_array(),
  534. m_3d_char_array(),
  535. m_unsigned_char(),
  536. m_unsigned_char_array(),
  537. m_short(),
  538. m_short_array(),
  539. m_int(),
  540. m_int_array(),
  541. m_unsigned(),
  542. m_unsigned_array(),
  543. m_long(),
  544. m_long_array(),
  545. m_float(),
  546. m_float_array(),
  547. m_double(),
  548. m_double_array(),
  549. m_long_double(),
  550. m_long_double_array(),
  551. m_void_ptr(),
  552. m_void_ptr_array(),
  553. m_function_ptr(),
  554. m_function_ptr_array(),
  555. m_function_ptr_struct(),
  556. m_function_ptr_struct_array(),
  557. m_member_function_ptr(),
  558. m_member_function_ptr_array(),
  559. m_member_function_ptr_struct(),
  560. m_member_function_ptr_struct_array(),
  561. m_ptr_to_member(),
  562. m_ptr_to_member_array(),
  563. m_ptr_to_member_struct(),
  564. m_ptr_to_member_struct_array(),
  565. m_bit_field_struct(),
  566. m_bit_field_struct_array(),
  567. m_int_struct(),
  568. m_int_struct_array(),
  569. m_int_struct_holder(),
  570. m_int_struct_holder_array(),
  571. m_pod_struct(),
  572. m_pod_struct_array(),
  573. m_derived_pod_struct(),
  574. m_derived_pod_struct_array(),
  575. m_derived_struct(),
  576. m_derived_struct_array(),
  577. m_derived_int_struct(),
  578. m_derived_int_struct_array(),
  579. m_private_int_holder(),
  580. m_private_int_holder_array(),
  581. m_char_array_struct(),
  582. m_char_array_struct_array(),
  583. m_private_int_array_pair(),
  584. m_private_int_array_pair_array(),
  585. m_enum_holder_and_int(),
  586. m_enum_holder_and_int_array(),
  587. m_private_and_protected_int(),
  588. m_private_and_protected_int_array(),
  589. m_user_defined_copy_constructor_holder_and_int(),
  590. m_user_defined_copy_constructor_holder_and_int_array(),
  591. m_user_defined_destructor_holder(),
  592. m_user_defined_destructor_holder_array(),
  593. m_virtual_destructor_holder(),
  594. m_virtual_destructor_holder_array(),
  595. m_non_pod(),
  596. m_non_pod_array(),
  597. m_pod_struct_and_int_union(),
  598. m_pod_struct_and_int_union_array(),
  599. m_int_and_pod_struct_union(),
  600. m_int_and_pod_struct_union_array()
  601. {
  602. }
  603. // Returns the number of failures.
  604. unsigned check_value_initialization_of_subobjects() const
  605. {
  606. const unsigned num_failures =
  607. FAILED_TO_VALUE_INITIALIZE(int_struct::data) +
  608. FAILED_TO_VALUE_INITIALIZE(m_enum_holder) +
  609. FAILED_TO_VALUE_INITIALIZE(m_enum_holder_array[0]) +
  610. FAILED_TO_VALUE_INITIALIZE(m_enum_holder_array[1]) +
  611. FAILED_TO_VALUE_INITIALIZE(m_enum) +
  612. FAILED_TO_VALUE_INITIALIZE(m_enum_array[0]) +
  613. FAILED_TO_VALUE_INITIALIZE(m_enum_array[1]) +
  614. FAILED_TO_VALUE_INITIALIZE(m_bool) +
  615. FAILED_TO_VALUE_INITIALIZE(m_bool_array[0]) +
  616. FAILED_TO_VALUE_INITIALIZE(m_bool_array[1]) +
  617. FAILED_TO_VALUE_INITIALIZE(m_char) +
  618. FAILED_TO_VALUE_INITIALIZE(m_char_array[0]) +
  619. FAILED_TO_VALUE_INITIALIZE(m_char_array[1]) +
  620. FAILED_TO_VALUE_INITIALIZE(m_2d_char_array) +
  621. FAILED_TO_VALUE_INITIALIZE(m_3d_char_array) +
  622. FAILED_TO_VALUE_INITIALIZE(m_unsigned_char) +
  623. FAILED_TO_VALUE_INITIALIZE(m_unsigned_char_array[0]) +
  624. FAILED_TO_VALUE_INITIALIZE(m_unsigned_char_array[1]) +
  625. FAILED_TO_VALUE_INITIALIZE(m_short) +
  626. FAILED_TO_VALUE_INITIALIZE(m_short_array[0]) +
  627. FAILED_TO_VALUE_INITIALIZE(m_short_array[1]) +
  628. FAILED_TO_VALUE_INITIALIZE(m_int) +
  629. FAILED_TO_VALUE_INITIALIZE(m_int_array[0]) +
  630. FAILED_TO_VALUE_INITIALIZE(m_int_array[1]) +
  631. FAILED_TO_VALUE_INITIALIZE(m_unsigned) +
  632. FAILED_TO_VALUE_INITIALIZE(m_unsigned_array[0]) +
  633. FAILED_TO_VALUE_INITIALIZE(m_unsigned_array[1]) +
  634. FAILED_TO_VALUE_INITIALIZE(m_long) +
  635. FAILED_TO_VALUE_INITIALIZE(m_long_array[0]) +
  636. FAILED_TO_VALUE_INITIALIZE(m_long_array[1]) +
  637. FAILED_TO_VALUE_INITIALIZE(m_float) +
  638. FAILED_TO_VALUE_INITIALIZE(m_float_array[0]) +
  639. FAILED_TO_VALUE_INITIALIZE(m_float_array[1]) +
  640. FAILED_TO_VALUE_INITIALIZE(m_double) +
  641. FAILED_TO_VALUE_INITIALIZE(m_double_array[0]) +
  642. FAILED_TO_VALUE_INITIALIZE(m_double_array[1]) +
  643. FAILED_TO_VALUE_INITIALIZE(m_long_double) +
  644. FAILED_TO_VALUE_INITIALIZE(m_long_double_array[0]) +
  645. FAILED_TO_VALUE_INITIALIZE(m_long_double_array[1]) +
  646. FAILED_TO_VALUE_INITIALIZE(m_void_ptr) +
  647. FAILED_TO_VALUE_INITIALIZE(m_void_ptr_array[0]) +
  648. FAILED_TO_VALUE_INITIALIZE(m_void_ptr_array[1]) +
  649. FAILED_TO_VALUE_INITIALIZE(m_function_ptr) +
  650. FAILED_TO_VALUE_INITIALIZE(m_function_ptr_array[0]) +
  651. FAILED_TO_VALUE_INITIALIZE(m_function_ptr_array[1]) +
  652. FAILED_TO_VALUE_INITIALIZE(m_function_ptr_struct) +
  653. FAILED_TO_VALUE_INITIALIZE(m_function_ptr_struct_array[0]) +
  654. FAILED_TO_VALUE_INITIALIZE(m_function_ptr_struct_array[1]) +
  655. FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr) +
  656. FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_array[0]) +
  657. FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_array[1]) +
  658. FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_struct) +
  659. FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_struct_array[0]) +
  660. FAILED_TO_VALUE_INITIALIZE(m_member_function_ptr_struct_array[1]) +
  661. FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member) +
  662. FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_array[0]) +
  663. FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_array[1]) +
  664. FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_struct) +
  665. FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_struct_array[0]) +
  666. FAILED_TO_VALUE_INITIALIZE(m_ptr_to_member_struct_array[1]) +
  667. FAILED_TO_VALUE_INITIALIZE(m_bit_field_struct) +
  668. FAILED_TO_VALUE_INITIALIZE(m_bit_field_struct_array[0]) +
  669. FAILED_TO_VALUE_INITIALIZE(m_bit_field_struct_array[1]) +
  670. FAILED_TO_VALUE_INITIALIZE(m_int_struct) +
  671. FAILED_TO_VALUE_INITIALIZE(m_int_struct_array[0]) +
  672. FAILED_TO_VALUE_INITIALIZE(m_int_struct_array[1]) +
  673. FAILED_TO_VALUE_INITIALIZE(m_int_struct_holder) +
  674. FAILED_TO_VALUE_INITIALIZE(m_int_struct_holder_array[0]) +
  675. FAILED_TO_VALUE_INITIALIZE(m_int_struct_holder_array[1]) +
  676. FAILED_TO_VALUE_INITIALIZE(m_pod_struct) +
  677. FAILED_TO_VALUE_INITIALIZE(m_pod_struct_array[0]) +
  678. FAILED_TO_VALUE_INITIALIZE(m_pod_struct_array[1]) +
  679. FAILED_TO_VALUE_INITIALIZE(m_derived_pod_struct) +
  680. FAILED_TO_VALUE_INITIALIZE(m_derived_pod_struct_array[0]) +
  681. FAILED_TO_VALUE_INITIALIZE(m_derived_pod_struct_array[1]) +
  682. FAILED_TO_VALUE_INITIALIZE(m_derived_struct) +
  683. FAILED_TO_VALUE_INITIALIZE(m_derived_struct_array[0]) +
  684. FAILED_TO_VALUE_INITIALIZE(m_derived_struct_array[1]) +
  685. FAILED_TO_VALUE_INITIALIZE(m_derived_int_struct) +
  686. FAILED_TO_VALUE_INITIALIZE(m_derived_int_struct_array[0]) +
  687. FAILED_TO_VALUE_INITIALIZE(m_derived_int_struct_array[1]) +
  688. FAILED_TO_VALUE_INITIALIZE(m_private_int_holder) +
  689. FAILED_TO_VALUE_INITIALIZE(m_private_int_holder_array[0]) +
  690. FAILED_TO_VALUE_INITIALIZE(m_private_int_holder_array[1]) +
  691. FAILED_TO_VALUE_INITIALIZE(m_char_array_struct) +
  692. FAILED_TO_VALUE_INITIALIZE(m_char_array_struct_array[0]) +
  693. FAILED_TO_VALUE_INITIALIZE(m_char_array_struct_array[1]) +
  694. FAILED_TO_VALUE_INITIALIZE(m_private_int_array_pair) +
  695. FAILED_TO_VALUE_INITIALIZE(m_private_int_array_pair_array[0]) +
  696. FAILED_TO_VALUE_INITIALIZE(m_private_int_array_pair_array[1]) +
  697. FAILED_TO_VALUE_INITIALIZE(m_enum_holder_and_int) +
  698. FAILED_TO_VALUE_INITIALIZE(m_enum_holder_and_int_array[0]) +
  699. FAILED_TO_VALUE_INITIALIZE(m_enum_holder_and_int_array[1]) +
  700. FAILED_TO_VALUE_INITIALIZE(m_private_and_protected_int) +
  701. FAILED_TO_VALUE_INITIALIZE(m_private_and_protected_int_array[0]) +
  702. FAILED_TO_VALUE_INITIALIZE(m_private_and_protected_int_array[1]) +
  703. FAILED_TO_VALUE_INITIALIZE(m_user_defined_copy_constructor_holder_and_int) +
  704. FAILED_TO_VALUE_INITIALIZE(m_user_defined_copy_constructor_holder_and_int_array[0]) +
  705. FAILED_TO_VALUE_INITIALIZE(m_user_defined_copy_constructor_holder_and_int_array[1]) +
  706. FAILED_TO_VALUE_INITIALIZE(m_user_defined_destructor_holder) +
  707. FAILED_TO_VALUE_INITIALIZE(m_user_defined_destructor_holder_array[0]) +
  708. FAILED_TO_VALUE_INITIALIZE(m_user_defined_destructor_holder_array[1]) +
  709. FAILED_TO_VALUE_INITIALIZE(m_virtual_destructor_holder) +
  710. FAILED_TO_VALUE_INITIALIZE(m_virtual_destructor_holder_array[0]) +
  711. FAILED_TO_VALUE_INITIALIZE(m_virtual_destructor_holder_array[1]) +
  712. FAILED_TO_VALUE_INITIALIZE(m_non_pod) +
  713. FAILED_TO_VALUE_INITIALIZE(m_non_pod_array[0]) +
  714. FAILED_TO_VALUE_INITIALIZE(m_non_pod_array[1]) +
  715. FAILED_TO_VALUE_INITIALIZE(m_pod_struct_and_int_union) +
  716. FAILED_TO_VALUE_INITIALIZE(m_pod_struct_and_int_union_array[0]) +
  717. FAILED_TO_VALUE_INITIALIZE(m_pod_struct_and_int_union_array[1]) +
  718. FAILED_TO_VALUE_INITIALIZE(m_int_and_pod_struct_union) +
  719. FAILED_TO_VALUE_INITIALIZE(m_int_and_pod_struct_union_array[0]) +
  720. FAILED_TO_VALUE_INITIALIZE(m_int_and_pod_struct_union_array[1]);
  721. return num_failures;
  722. }
  723. };
  724. // Checks value-initialization of a number of small temporary objects.
  725. // Returns the number of failures.
  726. unsigned check_value_initialization_of_temporaries()
  727. {
  728. typedef long double long_double_type;
  729. typedef unsigned char unsigned_char_type;
  730. typedef void* void_ptr_type;
  731. const unsigned num_failures =
  732. FAILED_TO_VALUE_INITIALIZE(enum_holder()) +
  733. FAILED_TO_VALUE_INITIALIZE(enum_type()) +
  734. FAILED_TO_VALUE_INITIALIZE(bool()) +
  735. FAILED_TO_VALUE_INITIALIZE(char()) +
  736. FAILED_TO_VALUE_INITIALIZE(unsigned_char_type()) +
  737. FAILED_TO_VALUE_INITIALIZE(short()) +
  738. FAILED_TO_VALUE_INITIALIZE(int()) +
  739. FAILED_TO_VALUE_INITIALIZE(unsigned()) +
  740. FAILED_TO_VALUE_INITIALIZE(long()) +
  741. FAILED_TO_VALUE_INITIALIZE(float()) +
  742. FAILED_TO_VALUE_INITIALIZE(double()) +
  743. FAILED_TO_VALUE_INITIALIZE(long_double_type()) +
  744. FAILED_TO_VALUE_INITIALIZE(void_ptr_type()) +
  745. FAILED_TO_VALUE_INITIALIZE(bit_field_struct()) +
  746. FAILED_TO_VALUE_INITIALIZE(function_ptr_type()) +
  747. FAILED_TO_VALUE_INITIALIZE(function_ptr_struct()) +
  748. FAILED_TO_VALUE_INITIALIZE(member_function_ptr_type()) +
  749. FAILED_TO_VALUE_INITIALIZE(member_function_ptr_struct()) +
  750. FAILED_TO_VALUE_INITIALIZE(ptr_to_member_type()) +
  751. FAILED_TO_VALUE_INITIALIZE(ptr_to_member_struct()) +
  752. FAILED_TO_VALUE_INITIALIZE(int_struct()) +
  753. FAILED_TO_VALUE_INITIALIZE(int_struct_holder()) +
  754. FAILED_TO_VALUE_INITIALIZE(pod_struct()) +
  755. FAILED_TO_VALUE_INITIALIZE(derived_pod_struct()) +
  756. FAILED_TO_VALUE_INITIALIZE(derived_struct()) +
  757. FAILED_TO_VALUE_INITIALIZE(derived_int_struct()) +
  758. FAILED_TO_VALUE_INITIALIZE(private_int_holder()) +
  759. FAILED_TO_VALUE_INITIALIZE(char_array_struct()) +
  760. FAILED_TO_VALUE_INITIALIZE(private_int_array_pair()) +
  761. // IBM's XL V10.1.0.0 may fail to value-initialize a temporary of a non-POD
  762. // type like enum_holder_and_int, virtual_destructor_holder, or non_pod_class,
  763. // as appeared at the Boost Config/trunk regression page in April 2010.
  764. // Michael Wong (IBM Canada Ltd) confirmed the issue to me (Niels Dekker, LKEB),
  765. // and gave it high priority.
  766. FAILED_TO_VALUE_INITIALIZE(enum_holder_and_int()) +
  767. FAILED_TO_VALUE_INITIALIZE(private_and_protected_int()) +
  768. FAILED_TO_VALUE_INITIALIZE(user_defined_copy_constructor_holder_and_int()) +
  769. // The following line, doing user_defined_destructor_holder(), causes
  770. // a compilation error on Embarcadero 2010 (Borland/CodeGear 6.21),
  771. // as reported by me (Niels Dekker, LKEB) in 2010, bug report 83851,
  772. // "Value-initialized temporary triggers internal backend error C1798",
  773. // http://qc.embarcadero.com/wc/qcmain.aspx?d=83851
  774. FAILED_TO_VALUE_INITIALIZE(user_defined_destructor_holder()) +
  775. FAILED_TO_VALUE_INITIALIZE(virtual_destructor_holder()) +
  776. FAILED_TO_VALUE_INITIALIZE(non_pod_class()) +
  777. FAILED_TO_VALUE_INITIALIZE(pod_struct_and_int_union()) +
  778. FAILED_TO_VALUE_INITIALIZE(int_and_pod_struct_union());
  779. return num_failures;
  780. }
  781. // Checks value-initialization of small heap objects.
  782. // Returns the number of failures.
  783. unsigned check_value_initialization_of_heap_objects()
  784. {
  785. const unsigned num_failures =
  786. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<enum_holder>() ) +
  787. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<enum_type>() ) +
  788. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<bool>() ) +
  789. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<char>() ) +
  790. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<unsigned char>() ) +
  791. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<short>() ) +
  792. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int>() ) +
  793. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<unsigned>() ) +
  794. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<long>() ) +
  795. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<float>() ) +
  796. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<double>() ) +
  797. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<long double>() ) +
  798. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<void*>() ) +
  799. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<function_ptr_type>() ) +
  800. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<function_ptr_struct>() ) +
  801. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<member_function_ptr_type>() ) +
  802. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<member_function_ptr_struct>() ) +
  803. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<ptr_to_member_type>() ) +
  804. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<ptr_to_member_struct>() ) +
  805. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<bit_field_struct>() ) +
  806. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int_struct>() ) +
  807. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int_struct>() ) +
  808. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<pod_struct>() ) +
  809. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<derived_pod_struct>() ) +
  810. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<derived_struct>() ) +
  811. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<derived_int_struct>() ) +
  812. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<char_array_struct>() ) +
  813. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<private_int_holder>() ) +
  814. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<private_int_array_pair>() ) +
  815. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<enum_holder_and_int>() ) +
  816. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<private_and_protected_int>() ) +
  817. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<user_defined_copy_constructor_holder_and_int>() ) +
  818. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<user_defined_destructor_holder>() ) +
  819. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<virtual_destructor_holder>() ) +
  820. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<non_pod_class>() ) +
  821. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<pod_struct_and_int_union>() ) +
  822. FAILED_TO_VALUE_INITIALIZE( heap_object_wrapper<int_and_pod_struct_union>() );
  823. return num_failures;
  824. }
  825. // Equivalent to the dirty_stack() function from GCC Bug 33916,
  826. // "Default constructor fails to initialize array members", reported in 2007 by
  827. // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916
  828. void dirty_stack()
  829. {
  830. unsigned char array_on_stack[sizeof(value_initializer) + 256];
  831. for (unsigned i = 0; i < sizeof(array_on_stack); ++i)
  832. {
  833. array_on_stack[i] = 0x11;
  834. }
  835. }
  836. // Checks value-initialization of the subobjects of a temporary object,
  837. // an object on the stack, an object on the heap; furthermore it checks
  838. // value-initialization of a number of smaller temporary objects and
  839. // heap objects.
  840. int test()
  841. {
  842. unsigned total_num_failures = 0;
  843. dirty_stack();
  844. const unsigned num_failures_of_subobjects_of_a_temporary =
  845. value_initializer().check_value_initialization_of_subobjects();
  846. total_num_failures += num_failures_of_subobjects_of_a_temporary;
  847. if ( total_num_failures > 0 )
  848. {
  849. std::cout << "- Number of subobject initialization failures of a temporary: "
  850. << num_failures_of_subobjects_of_a_temporary << std::endl;
  851. }
  852. dirty_stack();
  853. value_initializer object_on_stack;
  854. const unsigned num_failures_of_subobjects_on_stack =
  855. object_on_stack.check_value_initialization_of_subobjects();
  856. total_num_failures += num_failures_of_subobjects_on_stack;
  857. if ( total_num_failures > 0 )
  858. {
  859. std::cout << "- Number of subobject initialization failures on the stack: "
  860. << num_failures_of_subobjects_on_stack << std::endl;
  861. }
  862. const value_initializer* const ptr = new value_initializer();
  863. const unsigned num_failures_of_subobjects_on_heap = ptr->check_value_initialization_of_subobjects();
  864. delete ptr;
  865. total_num_failures += num_failures_of_subobjects_on_heap;
  866. if ( total_num_failures > 0 )
  867. {
  868. std::cout << "- Number of subobject initialization failures on the heap: "
  869. << num_failures_of_subobjects_on_heap << std::endl;
  870. }
  871. dirty_stack();
  872. const unsigned num_failures_of_temporaries = check_value_initialization_of_temporaries();
  873. total_num_failures += num_failures_of_temporaries;
  874. if ( total_num_failures > 0 )
  875. {
  876. std::cout << "- Number of initialization failures of temporary objects: "
  877. << num_failures_of_temporaries << std::endl;
  878. }
  879. const unsigned num_failures_of_heap_objects = check_value_initialization_of_heap_objects();
  880. total_num_failures += num_failures_of_heap_objects;
  881. if ( total_num_failures > 0 )
  882. {
  883. std::cout << "- Number of failures of heap objects: "
  884. << num_failures_of_heap_objects << std::endl;
  885. }
  886. if ( total_num_failures > 0 )
  887. {
  888. std::cout << "-- Total number of initialization failures ("
  889. << num_failures_of_subobjects_of_a_temporary << '+'
  890. << num_failures_of_subobjects_on_stack << '+'
  891. << num_failures_of_subobjects_on_heap << '+'
  892. << num_failures_of_temporaries << '+'
  893. << num_failures_of_heap_objects << "): "
  894. << total_num_failures
  895. << "\nDetected by boost_no_complete_value_initialization::test() revision 32."
  896. << std::endl;
  897. }
  898. return static_cast<int>(total_num_failures);
  899. }
  900. } // End of namespace.