re PR libstdc++/48760 (std::complex constructor buggy in the face of NaN's)
authorPaolo Carlini <paolo.carlini@oracle.com>
Thu, 28 Apr 2011 10:52:17 +0000 (10:52 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Thu, 28 Apr 2011 10:52:17 +0000 (10:52 +0000)
2011-04-28  Paolo Carlini  <paolo.carlini@oracle.com>

PR libstdc++/48760
* include/std/complex (complex<float>::complex(float, float),
complex<double>::complex(double, double),
complex<long double>::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  <paolo.carlini@oracle.com>

* include/std/bitset (_Base_bitset(unsigned long long)): Minor
tweak, remove redundant round braces.

From-SVN: r173065

12 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/parallel/losertree.h
libstdc++-v3/include/parallel/multiway_merge.h
libstdc++-v3/include/parallel/multiway_mergesort.h
libstdc++-v3/include/parallel/par_loop.h
libstdc++-v3/include/parallel/partial_sum.h
libstdc++-v3/include/parallel/quicksort.h
libstdc++-v3/include/parallel/random_shuffle.h
libstdc++-v3/include/std/bitset
libstdc++-v3/include/std/complex
libstdc++-v3/testsuite/26_numerics/complex/cons/48760.cc [new file with mode: 0644]
libstdc++-v3/testsuite/26_numerics/complex/cons/48760_c++0x.cc [new file with mode: 0644]

index 901e7b8f2d0fe29873f7776245238f6b5523904a..ffb034664018f6bc8ae8b5fecf782c359943e687 100644 (file)
@@ -1,3 +1,19 @@
+2011-04-28  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR libstdc++/48760
+       * include/std/complex (complex<float>::complex(float, float),
+       complex<double>::complex(double, double),
+       complex<long double>::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  <paolo.carlini@oracle.com>
+
+       * include/std/bitset (_Base_bitset(unsigned long long)): Minor
+       tweak, remove redundant round braces.
+
 2011-04-27  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * include/bits/move.h (move_if_noexcept): Add.
index 8d7b137aaf56d22f411113650d3e94dd0d732820..306fcd8856fa941252c5f374598e2a79e6657bd9 100644 (file)
@@ -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;
       }
     };
index a5fd3be1bd08e859ab9ea0636e6b9102277f96d4..1c73ad0042db8b93acbc8c57483c9b25fad9bfa0 100644 (file)
@@ -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<std::pair<_DifferenceType, _DifferenceType> >* __pieces;
 
index 2cb8013876699d06f787dbab162ca79a4919e600..80267f923b5554a4f54fae70c8fdd42a4f2060af 100644 (file)
@@ -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;
index 9671c1dd398a5de012f4ee99ea39ffb04d4ff577..d9116908567b5d68b0b2596bdaad25ed89b475a2 100644 (file)
@@ -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;
index 425e868fe6bb699f2e41be80f8b24543f11b3312..1a7697a6cefc83622c19157f63a9c1dbbb40f822 100644 (file)
@@ -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;
index 1884eb867fada377915235ce1b883fefedc99eb1..1b4d5983d06c4e500196dab3622797474cb0449b 100644 (file)
@@ -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;
index bae95724966b8462fd924f366062e1cd8c4a155b..c3967c22880b6552a91f2acd478f6f257532a437 100644 (file)
@@ -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
index e0e8f1340f41323045ff4414785277ff39deda09..381a0421a54abe7e3edd357cb35f6564cc38216c 100644 (file)
@@ -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()
index d36eddca5a6d5a3f03aa21b53833527591d6fb3c..0ce7e55343f93b6274d1612aaa41a47e8936a6b5 100644 (file)
@@ -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<double>&);
       explicit _GLIBCXX_CONSTEXPR complex(const complex<long double>&);        
@@ -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<float>& __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<float>& __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 (file)
index 0000000..0201cc7
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <limits>
+#include <testsuite_hooks.h>
+
+template<typename T>
+  void do_test01()
+  {
+    bool test __attribute__((unused)) = true;
+
+    if (std::numeric_limits<T>::has_quiet_NaN)
+      {
+       std::complex<T> c1(T(0), std::numeric_limits<T>::quiet_NaN());
+       VERIFY( c1.real() == T(0) );
+       VERIFY( std::isnan(c1.imag()) );
+
+       std::complex<T> c2(std::numeric_limits<T>::quiet_NaN(), T(0));
+       VERIFY( std::isnan(c2.real()) );
+       VERIFY( c2.imag() == T(0) );
+
+       std::complex<T> c3(std::numeric_limits<T>::quiet_NaN(),
+                          std::numeric_limits<T>::quiet_NaN());
+       VERIFY( std::isnan(c3.real()) );
+       VERIFY( std::isnan(c3.imag()) );
+      }
+  }
+
+// libstdc++/48760
+void test01()
+{
+  do_test01<float>();
+  do_test01<double>();
+  do_test01<long double>();
+}
+
+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 (file)
index 0000000..f0017b1
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <limits>
+#include <testsuite_hooks.h>
+
+template<typename T>
+  void do_test01()
+  {
+    bool test __attribute__((unused)) = true;
+
+    if (std::numeric_limits<T>::has_quiet_NaN)
+      {
+       std::complex<T> c1(T(0), std::numeric_limits<T>::quiet_NaN());
+       VERIFY( c1.real() == T(0) );
+       VERIFY( std::isnan(c1.imag()) );
+
+       std::complex<T> c2(std::numeric_limits<T>::quiet_NaN(), T(0));
+       VERIFY( std::isnan(c2.real()) );
+       VERIFY( c2.imag() == T(0) );
+
+       std::complex<T> c3(std::numeric_limits<T>::quiet_NaN(),
+                          std::numeric_limits<T>::quiet_NaN());
+       VERIFY( std::isnan(c3.real()) );
+       VERIFY( std::isnan(c3.imag()) );
+      }
+  }
+
+// libstdc++/48760
+void test01()
+{
+  do_test01<float>();
+  do_test01<double>();
+  do_test01<long double>();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}