From 9f9eb84eac326d99a1e1fb02496870bf3ebfbda9 Mon Sep 17 00:00:00 2001
From: Jonathan Wakely <jwakely@redhat.com>
Date: Thu, 28 Apr 2016 13:33:07 +0100
Subject: [PATCH] libstdc++/70766 use std::addressof instead of operator&

	PR libstdc++/70766
	* include/bits/basic_ios.tcc (basic_ios::_M_cache_locale): Use
	__addressof.
	* include/bits/stream_iterator.h (istream_iterator, ostream_iterator):
	Likewise.
	* include/std/atomic (atomic<_Tp>): Likewise.
	* include/std/shared_mutex (shared_lock): Likewise.
	* testsuite/24_iterators/istream_iterator/70766.cc: New test.
	* testsuite/24_iterators/ostream_iterator/70766.cc : New test.
	* testsuite/29_atomics/atomic/60695.cc: Adjust dg-error line number.
	* testsuite/29_atomics/atomic/70766.cc: New test.
	* testsuite/30_threads/shared_lock/70766.cc: New test.

From-SVN: r235565
---
 libstdc++-v3/ChangeLog                        | 13 +++++
 libstdc++-v3/include/bits/basic_ios.tcc       |  6 +-
 libstdc++-v3/include/bits/stream_iterator.h   |  7 ++-
 libstdc++-v3/include/std/atomic               | 35 ++++++++----
 libstdc++-v3/include/std/shared_mutex         | 15 +++--
 .../24_iterators/istream_iterator/70766.cc    | 44 +++++++++++++++
 .../24_iterators/ostream_iterator/70766.cc    | 37 +++++++++++++
 .../testsuite/29_atomics/atomic/60695.cc      |  2 +-
 .../testsuite/29_atomics/atomic/70766.cc      | 55 +++++++++++++++++++
 .../testsuite/30_threads/shared_lock/70766.cc | 44 +++++++++++++++
 10 files changed, 235 insertions(+), 23 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/24_iterators/istream_iterator/70766.cc
 create mode 100644 libstdc++-v3/testsuite/24_iterators/ostream_iterator/70766.cc
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic/70766.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/shared_lock/70766.cc

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index bbbe7a45d79b..825fef01e531 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,18 @@
 2016-04-28  Jonathan Wakely  <jwakely@redhat.com>
 
+	PR libstdc++/70766
+	* include/bits/basic_ios.tcc (basic_ios::_M_cache_locale): Use
+	__addressof.
+	* include/bits/stream_iterator.h (istream_iterator, ostream_iterator):
+	Likewise.
+	* include/std/atomic (atomic<_Tp>): Likewise.
+	* include/std/shared_mutex (shared_lock): Likewise.
+	* testsuite/24_iterators/istream_iterator/70766.cc: New test.
+	* testsuite/24_iterators/ostream_iterator/70766.cc : New test.
+	* testsuite/29_atomics/atomic/60695.cc: Adjust dg-error line number.
+	* testsuite/29_atomics/atomic/70766.cc: New test.
+	* testsuite/30_threads/shared_lock/70766.cc: New test.
+
 	* include/bits/hashtable_policy.h (__detail::_Insert_base,
 	__detail::_Insert): Improve comments.
 
diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc
index 6c2ea11da16f..04692201a51b 100644
--- a/libstdc++-v3/include/bits/basic_ios.tcc
+++ b/libstdc++-v3/include/bits/basic_ios.tcc
@@ -157,17 +157,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     basic_ios<_CharT, _Traits>::_M_cache_locale(const locale& __loc)
     {
       if (__builtin_expect(has_facet<__ctype_type>(__loc), true))
-	_M_ctype = &use_facet<__ctype_type>(__loc);
+	_M_ctype = std::__addressof(use_facet<__ctype_type>(__loc));
       else
 	_M_ctype = 0;
 
       if (__builtin_expect(has_facet<__num_put_type>(__loc), true))
-	_M_num_put = &use_facet<__num_put_type>(__loc);
+	_M_num_put = std::__addressof(use_facet<__num_put_type>(__loc));
       else
 	_M_num_put = 0;
 
       if (__builtin_expect(has_facet<__num_get_type>(__loc), true))
-	_M_num_get = &use_facet<__num_get_type>(__loc);
+	_M_num_get = std::__addressof(use_facet<__num_get_type>(__loc));
       else
 	_M_num_get = 0;
     }
diff --git a/libstdc++-v3/include/bits/stream_iterator.h b/libstdc++-v3/include/bits/stream_iterator.h
index f9c6ba67c5c2..4afba4e1cbf1 100644
--- a/libstdc++-v3/include/bits/stream_iterator.h
+++ b/libstdc++-v3/include/bits/stream_iterator.h
@@ -66,7 +66,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       ///  Construct start of input stream iterator.
       istream_iterator(istream_type& __s)
