Patchwork [v3] Fix libstdc++/50268

login
register
mail settings
Submitter Paolo Carlini
Date Sept. 2, 2011, 10:35 a.m.
Message ID <4E60B161.7080703@oracle.com>
Download mbox | patch
Permalink /patch/113104/
State New
Headers show

Comments

Paolo Carlini - Sept. 2, 2011, 10:35 a.m.
Hi,

tested x86_64-linux multilib, will go in 4_6-branch too.

See audit trail for details: in short when std::bitset has been updated 
for constexpr, thus the constructor from unsigned long long marked as 
such, the call to _M_do_sanitize in the body was inadvertently 
completely removed without replacing it with something else compatible 
with constexpr.

Thanks,
Paolo.

/////////////////////
2011-09-02  Paolo Carlini  <paolo.carlini@oracle.com>
	    Marc Glisse  <marc.glisse@normalesup.org>

	PR libstdc++/50268
	* include/std/bitset (struct _Sanitize_val): Add.
	(bitset<>::bitset(unsigned long long)): Fix.
	* testsuite/23_containers/bitset/cons/50268.cc: New.

Patch

Index: include/std/bitset
===================================================================
--- include/std/bitset	(revision 178444)
+++ include/std/bitset	(working copy)
@@ -52,11 +52,13 @@ 
 #include <iosfwd>
 #include <bits/cxxabi_forced.h>
 
-#define _GLIBCXX_BITSET_BITS_PER_WORD  (__CHAR_BIT__ * sizeof(unsigned long))
+#define _GLIBCXX_BITSET_BITS_PER_WORD  (__CHAR_BIT__ * __SIZEOF_LONG__)
 #define _GLIBCXX_BITSET_WORDS(__n) \
   ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \
    ((__n) % _GLIBCXX_BITSET_BITS_PER_WORD == 0 ? 0 : 1))
 
+#define _GLIBCXX_BITSET_BITS_PER_ULL (__CHAR_BIT__ * __SIZEOF_LONG_LONG__)
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
@@ -657,6 +659,24 @@ 
       _S_do_sanitize(_WordT) _GLIBCXX_NOEXCEPT { } 
     };
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+  template<size_t _Nb, bool = _Nb < _GLIBCXX_BITSET_BITS_PER_ULL>
+    struct _Sanitize_val
+    {
+      static constexpr unsigned long long
+      _S_do_sanitize_val(unsigned long long __val)
+      { return __val; }
+    };
+
+  template<size_t _Nb>
+    struct _Sanitize_val<_Nb, true>
+    {
+      static constexpr unsigned long long
+      _S_do_sanitize_val(unsigned long long __val)
+      { return __val & ~((~static_cast<unsigned long long>(0)) << _Nb); }
+    };
+#endif
+
   /**
    *  @brief  The %bitset class represents a @e fixed-size sequence of bits.
    *
@@ -822,7 +842,7 @@ 
       /// Initial bits bitwise-copied from a single word (others set to zero).
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
       constexpr bitset(unsigned long long __val) noexcept
-      : _Base(__val) { }
+      : _Base(_Sanitize_val<_Nb>::_S_do_sanitize_val(__val)) { }
 #else
       bitset(unsigned long __val)
       : _Base(__val)
@@ -1513,6 +1533,7 @@ 
 
 #undef _GLIBCXX_BITSET_WORDS
 #undef _GLIBCXX_BITSET_BITS_PER_WORD
+#undef _GLIBCXX_BITSET_BITS_PER_ULL
 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
 
Index: testsuite/23_containers/bitset/cons/50268.cc
===================================================================
--- testsuite/23_containers/bitset/cons/50268.cc	(revision 0)
+++ testsuite/23_containers/bitset/cons/50268.cc	(revision 0)
@@ -0,0 +1,84 @@ 
+// { 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 <bitset>
+#include <testsuite_hooks.h>
+
+// libstdc++/50268
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::bitset<1> b1(3ULL);
+  VERIFY( b1.count() == 1ULL );
+
+  std::bitset<3> b2(30ULL);
+  VERIFY( b2.count() == 2ULL );
+
+  std::bitset<6> b3(300ULL);
+  VERIFY( b3.count() == 3ULL );
+
+  std::bitset<9> b4(3000ULL);
+  VERIFY( b4.count() == 5ULL );
+
+  std::bitset<16> b5(300000ULL);
+  VERIFY( b5.count() == 7ULL );
+
+  std::bitset<24> b6(30000000ULL);
+  VERIFY( b6.count() == 9ULL );
+
+  std::bitset<32> b7(30000000000ULL);
+  VERIFY( b7.count() == 13ULL );
+
+  std::bitset<37> b8(3000000000000ULL);
+  VERIFY( b8.count() == 18ULL );
+
+  std::bitset<40> b9(30000000000000ULL);
+  VERIFY( b9.count() == 16ULL );
+
+  std::bitset<45> b10(30000000000000ULL);
+  VERIFY( b10.count() == 20ULL );
+
+  std::bitset<64> b11(30000000000000ULL);
+  VERIFY( b11.count() == 20ULL );
+
+  std::bitset<100> b12(30000000000000ULL);
+  VERIFY( b12.count() == 20ULL );
+
+  std::bitset<200> b13(30000000000000ULL);
+  VERIFY( b13.count() == 20ULL );
+
+  std::bitset<45> b14(18446744073709551615ULL);
+  VERIFY( b14.count() == 45ULL );
+
+  std::bitset<64> b15(18446744073709551615ULL);
+  VERIFY( b15.count() == 64ULL );
+
+  std::bitset<100> b16(18446744073709551615ULL);
+  VERIFY( b16.count() == 64ULL );
+
+  std::bitset<200> b17(18446744073709551615ULL);
+  VERIFY( b17.count() == 64ULL );  
+}
+
+int main()
+{
+  test01();
+  return 0;
+}