diff options
author | Richard Guenther <rguenther@suse.de> | 2009-01-04 19:51:18 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2009-01-04 19:51:18 +0000 |
commit | 9c01326d9a6d56c381ef139a2c25953f483feec8 (patch) | |
tree | cf9015c7924ee0018c79317504d5e9640ab6595d /libstdc++-v3/include/ext/pointer.h | |
parent | 70e72065c34129a5b5d3381b111f22f18c5c3aa3 (diff) | |
download | gcc-9c01326d9a6d56c381ef139a2c25953f483feec8.zip gcc-9c01326d9a6d56c381ef139a2c25953f483feec8.tar.gz gcc-9c01326d9a6d56c381ef139a2c25953f483feec8.tar.bz2 |
re PR libstdc++/38720 (_Relative_pointer_impl invokes undefined behavior)
2009-01-04 Richard Guenther <rguenther@suse.de>
PR libstdc++/38720
* include/ext/pointer.h (_Relative_pointer_impl): Use an unsigned
integer type for storage, arithmetic and comparisons.
* testsuite/ext/ext_pointer/1_neg.cc: Adjust line numbers.
From-SVN: r143058
Diffstat (limited to 'libstdc++-v3/include/ext/pointer.h')
-rw-r--r-- | libstdc++-v3/include/ext/pointer.h | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/libstdc++-v3/include/ext/pointer.h b/libstdc++-v3/include/ext/pointer.h index 5c764cf..ff409b6 100644 --- a/libstdc++-v3/include/ext/pointer.h +++ b/libstdc++-v3/include/ext/pointer.h @@ -42,6 +42,7 @@ #include <iosfwd> #include <bits/stl_iterator_base_types.h> #include <ext/cast.h> +#include <ext/type_traits.h> _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) @@ -111,9 +112,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) if (_M_diff == 1) return 0; else - return reinterpret_cast<_Tp*>( - const_cast<char*>(reinterpret_cast<const char*>(this)) - + _M_diff); + return reinterpret_cast<_Tp*>(reinterpret_cast<_UIntPtrType>(this) + + _M_diff); } void @@ -122,21 +122,26 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) if (!__arg) _M_diff = 1; else - _M_diff = reinterpret_cast<char*>(__arg) - - reinterpret_cast<char*>(this); + _M_diff = reinterpret_cast<_UIntPtrType>(__arg) + - reinterpret_cast<_UIntPtrType>(this); } // Comparison of pointers inline bool operator<(const _Relative_pointer_impl& __rarg) const - { return (this->get() < __rarg.get()); } + { return (reinterpret_cast<_UIntPtrType>(this->get()) + < reinterpret_cast<_UIntPtrType>(__rarg.get())); } inline bool operator==(const _Relative_pointer_impl& __rarg) const - { return (this->get() == __rarg.get()); } + { return (reinterpret_cast<_UIntPtrType>(this->get()) + == reinterpret_cast<_UIntPtrType>(__rarg.get())); } private: - std::ptrdiff_t _M_diff; + typedef __gnu_cxx::__conditional_type< + (sizeof(unsigned long) >= sizeof(void*)), + unsigned long, unsigned long long>::__type _UIntPtrType; + _UIntPtrType _M_diff; }; /** @@ -155,8 +160,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) if (_M_diff == 1) return 0; else - return reinterpret_cast<const _Tp*>( - (reinterpret_cast<const char*>(this)) + _M_diff); + return reinterpret_cast<const _Tp*> + (reinterpret_cast<_UIntPtrType>(this) + _M_diff); } void @@ -165,21 +170,26 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) if (!__arg) _M_diff = 1; else - _M_diff = reinterpret_cast<const char*>(__arg) - - reinterpret_cast<const char*>(this); + _M_diff = reinterpret_cast<_UIntPtrType>(__arg) + - reinterpret_cast<_UIntPtrType>(this); } // Comparison of pointers inline bool operator<(const _Relative_pointer_impl& __rarg) const - { return (this->get() < __rarg.get()); } + { return (reinterpret_cast<_UIntPtrType>(this->get()) + < reinterpret_cast<_UIntPtrType>(__rarg.get())); } inline bool operator==(const _Relative_pointer_impl& __rarg) const - { return (this->get() == __rarg.get()); } + { return (reinterpret_cast<_UIntPtrType>(this->get()) + == reinterpret_cast<_UIntPtrType>(__rarg.get())); } private: - std::ptrdiff_t _M_diff; + typedef __gnu_cxx::__conditional_type + <(sizeof(unsigned long) >= sizeof(void*)), + unsigned long, unsigned long long>::__type _UIntPtrType; + _UIntPtrType _M_diff; }; /** |