// RUN: %llvmgxx -S %s -o - -O2 | FileCheck %s namespace boost { namespace detail { template <typename T> struct cv_traits_imp {}; template <typename T> struct cv_traits_imp<T*> {typedef T unqualified_type;}; } } namespace mpl_ {} namespace boost { namespace mpl {using namespace mpl_;} template< typename T > struct remove_cv {typedef typename boost::detail::cv_traits_imp<T*>::unqualified_type type;}; namespace type_traits { typedef char yes_type; struct no_type {char padding[8];}; } } namespace mpl_ { template< bool C_ > struct bool_; typedef bool_<true> true_; typedef bool_<false> false_; template< bool C_ > struct bool_ {static const bool value = C_;}; template< typename T, T N > struct integral_c; } namespace boost{ template <class T, T val> struct integral_constant : public mpl::integral_c<T, val> {}; template<> struct integral_constant<bool,true> : public mpl::true_ {}; template<> struct integral_constant<bool,false> : public mpl::false_ {}; namespace type_traits { template <bool b1, bool b2, bool b3 = false, bool b4 = false, bool b5 = false, bool b6 = false, bool b7 = false> struct ice_or; template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7> struct ice_or {static const bool value = true; }; template <> struct ice_or<false, false, false, false, false, false, false> {static const bool value = false;}; template <bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true, bool b6 = true, bool b7 = true> struct ice_and; template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7> struct ice_and {static const bool value = false;}; template <> struct ice_and<true, true, true, true, true, true, true> {static const bool value = true;}; template <bool b> struct ice_not {static const bool value = true;}; }; namespace detail { template <typename T> struct is_union_impl {static const bool value = false;}; } template< typename T > struct is_union : ::boost::integral_constant<bool, ::boost::detail::is_union_impl<T>::value> {}; namespace detail { template <class U> ::boost::type_traits::yes_type is_class_tester(void(U::*)(void)); template <class U> ::boost::type_traits::no_type is_class_tester(...); template <typename T> struct is_class_impl { static const bool value = (::boost::type_traits::ice_and< sizeof(is_class_tester<T>(0)) == sizeof(::boost::type_traits::yes_type), ::boost::type_traits::ice_not< ::boost::is_union<T>::value >::value >::value);}; } template<typename T> struct is_class: ::boost::integral_constant<bool,::boost::detail::is_class_impl<T>::value> { }; namespace detail { template <typename T> struct empty_helper_t1: public T {int i[256];}; struct empty_helper_t2 {int i[256];}; template <typename T, bool is_a_class = false> struct empty_helper {static const bool value = false;}; template <typename T> struct empty_helper<T, true> {static const bool value = (sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2));}; template <typename T> struct is_empty_impl { typedef typename remove_cv<T>::type cvt; static const bool value = (::boost::type_traits::ice_or< ::boost::detail::empty_helper <cvt,::boost::is_class<T>::value>::value, false>::value); }; } template<typename T> struct is_empty: ::boost::integral_constant<bool,::boost::detail::is_empty_impl<T>::value> {}; template<typename T, typename U > struct is_same: ::boost::integral_constant<bool,false> {}; template<typename T> struct call_traits {typedef T& reference;}; namespace details { template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty> struct compressed_pair_switch; template <class T1, class T2> struct compressed_pair_switch<T1, T2, false, true, false> {static const int value = 1;}; template <class T1, class T2, int Version> class compressed_pair_imp; template <class T1, class T2> class compressed_pair_imp<T1, T2, 1>: protected ::boost::remove_cv<T1>::type { public: typedef T1 first_type; typedef T2 second_type; typedef typename call_traits<first_type>::reference first_reference; typedef typename call_traits<second_type>::reference second_reference; first_reference first() {return *this;} second_reference second() {return second_;} second_type second_; }; } template <class T1, class T2> class compressed_pair: private ::boost::details::compressed_pair_imp<T1, T2, ::boost::details::compressed_pair_switch< T1, T2, ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, ::boost::is_empty<T1>::value, ::boost::is_empty<T2>::value>::value> { private: typedef details::compressed_pair_imp<T1, T2, ::boost::details::compressed_pair_switch< T1, T2, ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, ::boost::is_empty<T1>::value, ::boost::is_empty<T2>::value>::value> base; public: typedef T1 first_type; typedef T2 second_type; typedef typename call_traits<first_type>::reference first_reference; typedef typename call_traits<second_type>::reference second_reference; first_reference first() {return base::first();} second_reference second() {return base::second();} }; } struct empty_base_t {}; struct empty_t : empty_base_t {}; typedef boost::compressed_pair<empty_t, int> data_t; extern "C" {int printf(const char * , ...);} extern "C" {void abort(void);} int main (int argc, char * const argv[]) { data_t x; x.second() = -3; // This store should be elided: x.first() = empty_t(); // If x.second() has been clobbered by the elided store, fail. if (x.second() != -3) { printf("x.second() was clobbered\n"); // CHECK-NOT: x.second() was clobbered abort(); } return 0; } // CHECK: ret i32