From 9f1163b171df2a6f9faec0af92c7e651bf69db72 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Thu, 28 Apr 2011 10:52:17 +0000 Subject: [PATCH] re PR libstdc++/48760 (std::complex constructor buggy in the face of NaN's) 2011-04-28 Paolo Carlini PR libstdc++/48760 * include/std/complex (complex::complex(float, float), complex::complex(double, double), complex::complex(long double, long double)): Use list-initialization in C++0x mode, initialize in the body in C++03 mode. * testsuite/26_numerics/complex/cons/48760.cc: New. * testsuite/26_numerics/complex/cons/48760_c++0x.cc: Likewise. 2011-04-28 Paolo Carlini * include/std/bitset (_Base_bitset(unsigned long long)): Minor tweak, remove redundant round braces. From-SVN: r173065 --- libstdc++-v3/ChangeLog | 16 +++++ libstdc++-v3/include/parallel/losertree.h | 26 ++++++--- .../include/parallel/multiway_merge.h | 19 +++--- .../include/parallel/multiway_mergesort.h | 11 +++- libstdc++-v3/include/parallel/par_loop.h | 19 ++++-- libstdc++-v3/include/parallel/partial_sum.h | 3 + libstdc++-v3/include/parallel/quicksort.h | 4 +- .../include/parallel/random_shuffle.h | 13 +++-- libstdc++-v3/include/std/bitset | 4 +- libstdc++-v3/include/std/complex | 29 ++++++++-- .../26_numerics/complex/cons/48760.cc | 56 ++++++++++++++++++ .../26_numerics/complex/cons/48760_c++0x.cc | 58 +++++++++++++++++++ 12 files changed, 223 insertions(+), 35 deletions(-) create mode 100644 libstdc++-v3/testsuite/26_numerics/complex/cons/48760.cc create mode 100644 libstdc++-v3/testsuite/26_numerics/complex/cons/48760_c++0x.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 901e7b8f2d0..ffb03466401 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,19 @@ +2011-04-28 Paolo Carlini + + PR libstdc++/48760 + * include/std/complex (complex::complex(float, float), + complex::complex(double, double), + complex::complex(long double, long double)): Use + list-initialization in C++0x mode, initialize in the body in + C++03 mode. + * testsuite/26_numerics/complex/cons/48760.cc: New. + * testsuite/26_numerics/complex/cons/48760_c++0x.cc: Likewise. + +2011-04-28 Paolo Carlini + + * include/std/bitset (_Base_bitset(unsigned long long)): Minor + tweak, remove redundant round braces. + 2011-04-27 Paolo Carlini * include/bits/move.h (move_if_noexcept): Add. diff --git a/libstdc++-v3/include/parallel/losertree.h b/libstdc++-v3/include/parallel/losertree.h index 8d7b137aaf5..306fcd8856f 100644 --- a/libstdc++-v3/include/parallel/losertree.h +++ b/libstdc++-v3/include/parallel/losertree.h @@ -1,6 +1,6 @@ // -*- C++ -*- -// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. +// Copyright (C) 2007, 2008, 2009, 2010, 2011 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 @@ -116,7 +116,11 @@ namespace __gnu_parallel * @brief The destructor. */ ~_LoserTreeBase() - { ::operator delete(_M_losers); } + { + for (unsigned int __i = 0; __i < (2 * _M_k); ++__i) + _M_losers[__i].~_Loser(); + ::operator delete(_M_losers); + } /** * @brief Initializes the sequence "_M_source" with the element "__key". @@ -131,15 +135,15 @@ namespace __gnu_parallel { unsigned int __pos = _M_k + __source; - if(_M_first_insert) + if (_M_first_insert) { - // Construct all keys, so we can easily deconstruct them. + // Construct all keys, so we can easily destruct them. for (unsigned int __i = 0; __i < (2 * _M_k); ++__i) new(&(_M_losers[__i]._M_key)) _Tp(__key); _M_first_insert = false; } else - new(&(_M_losers[__pos]._M_key)) _Tp(__key); + _M_losers[__pos]._M_key = __key; _M_losers[__pos]._M_sup = __sup; _M_losers[__pos]._M_source = __source; @@ -379,7 +383,7 @@ namespace __gnu_parallel } ~_LoserTreePointerBase() - { ::operator delete[](_M_losers); } + { delete[] _M_losers; } int __get_min_source() { return _M_losers[0]._M_source; } @@ -592,13 +596,17 @@ namespace __gnu_parallel for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i) { - _M_losers[__i]._M_key = __sentinel; + ::new(&(_M_losers[__i]._M_key)) _Tp(__sentinel); _M_losers[__i]._M_source = -1; } } ~_LoserTreeUnguardedBase() - { ::operator delete(_M_losers); } + { + for (unsigned int __i = 0; __i < (2 * _M_k); ++__i) + _M_losers[__i].~_Loser(); + ::operator delete(_M_losers); + } int __get_min_source() @@ -615,7 +623,7 @@ namespace __gnu_parallel { unsigned int __pos = _M_k + __source; - new(&(_M_losers[__pos]._M_key)) _Tp(__key); + ::new(&(_M_losers[__pos]._M_key)) _Tp(__key); _M_losers[__pos]._M_source = __source; } }; diff --git a/libstdc++-v3/include/parallel/multiway_merge.h b/libstdc++-v3/include/parallel/multiway_merge.h index a5fd3be1bd0..1c73ad0042d 100644 --- a/libstdc++-v3/include/parallel/multiway_merge.h +++ b/libstdc++-v3/include/parallel/multiway_merge.h @@ -1045,11 +1045,12 @@ namespace __gnu_parallel _ValueType; // __k sequences. - _SeqNumber __k = static_cast<_SeqNumber>(__seqs_end - __seqs_begin); + const _SeqNumber __k + = static_cast<_SeqNumber>(__seqs_end - __seqs_begin); - _ThreadIndex __num_threads = omp_get_num_threads(); + const _ThreadIndex __num_threads = omp_get_num_threads(); - _DifferenceType __num_samples = + const _DifferenceType __num_samples = __gnu_parallel::_Settings::get().merge_oversampling * __num_threads; _ValueType* __samples = static_cast<_ValueType*> @@ -1096,6 +1097,10 @@ namespace __gnu_parallel __pieces[__slab][__seq].second = _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]); } + + for (_SeqNumber __s = 0; __s < __k; ++__s) + for (_DifferenceType __i = 0; __i < __num_samples; ++__i) + __samples[__s * __num_samples + __i].~_ValueType(); ::operator delete(__samples); } @@ -1258,10 +1263,10 @@ namespace __gnu_parallel __length = std::min<_DifferenceTp>(__length, __total_length); if (__total_length == 0 || __k == 0) - { - delete[] __ne_seqs; - return __target; - } + { + delete[] __ne_seqs; + return __target; + } std::vector >* __pieces; diff --git a/libstdc++-v3/include/parallel/multiway_mergesort.h b/libstdc++-v3/include/parallel/multiway_mergesort.h index 2cb80138766..80267f923b5 100644 --- a/libstdc++-v3/include/parallel/multiway_mergesort.h +++ b/libstdc++-v3/include/parallel/multiway_mergesort.h @@ -378,6 +378,8 @@ namespace __gnu_parallel # pragma omp barrier + for (_DifferenceType __i = 0; __i < __length_local; ++__i) + __sd->_M_temporary[__iam][__i].~_ValueType(); ::operator delete(__sd->_M_temporary[__iam]); } @@ -413,6 +415,7 @@ namespace __gnu_parallel // shared variables _PMWMSSortingData<_RAIter> __sd; _DifferenceType* __starts; + _DifferenceType __size; # pragma omp parallel num_threads(__num_threads) { @@ -427,7 +430,7 @@ namespace __gnu_parallel if (!__exact) { - _DifferenceType __size = + __size = (_Settings::get().sort_mwms_oversampling * __num_threads - 1) * __num_threads; __sd._M_samples = static_cast<_ValueType*> @@ -463,7 +466,11 @@ namespace __gnu_parallel delete[] __sd._M_temporary; if (!__exact) - ::operator delete(__sd._M_samples); + { + for (_DifferenceType __i = 0; __i < __size; ++__i) + __sd._M_samples[__i].~_ValueType(); + ::operator delete(__sd._M_samples); + } delete[] __sd._M_offsets; delete[] __sd._M_pieces; diff --git a/libstdc++-v3/include/parallel/par_loop.h b/libstdc++-v3/include/parallel/par_loop.h index 9671c1dd398..d9116908567 100644 --- a/libstdc++-v3/include/parallel/par_loop.h +++ b/libstdc++-v3/include/parallel/par_loop.h @@ -91,8 +91,7 @@ namespace __gnu_parallel _ThreadIndex __iam = omp_get_thread_num(); // Neutral element. - _Result* __reduct = static_cast<_Result*> - (::operator new(sizeof(_Result))); + _Result* __reduct; _DifferenceType __start = __equally_split_point(__length, __num_threads, __iam), @@ -100,7 +99,7 @@ namespace __gnu_parallel if (__start < __stop) { - new(__reduct) _Result(__f(__o, __begin + __start)); + __reduct = new _Result(__f(__o, __begin + __start)); ++__start; __constructed[__iam] = true; } @@ -110,18 +109,26 @@ namespace __gnu_parallel for (; __start < __stop; ++__start) *__reduct = __r(*__reduct, __f(__o, __begin + __start)); - __thread_results[__iam] = *__reduct; + if (__constructed[__iam]) + { + ::new(&__thread_results[__iam]) _Result(*__reduct); + delete __reduct; + } } //parallel for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) if (__constructed[__i]) - __output = __r(__output, __thread_results[__i]); + { + __output = __r(__output, __thread_results[__i]); + __thread_results[__i].~_Result(); + } // Points to last element processed (needed as return value for // some algorithms like transform). __f._M_finish_iterator = __begin + __length; - delete[] __thread_results; + ::operator delete(__thread_results); + delete[] __constructed; return __o; diff --git a/libstdc++-v3/include/parallel/partial_sum.h b/libstdc++-v3/include/parallel/partial_sum.h index 425e868fe6b..1a7697a6cef 100644 --- a/libstdc++-v3/include/parallel/partial_sum.h +++ b/libstdc++-v3/include/parallel/partial_sum.h @@ -184,7 +184,10 @@ namespace __gnu_parallel __bin_op, __sums[__iam]); } //parallel + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + __sums[__i].~_ValueType(); ::operator delete(__sums); + delete[] __borders; return __result + __n; diff --git a/libstdc++-v3/include/parallel/quicksort.h b/libstdc++-v3/include/parallel/quicksort.h index 1884eb867fa..1b4d5983d06 100644 --- a/libstdc++-v3/include/parallel/quicksort.h +++ b/libstdc++-v3/include/parallel/quicksort.h @@ -1,6 +1,6 @@ // -*- C++ -*- -// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2007, 2008, 2009, 2010, 2011 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 @@ -82,6 +82,8 @@ namespace __gnu_parallel _DifferenceType __split = __parallel_partition(__begin, __end, __pred, __num_threads); + for (_DifferenceType __s = 0; __s < __num_samples; ++__s) + __samples[__s].~_ValueType(); ::operator delete(__samples); return __split; diff --git a/libstdc++-v3/include/parallel/random_shuffle.h b/libstdc++-v3/include/parallel/random_shuffle.h index bae95724966..c3967c22880 100644 --- a/libstdc++-v3/include/parallel/random_shuffle.h +++ b/libstdc++-v3/include/parallel/random_shuffle.h @@ -1,6 +1,6 @@ // -*- C++ -*- -// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2007, 2008, 2009, 2010, 2011 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 @@ -209,7 +209,7 @@ namespace __gnu_parallel _ThreadIndex __target_p = __bin_proc[__target_bin]; // Last column [__d->_M_num_threads] stays unchanged. - ::new(&(__temporaries[__target_p][__dist[__target_bin + 1]++])) + ::new(&(__temporaries[__target_p][__dist[__target_bin + 1]++])) _ValueType(*(__source + __i + __start)); } @@ -227,8 +227,8 @@ namespace __gnu_parallel (__sd->_M_temporaries[__iam] + (__b == __d->_M_bins_begin ? 0 : __sd->_M_dist[__b][__d->_M_num_threads])), - * __end = (__sd->_M_temporaries[__iam] - + __sd->_M_dist[__b + 1][__d->_M_num_threads]); + *__end = (__sd->_M_temporaries[__iam] + + __sd->_M_dist[__b + 1][__d->_M_num_threads]); __sequential_random_shuffle(__begin, __end, __rng); std::copy(__begin, __end, __sd->_M_source + __global_offset @@ -236,6 +236,8 @@ namespace __gnu_parallel ? 0 : __sd->_M_dist[__b][__d->_M_num_threads])); } + for (_SequenceIndex __i = 0; __i < __offset; ++__i) + __sd->_M_temporaries[__iam][__i].~_ValueType(); ::operator delete(__sd->_M_temporaries[__iam]); } @@ -501,6 +503,9 @@ namespace __gnu_parallel delete[] __dist0; delete[] __dist1; delete[] __oracles; + + for (_DifferenceType __i = 0; __i < __n; ++__i) + __target[__i].~_ValueType(); ::operator delete(__target); } else diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index e0e8f1340f4..381a0421a54 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -80,11 +80,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #ifdef __GXX_EXPERIMENTAL_CXX0X__ constexpr _Base_bitset(unsigned long long __val) - : _M_w({ _WordT(__val) + : _M_w{ _WordT(__val) #if __SIZEOF_LONG_LONG__ > __SIZEOF_LONG__ , _WordT(__val >> _GLIBCXX_BITSET_BITS_PER_WORD) #endif - }) { } + } { } #else _Base_bitset(unsigned long __val) : _M_w() diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index d36eddca5a6..0ce7e55343f 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -1,7 +1,7 @@ // The template and inlines for the -*- C++ -*- complex number classes. // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2007, 2008, 2009, 2010 +// 2006, 2007, 2008, 2009, 2010, 2011 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -1046,7 +1046,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } _GLIBCXX_CONSTEXPR complex(float __r = 0.0f, float __i = 0.0f) - : _M_value(__r + __i * 1.0fi) { } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif explicit _GLIBCXX_CONSTEXPR complex(const complex&); explicit _GLIBCXX_CONSTEXPR complex(const complex&); @@ -1186,7 +1193,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } _GLIBCXX_CONSTEXPR complex(double __r = 0.0, double __i = 0.0) - : _M_value(__r + __i * 1.0i) { } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } @@ -1328,7 +1342,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_CONSTEXPR complex(long double __r = 0.0L, long double __i = 0.0L) - : _M_value(__r + __i * 1.0Li) { } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } diff --git a/libstdc++-v3/testsuite/26_numerics/complex/cons/48760.cc b/libstdc++-v3/testsuite/26_numerics/complex/cons/48760.cc new file mode 100644 index 00000000000..0201cc7dca0 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/complex/cons/48760.cc @@ -0,0 +1,56 @@ +// Copyright (C) 2011 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 +// . + +#include +#include +#include + +template + void do_test01() + { + bool test __attribute__((unused)) = true; + + if (std::numeric_limits::has_quiet_NaN) + { + std::complex c1(T(0), std::numeric_limits::quiet_NaN()); + VERIFY( c1.real() == T(0) ); + VERIFY( std::isnan(c1.imag()) ); + + std::complex c2(std::numeric_limits::quiet_NaN(), T(0)); + VERIFY( std::isnan(c2.real()) ); + VERIFY( c2.imag() == T(0) ); + + std::complex c3(std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()); + VERIFY( std::isnan(c3.real()) ); + VERIFY( std::isnan(c3.imag()) ); + } + } + +// libstdc++/48760 +void test01() +{ + do_test01(); + do_test01(); + do_test01(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/26_numerics/complex/cons/48760_c++0x.cc b/libstdc++-v3/testsuite/26_numerics/complex/cons/48760_c++0x.cc new file mode 100644 index 00000000000..f0017b113d0 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/complex/cons/48760_c++0x.cc @@ -0,0 +1,58 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2011 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 +// . + +#include +#include +#include + +template + void do_test01() + { + bool test __attribute__((unused)) = true; + + if (std::numeric_limits::has_quiet_NaN) + { + std::complex c1(T(0), std::numeric_limits::quiet_NaN()); + VERIFY( c1.real() == T(0) ); + VERIFY( std::isnan(c1.imag()) ); + + std::complex c2(std::numeric_limits::quiet_NaN(), T(0)); + VERIFY( std::isnan(c2.real()) ); + VERIFY( c2.imag() == T(0) ); + + std::complex c3(std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()); + VERIFY( std::isnan(c3.real()) ); + VERIFY( std::isnan(c3.imag()) ); + } + } + +// libstdc++/48760 +void test01() +{ + do_test01(); + do_test01(); + do_test01(); +} + +int main() +{ + test01(); + return 0; +} -- 2.30.2