Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r67020 - trunk/boost/optional
From: andrey.semashev_at_[hidden]
Date: 2010-12-05 09:43:19


Author: andysem
Date: 2010-12-05 09:43:18 EST (Sun, 05 Dec 2010)
New Revision: 67020
URL: http://svn.boost.org/trac/boost/changeset/67020

Log:
Refs #3395. Optional construction and assignment now works correctly for types with overridden operator&. Also silenced some GCC warnings about broken strict aliasing rules.
Text files modified:
   trunk/boost/optional/optional.hpp | 63 +++++++++++++++++++++++++++------------
   1 files changed, 44 insertions(+), 19 deletions(-)

Modified: trunk/boost/optional/optional.hpp
==============================================================================
--- trunk/boost/optional/optional.hpp (original)
+++ trunk/boost/optional/optional.hpp 2010-12-05 09:43:18 EST (Sun, 05 Dec 2010)
@@ -11,12 +11,12 @@
 //
 // Revisions:
 // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
-//
+//
 #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
 #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
 
-#include<new>
-#include<algorithm>
+#include <new>
+#include <algorithm>
 
 #include "boost/config.hpp"
 #include "boost/assert.hpp"
@@ -31,6 +31,7 @@
 #include "boost/mpl/not.hpp"
 #include "boost/detail/reference_content.hpp"
 #include "boost/none.hpp"
+#include "boost/utility/addressof.hpp"
 #include "boost/utility/compare_pointees.hpp"
 #include "boost/utility/in_place_factory.hpp"
 
@@ -110,7 +111,12 @@
 class aligned_storage
 {
     // Borland ICEs if unnamed unions are used for this!
- union dummy_u
+ union
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
+ __attribute__((may_alias))
+#endif
+ dummy_u
     {
         char data[ sizeof(T) ];
         BOOST_DEDUCED_TYPENAME type_with_alignment<
@@ -119,8 +125,13 @@
 
   public:
 
- void const* address() const { return &dummy_.data[0]; }
- void * address() { return &dummy_.data[0]; }
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ void const* address() const { return &dummy_; }
+ void * address() { return &dummy_; }
+#else
+ void const* address() const { return dummy_.data; }
+ void * address() { return dummy_.data; }
+#endif
 } ;
 
 template<class T>
@@ -154,7 +165,7 @@
     typedef
 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
     BOOST_DEDUCED_TYPENAME
-#endif
+#endif
     ::boost::detail::make_reference_content<T>::type internal_type ;
 
     typedef aligned_storage<internal_type> storage_type ;
@@ -205,7 +216,7 @@
     {
       construct(val);
     }
-
+
     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
     // Can throw if T::T(T const&) does
     optional_base ( bool cond, argument_type val )
@@ -426,8 +437,22 @@
   private :
 
     // internal_type can be either T or reference_content<T>
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
+ internal_type const* get_object() const
+ {
+ union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
+ return caster.as_ptype;
+ }
+ internal_type * get_object()
+ {
+ union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
+ return caster.as_ptype;
+ }
+#else
     internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
     internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
+#endif
 
     // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
     reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
@@ -518,7 +543,7 @@
     // Depending on the above some T ctor is called.
     // Can throw is the resolved T ctor throws.
     template<class Expr>
- explicit optional ( Expr const& expr ) : base(expr,&expr) {}
+ explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
 #endif
 
     // Creates a deep copy of another optional<T>
@@ -532,9 +557,9 @@
     // Assigns from an expression. See corresponding constructor.
     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
     template<class Expr>
- optional& operator= ( Expr expr )
+ optional& operator= ( Expr const& expr )
       {
- this->assign_expr(expr,&expr);
+ this->assign_expr(expr,boost::addressof(expr));
         return *this ;
       }
 #endif
@@ -595,7 +620,7 @@
     // Returns a copy of the value if this is initialized, 'v' otherwise
     reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
     reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
-
+
     // Returns a pointer to the value if this is initialized, otherwise,
     // the behaviour is UNDEFINED
     // No-throw
@@ -612,22 +637,22 @@
     // No-throw
     operator unspecified_bool_type() const { return this->safe_bool() ; }
 
- // This is provided for those compilers which don't like the conversion to bool
- // on some contexts.
- bool operator!() const { return !this->is_initialized() ; }
+ // This is provided for those compilers which don't like the conversion to bool
+ // on some contexts.
+ bool operator!() const { return !this->is_initialized() ; }
 } ;
 
 // Returns optional<T>(v)
-template<class T>
-inline
+template<class T>
+inline
 optional<T> make_optional ( T const& v )
 {
   return optional<T>(v);
 }
 
 // Returns optional<T>(cond,v)
-template<class T>
-inline
+template<class T>
+inline
 optional<T> make_optional ( bool cond, T const& v )
 {
   return optional<T>(cond,v);


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk