From 5744aef20ce7a681cc38466d6eb3eb7868109d64 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 13 Jan 2009 13:02:56 +0000 Subject: [PATCH] Merge msvc-specific regression-fixes from trunk. [SVN r50560] --- include/boost/type_traits/alignment_of.hpp | 13 ++- test/aligned_storage_test_a2.cpp | 113 +++++++++++++++++++++ test/alignment_of_test_a2.cpp | 113 +++++++++++++++++++++ 3 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 test/aligned_storage_test_a2.cpp create mode 100644 test/alignment_of_test_a2.cpp diff --git a/include/boost/type_traits/alignment_of.hpp b/include/boost/type_traits/alignment_of.hpp index 9739f14..564d3bb 100644 --- a/include/boost/type_traits/alignment_of.hpp +++ b/include/boost/type_traits/alignment_of.hpp @@ -56,7 +56,18 @@ struct alignment_logic template< typename T > struct alignment_of_impl { -#ifndef BOOST_ALIGNMENT_OF +#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) + // + // With MSVC both the native __alignof operator + // and our own logic gets things wrong from time to time :-( + // Using a combination of the two seems to make the most of a bad job: + // + BOOST_STATIC_CONSTANT(std::size_t, value = + (::boost::detail::alignment_logic< + sizeof(::boost::detail::alignment_of_hack) - sizeof(T), + __alignof(T) + >::value)); +#elif !defined(BOOST_ALIGNMENT_OF) BOOST_STATIC_CONSTANT(std::size_t, value = (::boost::detail::alignment_logic< sizeof(::boost::detail::alignment_of_hack) - sizeof(T), diff --git a/test/aligned_storage_test_a2.cpp b/test/aligned_storage_test_a2.cpp new file mode 100644 index 0000000..47fe3c4 --- /dev/null +++ b/test/aligned_storage_test_a2.cpp @@ -0,0 +1,113 @@ + +#ifdef _MSC_VER +#pragma pack(2) +#endif + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include "check_integral_constant.hpp" +#ifdef TEST_STD +# include +# include // max_align and long_long_type +#else +# include +# include +# include +#endif + +template +union must_be_pod +{ + int i; + T t; +}; + +template +inline void no_unused_warning(const volatile T&) +{ +} + +template +void check(const T&) +{ + typedef typename tt::aligned_storage::type t1; + t1 as1 = { 0, }; + must_be_pod pod1; + no_unused_warning(as1); + no_unused_warning(pod1); + BOOST_MESSAGE(typeid(t1).name()); + BOOST_CHECK(::tt::alignment_of::value == T::value); + BOOST_CHECK(sizeof(t1) == T::value); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_CHECK(::tt::is_pod::value == true); +#endif + typedef typename tt::aligned_storage::type t2; + t2 as2 = { 0, }; + must_be_pod pod2; + no_unused_warning(as2); + no_unused_warning(pod2); + BOOST_MESSAGE(typeid(t2).name()); + BOOST_CHECK(::tt::alignment_of::value == T::value); + BOOST_CHECK(sizeof(t2) == T::value*2); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_CHECK(::tt::is_pod::value == true); +#endif + +#ifndef TEST_STD + // Non-Tr1 behaviour: + typedef typename tt::aligned_storage::type t3; + t3 as3 = { 0, }; + must_be_pod pod3; + no_unused_warning(as3); + no_unused_warning(pod3); + BOOST_MESSAGE(typeid(t3).name()); + BOOST_CHECK(::tt::alignment_of::value == ::tt::alignment_of< ::boost::detail::max_align>::value); + BOOST_CHECK((sizeof(t3) % T::value) == 0); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_CHECK(::tt::is_pod::value == true); +#endif +#endif +} + +TT_TEST_BEGIN(type_with_alignment) + +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); + +#ifdef BOOST_HAS_LONG_LONG +check(tt::integral_constant::value>()); +#endif +#ifdef BOOST_HAS_MS_INT64 +check(tt::integral_constant::value>()); +#endif +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); +check(tt::integral_constant::value>()); + +TT_TEST_END + + + + + + + + + diff --git a/test/alignment_of_test_a2.cpp b/test/alignment_of_test_a2.cpp new file mode 100644 index 0000000..72a1109 --- /dev/null +++ b/test/alignment_of_test_a2.cpp @@ -0,0 +1,113 @@ + +#ifdef _MSC_VER +#pragma pack(2) +#endif + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include "check_integral_constant.hpp" +#ifdef TEST_STD +# include +#else +# include +#endif + +// +// VC++ emits an awful lot of warnings unless we define these: +#ifdef BOOST_MSVC +# pragma warning(disable:4244) +// +// What follows here is the test case for issue 1946. +// +#include +// This kind of packing is set within MSVC 9.0 headers. +// E.g. std::ostream has it. +#pragma pack(push,8) + +// The issue is gone if Root has no data members +struct Root { int a; }; +// The issue is gone if Root is inherited non-virtually +struct A : virtual public Root {}; + +#pragma pack(pop) +// +// This class has 8-byte alignment but is 44 bytes in size, which means +// that elements in an array of this type will not actually be 8 byte +// aligned. This appears to be an MSVC bug, and throws off our +// alignment calculations: causing us to report a non-sensical 12-byte +// alignment for this type. This is fixed by using the native __alignof +// operator. +// +class issue1946 : + public A +{ +public: + // The issue is gone if the type is not a boost::function. The signature doesn't matter. + typedef boost::function0< void > function_type; + function_type m_function; +}; + +#endif + + +template +struct align_calc +{ + char padding; + T instance; + static std::ptrdiff_t get() + { + static align_calc a; + return reinterpret_cast(&(a.instance)) - reinterpret_cast(&(a.padding)); + } +}; + +#define ALIGNOF(x) align_calc< x>::get() + +TT_TEST_BEGIN(alignment_of) + +#ifndef TEST_STD +// This test is not required to work for non-boost implementations: +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, 0); +#endif +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(char)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(short)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(int)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(long)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(float)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(double)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(long double)); +#ifdef BOOST_HAS_LONG_LONG +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of< ::boost::long_long_type>::value, ALIGNOF(::boost::long_long_type)); +#endif +#ifdef BOOST_HAS_MS_INT64 +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of<__int64>::value, ALIGNOF(__int64)); +#endif +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(int[4])); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(int(*)(int))); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(int*)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(VB)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(VD)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(enum_UDT)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(mf2)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(POD_UDT)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(empty_UDT)); +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(union_UDT)); + +#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::alignment_of::value, ALIGNOF(issue1946)); +#endif + +TT_TEST_END + + + + + + + +