Stuart Hastings | 98e3c14 | 2010-03-23 18:39:23 +0000 | [diff] [blame] | 1 | // RUN: %llvmgxx -S -emit-llvm %s -o - -O2 | FileCheck %s |
| 2 | namespace boost { |
| 3 | namespace detail { |
| 4 | template <typename T> struct cv_traits_imp {}; |
| 5 | template <typename T> struct cv_traits_imp<T*> {typedef T unqualified_type;}; |
| 6 | } |
| 7 | } |
| 8 | namespace mpl_ {} |
| 9 | namespace boost { |
| 10 | namespace mpl {using namespace mpl_;} |
| 11 | template< typename T > struct remove_cv {typedef typename boost::detail::cv_traits_imp<T*>::unqualified_type type;}; |
| 12 | namespace type_traits { |
| 13 | typedef char yes_type; |
| 14 | struct no_type {char padding[8];}; |
| 15 | } |
| 16 | } |
| 17 | namespace mpl_ { |
| 18 | template< bool C_ > struct bool_; |
| 19 | typedef bool_<true> true_; |
| 20 | typedef bool_<false> false_; |
| 21 | template< bool C_ > struct bool_ {static const bool value = C_;}; |
| 22 | template< typename T, T N > struct integral_c; |
| 23 | } |
| 24 | namespace boost{ |
| 25 | template <class T, T val> struct integral_constant : |
| 26 | public mpl::integral_c<T, val> {}; |
| 27 | template<> struct integral_constant<bool,true> : public mpl::true_ {}; |
| 28 | template<> struct integral_constant<bool,false> : public mpl::false_ {}; |
| 29 | namespace type_traits { |
| 30 | template <bool b1, bool b2, bool b3 = false, bool b4 = false, |
| 31 | bool b5 = false, bool b6 = false, bool b7 = false> struct ice_or; |
| 32 | template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7> |
| 33 | struct ice_or {static const bool value = true; }; |
| 34 | template <> struct ice_or<false, false, false, false, false, false, false> |
| 35 | {static const bool value = false;}; |
| 36 | template <bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true, |
| 37 | bool b6 = true, bool b7 = true> struct ice_and; |
| 38 | template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7> |
| 39 | struct ice_and {static const bool value = false;}; |
| 40 | template <> struct ice_and<true, true, true, true, true, true, true> |
| 41 | {static const bool value = true;}; |
| 42 | template <bool b> struct ice_not {static const bool value = true;}; |
| 43 | }; |
| 44 | namespace detail { |
| 45 | template <typename T> struct is_union_impl {static const bool value = false;}; |
| 46 | } |
| 47 | template< typename T > struct is_union : |
| 48 | ::boost::integral_constant<bool, ::boost::detail::is_union_impl<T>::value> {}; |
| 49 | namespace detail { |
| 50 | template <class U> ::boost::type_traits::yes_type is_class_tester(void(U::*)(void)); |
| 51 | template <class U> ::boost::type_traits::no_type is_class_tester(...); |
| 52 | template <typename T> struct is_class_impl { |
| 53 | static const bool value = (::boost::type_traits::ice_and< sizeof(is_class_tester<T>(0)) |
| 54 | == sizeof(::boost::type_traits::yes_type), |
| 55 | ::boost::type_traits::ice_not< ::boost::is_union<T>::value >::value >::value);}; |
| 56 | } |
| 57 | template<typename T> struct is_class: |
| 58 | ::boost::integral_constant<bool,::boost::detail::is_class_impl<T>::value> { }; |
| 59 | namespace detail { |
| 60 | template <typename T> struct empty_helper_t1: public T {int i[256];}; |
| 61 | struct empty_helper_t2 {int i[256];}; |
| 62 | template <typename T, bool is_a_class = false> struct empty_helper |
| 63 | {static const bool value = false;}; |
| 64 | template <typename T> struct empty_helper<T, true> |
| 65 | {static const bool value = (sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2));}; |
| 66 | template <typename T> struct is_empty_impl { |
| 67 | typedef typename remove_cv<T>::type cvt; |
| 68 | static const bool value = (::boost::type_traits::ice_or< ::boost::detail::empty_helper |
| 69 | <cvt,::boost::is_class<T>::value>::value, false>::value); |
| 70 | }; |
| 71 | } |
| 72 | template<typename T> struct is_empty: |
| 73 | ::boost::integral_constant<bool,::boost::detail::is_empty_impl<T>::value> {}; |
| 74 | template<typename T, typename U > struct is_same: |
| 75 | ::boost::integral_constant<bool,false> {}; |
| 76 | template<typename T> struct call_traits {typedef T& reference;}; |
| 77 | namespace details { |
| 78 | template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty> |
| 79 | struct compressed_pair_switch; |
| 80 | template <class T1, class T2> |
| 81 | struct compressed_pair_switch<T1, T2, false, true, false> |
| 82 | {static const int value = 1;}; |
| 83 | template <class T1, class T2, int Version> class compressed_pair_imp; |
| 84 | template <class T1, class T2> class compressed_pair_imp<T1, T2, 1>: |
| 85 | protected ::boost::remove_cv<T1>::type { |
| 86 | public: |
| 87 | typedef T1 first_type; |
| 88 | typedef T2 second_type; |
| 89 | typedef typename call_traits<first_type>::reference first_reference; |
| 90 | typedef typename call_traits<second_type>::reference second_reference; |
| 91 | first_reference first() {return *this;} |
| 92 | second_reference second() {return second_;} |
| 93 | second_type second_; |
| 94 | }; |
| 95 | } |
| 96 | template <class T1, class T2> class compressed_pair: |
| 97 | private ::boost::details::compressed_pair_imp<T1, T2, ::boost::details::compressed_pair_switch< |
| 98 | T1, T2, ::boost::is_same<typename remove_cv<T1>::type, |
| 99 | typename remove_cv<T2>::type>::value, |
| 100 | ::boost::is_empty<T1>::value, ::boost::is_empty<T2>::value>::value> |
| 101 | { |
| 102 | private: |
| 103 | typedef details::compressed_pair_imp<T1, T2, ::boost::details::compressed_pair_switch< |
| 104 | T1, T2, ::boost::is_same<typename remove_cv<T1>::type, |
| 105 | typename remove_cv<T2>::type>::value, |
| 106 | ::boost::is_empty<T1>::value, ::boost::is_empty<T2>::value>::value> base; |
| 107 | public: |
| 108 | typedef T1 first_type; |
| 109 | typedef T2 second_type; |
| 110 | typedef typename call_traits<first_type>::reference first_reference; |
| 111 | typedef typename call_traits<second_type>::reference second_reference; |
| 112 | first_reference first() {return base::first();} |
| 113 | second_reference second() {return base::second();} |
| 114 | }; |
| 115 | } |
| 116 | struct empty_base_t {}; |
| 117 | struct empty_t : empty_base_t {}; |
| 118 | typedef boost::compressed_pair<empty_t, int> data_t; |
| 119 | extern "C" {int printf(const char * , ...);} |
| 120 | extern "C" {void abort(void);} |
| 121 | int main (int argc, char * const argv[]) { |
| 122 | data_t x; |
| 123 | x.second() = -3; |
| 124 | // This store should be elided: |
| 125 | x.first() = empty_t(); |
| 126 | // If x.second() has been clobbered by the elided store, fail. |
| 127 | if (x.second() != -3) { |
| 128 | printf("x.second() was clobbered\n"); |
| 129 | // CHECK-NOT: x.second() was clobbered |
| 130 | abort(); |
| 131 | } |
| 132 | return 0; |
| 133 | } |
| 134 | // CHECK: ret i32 |