re PR libstdc++/51811 ([C++0x] Incorrect increment/decrement of atomic pointers)

2012-02-03  Benjamin Kosnik  <bkoz@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.

From-SVN: r183875
This commit is contained in:
Benjamin Kosnik 2012-02-03 19:49:11 +00:00 committed by Benjamin Kosnik
parent 3bc05470eb
commit 4035739819
4 changed files with 197 additions and 15 deletions

View File

@ -1,3 +1,10 @@
2012-02-03 Benjamin Kosnik <bkoz@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.
2012-02-03 Jakub Jelinek <jakub@redhat.com>
* config/abi/post/i386-linux-gnu/baseline_symbols.txt: Update.

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}