-      : _M_stream(&__s)
+      : _M_stream(std::__addressof(__s))
       { _M_read(); }
 
       istream_iterator(const istream_iterator& __obj)
@@ -84,7 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
       const _Tp*
-      operator->() const { return &(operator*()); }
+      operator->() const { return std::__addressof((operator*())); }
 
       istream_iterator&
       operator++()
@@ -168,7 +168,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     public:
       /// Construct from an ostream.
-      ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}
+      ostream_iterator(ostream_type& __s)
+      : _M_stream(std::__addressof(__s)), _M_string(0) {}
 
       /**
        *  Construct from an ostream.
diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic
index bdc1f25e5425..3c8ece85b0b7 100644
--- a/libstdc++-v3/include/std/atomic
+++ b/libstdc++-v3/include/std/atomic
@@ -39,6 +39,7 @@
 #else
 
 #include <bits/atomic_base.h>
+#include <bits/move.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -222,17 +223,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       void
       store(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept
-      { __atomic_store(&_M_i, &__i, __m); }
+      { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), __m); }
 
       void
       store(_Tp __i, memory_order __m = memory_order_seq_cst) volatile noexcept
-      { __atomic_store(&_M_i, &__i, __m); }
+      { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), __m); }
 
       _Tp
       load(memory_order __m = memory_order_seq_cst) const noexcept
       { 
         _Tp tmp;
-	__atomic_load(&_M_i, &tmp, __m);
+	__atomic_load(std::__addressof(_M_i), std::__addressof(tmp), __m);
 	return tmp;
       }
 
@@ -240,7 +241,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
       { 
         _Tp tmp;
-	__atomic_load(&_M_i, &tmp, __m);
+	__atomic_load(std::__addressof(_M_i), std::__addressof(tmp), __m);
 	return tmp;
       }
 
@@ -248,7 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       exchange(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept
       { 
         _Tp tmp;
-	__atomic_exchange(&_M_i, &__i, &tmp, __m);
+	__atomic_exchange(std::__addressof(_M_i), std::__addressof(__i),
+			  std::__addressof(tmp), __m);
 	return tmp;
       }
 
@@ -257,7 +259,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       memory_order __m = memory_order_seq_cst) volatile noexcept
       { 
         _Tp tmp;
-	__atomic_exchange(&_M_i, &__i, &tmp, __m);
+	__atomic_exchange(std::__addressof(_M_i), std::__addressof(__i),
+			  std::__addressof(tmp), __m);
 	return tmp;
       }
 
@@ -265,14 +268,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, 
 			    memory_order __f) noexcept
       {
-	return __atomic_compare_exchange(&_M_i, &__e, &__i, true, __s, __f);
+	return __atomic_compare_exchange(std::__addressof(_M_i),
+					 std::__addressof(__e),
+					 std::__addressof(__i),
+					 true, __s, __f);
       }
 
       bool
       compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, 
 			    memory_order __f) volatile noexcept
       {
-	return __atomic_compare_exchange(&_M_i, &__e, &__i, true, __s, __f);
+	return __atomic_compare_exchange(std::__addressof(_M_i),
+					 std::__addressof(__e),
+					 std::__addressof(__i),
+					 true, __s, __f);
       }
 
       bool
@@ -291,14 +300,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, 
 			      memory_order __f) noexcept
       {
-	return __atomic_compare_exchange(&_M_i, &__e, &__i, false, __s, __f);
+	return __atomic_compare_exchange(std::__addressof(_M_i),
+					 std::__addressof(__e),
+					 std::__addressof(__i),
+					 false, __s, __f);
       }
 
       bool
       compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, 
 			      memory_order __f) volatile noexcept
       {
-	return __atomic_compare_exchange(&_M_i, &__e, &__i, false, __s, __f);
+	return __atomic_compare_exchange(std::__addressof(_M_i),
+					 std::__addressof(__e),
+					 std::__addressof(__i),
+					 false, __s, __f);
       }
 
       bool
diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex
index d87ac5690e77..6ca322b44e8a 100644
--- a/libstdc++-v3/include/std/shared_mutex
+++ b/libstdc++-v3/include/std/shared_mutex
@@ -550,27 +550,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       shared_lock() noexcept : _M_pm(nullptr), _M_owns(false) { }
 
       explicit
-      shared_lock(mutex_type& __m) : _M_pm(&__m), _M_owns(true)
+      shared_lock(mutex_type& __m)
+      : _M_pm(std::__addressof(__m)), _M_owns(true)
       { __m.lock_shared(); }
 
       shared_lock(mutex_type& __m, defer_lock_t) noexcept
-      : _M_pm(&__m), _M_owns(false) { }
+      : _M_pm(std::__addressof(__m)), _M_owns(false) { }
 
       shared_lock(mutex_type& __m, try_to_lock_t)
-      : _M_pm(&__m), _M_owns(__m.try_lock_shared()) { }
+      : _M_pm(std::__addressof(__m)), _M_owns(__m.try_lock_shared()) { }
 
       shared_lock(mutex_type& __m, adopt_lock_t)
-      : _M_pm(&__m), _M_owns(true) { }
+      : _M_pm(std::__addressof(__m)), _M_owns(true) { }
 
       template<typename _Clock, typename _Duration>
 	shared_lock(mutex_type& __m,
 		    const chrono::time_point<_Clock, _Duration>& __abs_time)
-      : _M_pm(&__m), _M_owns(__m.try_lock_shared_until(__abs_time)) { }
+      : _M_pm(std::__addressof(__m)),
+	_M_owns(__m.try_lock_shared_until(__abs_time)) { }
 
       template<typename _Rep, typename _Period>
 	shared_lock(mutex_type& __m,
 		    const chrono::duration<_Rep, _Period>& __rel_time)
-      : _M_pm(&__m), _M_owns(__m.try_lock_shared_for(__rel_time)) { }
+      : _M_pm(std::__addressof(__m)),
+	_M_owns(__m.try_lock_shared_for(__rel_time)) { }
 
       ~shared_lock()
       {
diff --git a/libstdc++-v3/testsuite/24_iterators/istream_iterator/70766.cc b/libstdc++-v3/testsuite/24_iterators/istream_iterator/70766.cc
new file mode 100644
index 000000000000..3018e346477c
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/istream_iterator/70766.cc
@@ -0,0 +1,44 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <iterator>
+#include <istream>
+
+namespace adl
+{
+  template<typename T>
+    void operator&(const T&) = delete;
+
+  struct traits : std::char_traits<char> { };
+
+  struct X { void f() const { } };
+
+  std::basic_istream<char, adl::traits>&
+  operator>>(std::basic_istream<char, adl::traits>& is, X&)
+  { return is; }
+}
+
+void
+test01()
+{
+  std::basic_istream<char, adl::traits> is(nullptr);
+  std::istream_iterator<adl::X, char, adl::traits> ii(is);
+  ii->f();
+}
diff --git a/libstdc++-v3/testsuite/24_iterators/ostream_iterator/70766.cc b/libstdc++-v3/testsuite/24_iterators/ostream_iterator/70766.cc
new file mode 100644
index 000000000000..1f6b94358bea
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/ostream_iterator/70766.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <iterator>
+#include <ostream>
+
+namespace adl
+{
+  template<typename T>
+    void operator&(const T&) = delete;
+
+  struct traits : std::char_traits<char> { };
+}
+
+void
+test01()
+{
+  std::basic_ostream<char, adl::traits> os(nullptr);
+  std::ostream_iterator<int, char, adl::traits> oi(os);
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc b/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc
index ddd1b2ca0517..5977d54760c5 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc
@@ -27,4 +27,4 @@ struct X {
   char stuff[0]; // GNU extension, type has zero size
 };
 
-std::atomic<X> a;  // { dg-error "not supported" "" { target *-*-* } 181 }
+std::atomic<X> a;  // { dg-error "not supported" "" { target *-*-* } 182 }
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/70766.cc b/libstdc++-v3/testsuite/29_atomics/atomic/70766.cc
new file mode 100644
index 000000000000..1390e4e4de5d
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/70766.cc
@@ -0,0 +1,55 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <atomic>
+
+namespace adl
+{
+  template<typename T>
+    void operator&(const T&) = delete;
+
+  struct X {
+    int i;
+  };
+}
+
+void
+test01()
+{
+  adl::X x;
+  std::atomic<adl::X> a;
+  a.store(x);
+  x = a.load();
+  x = a.exchange(x);
+  a.compare_exchange_weak(x, x);
+  a.compare_exchange_strong(x, x);
+}
+
+void
+test02()
+{
+  adl::X x;
+  volatile std::atomic<adl::X> a;
+  a.store(x);
+  x = a.load();
+  x = a.exchange(x);
+  a.compare_exchange_weak(x, x);
+  a.compare_exchange_strong(x, x);
+}
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/70766.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/70766.cc
new file mode 100644
index 000000000000..940b7b17281d
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/70766.cc
@@ -0,0 +1,44 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+#include <shared_mutex>
+
+namespace adl
+{
+  template<typename T>
+    void operator&(const T&) = delete;
+
+  struct M : std::shared_timed_mutex { };
+}
+
+void
+test01()
+{
+  using namespace std::chrono_literals;
+
+  adl::M m;
+  std::shared_lock<adl::M> l1(m);
+  std::shared_lock<adl::M> l2(m, std::defer_lock);
+  std::shared_lock<adl::M> l3(m, std::try_to_lock);
+  m.lock_shared();
+  std::shared_lock<adl::M> l4(m, std::adopt_lock);
+  std::shared_lock<adl::M> l5(m, std::chrono::system_clock::now() + 1ms);
+  std::shared_lock<adl::M> l6(m, 1ms);
+}
-- 
GitLab