> Different patch attached?
Indeed, sorry. Here's the right one.
-benjamin
2012-02-03 Benjamin Kosnik <b...@redhat.com>
PR libstdc++/51811
* include/bits/atomic_base.h (atomic<_Tp*>): Fix offsets.
* testsuite/29_atomics/atomic/operators/51811.cc: New.
* testsuite/29_atomics/atomic/operators/pointer_partial_void.cc: New.
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index aa43bcc..9d5f4eb 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -1,6 +1,6 @@
// -*- C++ -*- header.
-// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011, 2012 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
@@ -621,6 +621,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__pointer_type _M_p;
+ // Factored out to facilitate explicit specialization.
+ constexpr ptrdiff_t
+ _M_type_size(ptrdiff_t __d) { return __d * sizeof(_PTp); }
+
+ constexpr ptrdiff_t
+ _M_type_size(ptrdiff_t __d) volatile { return __d * sizeof(_PTp); }
+
public:
__atomic_base() noexcept = default;
~__atomic_base() noexcept = default;
@@ -669,43 +676,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__pointer_type
operator++() noexcept
- { return __atomic_add_fetch(&_M_p, 1, memory_order_seq_cst); }
+ { return __atomic_add_fetch(&_M_p, _M_type_size(1),
+ memory_order_seq_cst); }
__pointer_type
operator++() volatile noexcept
- { return __atomic_add_fetch(&_M_p, 1, memory_order_seq_cst); }
+ { return __atomic_add_fetch(&_M_p, _M_type_size(1),
+ memory_order_seq_cst); }
__pointer_type
operator--() noexcept
- { return __atomic_sub_fetch(&_M_p, 1, memory_order_seq_cst); }
+ { return __atomic_sub_fetch(&_M_p, _M_type_size(1),
+ memory_order_seq_cst); }
__pointer_type
operator--() volatile noexcept
- { return __atomic_sub_fetch(&_M_p, 1, memory_order_seq_cst); }
+ { return __atomic_sub_fetch(&_M_p, _M_type_size(1),
+ memory_order_seq_cst); }
__pointer_type
operator+=(ptrdiff_t __d) noexcept
- { return __atomic_add_fetch(&_M_p, __d, memory_order_seq_cst); }
+ { return __atomic_add_fetch(&_M_p, _M_type_size(__d),
+ memory_order_seq_cst); }
__pointer_type
operator+=(ptrdiff_t __d) volatile noexcept
- { return __atomic_add_fetch(&_M_p, __d, memory_order_seq_cst); }
+ { return __atomic_add_fetch(&_M_p, _M_type_size(__d),
+ memory_order_seq_cst); }
__pointer_type
operator-=(ptrdiff_t __d) noexcept
- { return __atomic_sub_fetch(&_M_p, __d, memory_order_seq_cst); }
+ { return __atomic_sub_fetch(&_M_p, _M_type_size(__d),
+ memory_order_seq_cst); }
__pointer_type
operator-=(ptrdiff_t __d) volatile noexcept
- { return __atomic_sub_fetch(&_M_p, __d, memory_order_seq_cst); }
+ { return __atomic_sub_fetch(&_M_p, _M_type_size(__d),
+ memory_order_seq_cst); }
bool
is_lock_free() const noexcept
- { return __atomic_is_lock_free (sizeof (_M_p), &_M_p); }
+ { return __atomic_is_lock_free(_M_type_size(1), &_M_p); }
bool
is_lock_free() const volatile noexcept
- { return __atomic_is_lock_free (sizeof (_M_p), &_M_p); }
+ { return __atomic_is_lock_free(_M_type_size(1), &_M_p); }
void
store(__pointer_type __p,
@@ -789,22 +804,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__pointer_type
fetch_add(ptrdiff_t __d,
memory_order __m = memory_order_seq_cst) noexcept
- { return __atomic_fetch_add(&_M_p, __d, __m); }
+ { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); }
__pointer_type
fetch_add(ptrdiff_t __d,
memory_order __m = memory_order_seq_cst) volatile noexcept
- { return __atomic_fetch_add(&_M_p, __d, __m); }
+ { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); }
__pointer_type
fetch_sub(ptrdiff_t __d,
memory_order __m = memory_order_seq_cst) noexcept
- { return __atomic_fetch_sub(&_M_p, __d, __m); }
+ { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); }
__pointer_type
fetch_sub(ptrdiff_t __d,
memory_order __m = memory_order_seq_cst) volatile noexcept
- { return __atomic_fetch_sub(&_M_p, __d, __m); }
+ { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); }
};
// @} group atomics
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/operators/51811.cc b/libstdc++-v3/testsuite/29_atomics/atomic/operators/51811.cc
new file mode 100644
index 0000000..7c234f2
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/operators/51811.cc
@@ -0,0 +1,90 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2012 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/>.
+
+#include <atomic>
+#include <cstdlib> //std::abs
+#include <testsuite_hooks.h>
+
+// libstdc++/51811
+// pointer arithimetic vs. atomic<_Tp*> specialization
+int main(void)
+{
+ bool test __attribute__((unused)) = true;
+
+ using namespace std;
+
+ typedef int value_type;
+ const size_t n = 2;
+ value_type value = 42;
+ atomic<value_type*> p, p2, p3;
+
+ // operator++
+ {
+ p = &value;
+ p2 = p++;
+ VERIFY (p != p2);
+
+ value_type* vp(p);
+ value_type* vp2(p2);
+ ptrdiff_t dist = reinterpret_cast<char*>(vp) - reinterpret_cast<char*>(vp2);
+ VERIFY ( std::abs(dist) == sizeof(value_type));
+
+ p = &value;
+ p3 = ++p;
+ VERIFY (p == p3);
+ }
+
+ // operator--
+ {
+ p = &value;
+ p2 = p--;
+ VERIFY (p != p2);
+
+ value_type* vp(p);
+ value_type* vp2(p2);
+ ptrdiff_t dist = reinterpret_cast<char*>(vp) - reinterpret_cast<char*>(vp2);
+ VERIFY ( std::abs(dist) == sizeof(value_type));
+
+ p = &value;
+ p3 = --p;
+ VERIFY (p == p3);
+ }
+
+ // operator+=
+ {
+ p = &value;
+ value_type* vp(p);
+ p+=n;
+ value_type* vp2(p);
+ ptrdiff_t dist = reinterpret_cast<char*>(vp) - reinterpret_cast<char*>(vp2);
+ VERIFY ( std::abs(dist) == sizeof(value_type) * n);
+ }
+
+ // operator-=
+ {
+ p = &value;
+ value_type* vp(p);
+ p-=n;
+ value_type* vp2(p);
+ ptrdiff_t dist = reinterpret_cast<char*>(vp) - reinterpret_cast<char*>(vp2);
+ VERIFY ( std::abs(dist) == sizeof(value_type) * n);
+ }
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc b/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc
new file mode 100644
index 0000000..09a4d44
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc
@@ -0,0 +1,70 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2012 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/>.
+
+#include <atomic>
+#include <cstdlib> //std::abs
+#include <testsuite_hooks.h>
+
+// pointer arithimetic vs. atomic<void*>.
+// atomic<void*> vs. explicitly specialized w/o operators, like atomic_bool?
+int main(void)
+{
+ // bool test __attribute__((unused)) = true;
+
+ using namespace std;
+
+ typedef int value_type;
+ const size_t n = 2;
+ value_type value = 42;
+ value_type* p = &value;
+ void* vp = p;
+ ptrdiff_t dist(0);
+
+ atomic<void*> a(vp);
+
+ // operator++
+ void* vp2(a);
+ a++;
+ void* vp3(a);
+ dist = reinterpret_cast<char*>(vp2) - reinterpret_cast<char*>(vp3);
+ // VERIFY ( std::abs(dist) == sizeof(void*));
+
+ // operator--
+ void* vp4(a);
+ a--;
+ void* vp5(a);
+ dist = reinterpret_cast<char*>(vp4) - reinterpret_cast<char*>(vp5);
+ // VERIFY ( std::abs(dist) == sizeof(void*));
+
+ // operator+=
+ void* vp6(a);
+ a+=n;
+ void* vp7(a);
+ dist = reinterpret_cast<char*>(vp6) - reinterpret_cast<char*>(vp7);
+ // VERIFY ( std::abs(dist) == sizeof(void*) * n);
+
+ // operator-=
+ void* vp8(a);
+ a-=n;
+ void* vp9(a);
+ dist = reinterpret_cast<char*>(vp8) - reinterpret_cast<char*>(vp9);
+ //VERIFY ( std::abs(dist) == sizeof(void*) * n);
+
+ return 0;
+}