diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-11-30 05:16:36 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-11-30 05:16:36 +0000 |
commit | bc4381667a31bd5f1e677d64c789b1e959df00d5 (patch) | |
tree | a6b80dca8f72a2e7640e4d535901e42325b2a954 /libstdc++-v3 | |
parent | 1cd66bce1663eb648638d311b493de0dcc4146c3 (diff) | |
parent | 738c50b853f5ba0eaf93e23f6d29cbac761eef9e (diff) | |
download | gcc-reload-v2a.tar.gz |
Weekly merge from trunk. No regressions.reload-v2a
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/reload-v2a@181834 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
97 files changed, 2707 insertions, 753 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5eb3f8d4376..1d4dff8747c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,254 @@ +2011-11-28 Paolo Carlini <paolo.carlini@oracle.com> + + PR libstdc++/51288 + * include/std/iomanip (get_money, put_money): Use sentry. + * testsuite/27_io/manipulators/extended/get_money/char/51288.cc: New. + * testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc: + Likewise. + * testsuite/27_io/manipulators/extended/put_money/char/51288.cc: + Likewise. + * testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc: + Likewise. + +2011-11-27 Gerald Pfeifer <gerald@pfeifer.com> + + * doc/xml/manual/using.xml (Prerequisites): Refer to x86 instead + of i386. + +2011-11-27 Gerald Pfeifer <gerald@pfeifer.com> + + * scripts/run_doxygen (problematic): Change Linux reference to + GNU/Linux. + +2011-11-26 Gerald Pfeifer <gerald@pfeifer.com> + + * doc/xml/manual/abi.xml (Prerequisites): Refer to GNU/Linux. + Fix reference to GCC. + +2011-11-26 Jonathan Wakely <jwakely.gcc@gmail.com> + + PR libstdc++/51296 + * testsuite/30_threads/thread/native_handle/typesizes.cc: Do not run + on alpha*-*-osf*. + * testsuite/30_threads/future/cons/constexpr.cc: Disable debug + symbols. + * testsuite/30_threads/shared_future/cons/constexpr.cc: Likewise. + +2011-11-23 François Dumont <fdumont@gcc.gnu.org> + + PR libstdc++/41975 + * include/bits/hashtable.h (_Hashtable<>): Major data model + modification to limit performance impact of empty buckets in + erase(iterator) implementation. + * include/bits/hashtable_policy.h (_Hashtable_iterator, + _Hashtable_const_iterator): Remove not used anymore. + * include/bits/hashtable_policy.h (_Prime_rehash_policy): Remove + _M_grow_factor, just use natural evolution of prime numbers. Add + _M_prev_size to know when the number of buckets can be reduced. + * include/bits/unordered_set.h (__unordered_set<>, + __unordered_multiset<>), unordered_map.h (__unordered_map<>, + __unordered_multimap<>): Change default value of cache hash code + template parameter, false for integral types with noexcept hash + functor, true otherwise. + * include/debug/unordered_map, unordered_set: Adapt transformation + from iterator/const_iterator to respectively + local_iterator/const_local_iterator. + * testsuite/performance/23_containers/copy_construct/unordered_set.cc: + New. + * testsuite/23_containers/unordered_set/instantiation_neg.cc: New. + * testsuite/23_containers/unordered_set/hash_policy/rehash.cc: New. + * testsuite/23_containers/unordered_multiset/cons/copy.cc: New. + * testsuite/23_containers/unordered_multiset/erase/1.cc, + 24061-multiset.cc: Add checks on the number of bucket elements. + * testsuite/23_containers/unordered_multiset/insert/multiset_range.cc, + multiset_single.cc, multiset_single_move.cc: Likewise. + +2011-11-21 Jonathan Wakely <jwakely.gcc@gmail.com> + + * include/std/functional (is_placeholder, is_bind_expression): Add + partial specializations for cv-qualified types. + * include/tr1/functional (is_placeholder, is_bind_expression): Add + partial specializations for std::bind and std::placeholders and for + cv-qualified types. + * testsuite/20_util/bind/cv_quals_3.cc: New. + * testsuite/tr1/3_function_objects/bind/cv_quals.cc: New. + * testsuite/tr1/3_function_objects/bind/mixed.cc: New. + +2011-11-21 Andreas Tobler <andreast@fgznet.ch> + + * configure: Regenerate. + +2011-11-21 Daniel Krugler <daniel.kruegler@googlemail.com> + + PR libstdc++/51185 + * include/std/type_traits (__is_base_to_derived_ref, + __is_lvalue_to_rvalue_ref): Fix. + * testsuite/20_util/is_constructible/51185.cc: New. + * testsuite/20_util/is_constructible/value-2.cc: Extend. + * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error + line number. + * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: + Likewise. + * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc + Likewise. + +2011-11-21 Paolo Carlini <paolo.carlini@oracle.com> + + * include/std/tuple (__conv_types, __one_by_one_convertible, + __all_convertible): Remove. + (tuple<>::tuple(_UElements&&...), + tuple<>::tuple(const tuple<_UElements...>&), + tuple<>::tuple(tuple<_UElements...>&&)): Remove wa for c++/48322. + * testsuite/20_util/uses_allocator/cons_neg.cc: Adjust dg-error + line number. + +2011-11-20 Jason Merrill <jason@redhat.com> + + PR c++/48322 + * include/std/tuple (tuple(_UElements&&...)): Fix SFINAE. + + * testsuite/20_util/bind/ref_neg.cc: Adjust error markings. + +2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com> + + * include/backward/binders.h: Fix examples in doxygen comments and + suggest using std::bind instead. + +2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com> + + * doc/xml/manual/status_cxx2011.xml: Fix docbook markup. + +2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com> + + * doc/xml/manual/appendix_contributing.xml: Do not use "here" as link + text. + * doc/xml/faq.xml: Likewise. Do not request standard library issues + to be reported to the libstdc++ mailing list. + * doc/xml/manual/status_cxx2011.xml: Document implementation-defined + behaviour. + * doc/xml/manual/status_cxxtr1.xml: Likewise. + * doc/xml/manual/utilities.xml: Fix grammar, probably caused by a + global search and replace of "part" by "chapter". + * doc/xml/manual/shared_ptr.xml: Remove outdated information. + * doc/xml/manual/messages.xml: Be more specific about systems where + using 'int' for catalog handle is not a problem, mention LWG issue. + +2011-11-19 Paolo Carlini <paolo.carlini@oracle.com> + + * include/debug/bitset (operator[](size_t) const): Declare constexpr. + * include/profile/bitset: Likewise. + * testsuite/23_containers/bitset/operations/constexpr.cc: Split out + non portable bits to... + * testsuite/23_containers/bitset/operations/constexpr-2.cc: ... here. + +2011-11-18 Harti Brandt <hartmut.brandt@dlr.de> + + PR libstdc++/51209 + * include/bits/hashtable.h (_Hashtable<>::_M_find_node): Return + nullptr when no node is found. + * include/tr1/hashtable.h (_Hashtable<>::_M_find_node): Return + zero when no node is found. + +2011-11-18 Paolo Carlini <paolo.carlini@oracle.com> + + * src/hash-long-double-aux.cc: Rename to... + * src/hash-long-double-tr1-aux.cc: ... this. + * src/compatibility-ldbl.cc: Adjust. + * src/hash_tr1.cc: Likewise. + * src/hash_c++0x.cc: Don't use src/hash-long-double-aux.cc. + * include/bits/functional_hash.h (hash<_Tp*>::operator(), specs + for integer types, hash<float>::operator(), hash<double>::operator(), + hash<long double>::operator()): Declare noexcept. + * include/debug/bitset (hash<__debug::bitset>::operator()): Likewise. + * include/debug/vector (hash<__debug::vector>::operator()): Likewise. + * include/std/system_error (hash<error_code>::operator()): Likewise. + * include/std/thread (hash<thread::id>::operator()): Likewise. + * include/std/bitset (hash<bitset>::operator()): Likewise. + * include/std/typeindex (hash<type_index>::operator()): Likewise. + * include/profile/bitset (hash<__profile::vector>::operator()): + Likewise. + * include/profile/vector (hash<__profile::vector>::operator()): + Likewise. + * include/ext/vstring.h (hash<__vstring>::operator(), + hash<__wvstring>::operator(), hash<__u16vstring>::operator(), + hash<__u32vstring>::operator()): Likewise. + * include/bits/shared_ptr.h (hash<shared_ptr>::operator()): Likewise. + * include/bits/shared_ptr_base.h (hash<__shared_ptr>::operator()): + Likewise. + * include/bits/unique_ptr.h (hash<unique_ptr>::operator()): Likewise. + * include/bits/basic_string.h (hash<string>::operator(), + hash<wstring>::operator(), hash<u16string>::operator(), + hash<u32string>::operator()): Likewise. + * include/bits/vector.tcc (hash<vector>::operator()): Likewise. + * include/bits/stl_bvector.h (hash<vector>::operator()): Likewise. + * libsupc++/typeinfo (type_info::hash_code): Use noexcept instead of + throw(). + +2011-11-17 Richard Henderson <rth@redhat.com> + + PR libstdc++/51181 + * libsupc++/eh_tm.cc (free_any_cxa_exception): Protect the use + of __sync_sub_and_fetch with _GLIBCXX_ATOMIC_BUILTINS_4. + +2011-11-18 Jonathan Wakely <jwakely.gcc@gmail.com> + + * testsuite/30_threads/thread/native_handle/typesizes.cc: Do not run + on darwin. + +2011-11-17 Jason Merrill <jason@redhat.com> + + * testsuite/21_strings/basic_string/cons/char/moveable2.cc + (tstring): Add defaulted move assignment. + * testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc + (tstring): Add defaulted move assignment. + * testsuite/util/testsuite_tr1.h (NoexceptMoveConsClass): Add + defaulted move assignment operator. + (NoexceptMoveAssignClass): Add defaulted move constructor. + +2011-11-17 Jonathan Wakely <jwakely.gcc@gmail.com> + + * doc/xml/manual/status_cxx2011.xml: Status of piecewise construction + and ios_base::failure. + * doc/xml/manual/backwards_compatibility.xml: List headers in + alphabetical order. + +2011-11-16 Andrew MacLeod <amacleod@redhat.com> + + PR libstdc++/51102 + * include/bits/atomic_base.h (ATOMIC_BOOL_LOCK_FREE, + ATOMIC_POINTER_LOCK_FREE): New. Add missing macros. + +2011-11-15 Paolo Carlini <paolo.carlini@oracle.com> + + PR libstdc++/51142 + * include/debug/unordered_map (unordered_map<>::erase(iterator), + unordered_multimap<>::erase(iterator)): Add, consistently with + LWG 2059. + * include/debug/unordered_set (unordered_set<>::erase(iterator), + unordered_multiset<>::erase(iterator)): Likewise. + * include/debug/map.h (map<>::erase(iterator)): Likewise. + * include/debug/multimap.h (multimap<>::erase(iterator)): Likewise. + * include/profile/map.h (map<>::erase(iterator)): Likewise. + * include/profile/multimap.h (multimap<>::erase(iterator)): Likewise. + * include/bits/hashtable.h (_Hashtable<>::erase(iterator)): Likewise. + * include/bits/stl_map.h (map<>::erase(iterator)): Likewise. + * include/bits/stl_multimap.h (multimap<>::erase(iterator)): Likewise. + * include/bits/stl_tree.h (_Rb_tree<>::erase(iterator)): Likewise. + * testsuite/23_containers/unordered_map/erase/51142.cc: New. + * testsuite/23_containers/multimap/modifiers/erase/51142.cc: Likewise. + * testsuite/23_containers/set/modifiers/erase/51142.cc: Likewise. + * testsuite/23_containers/unordered_multimap/erase/51142.cc: Likewise. + * testsuite/23_containers/unordered_set/erase/51142.cc: Likewise. + * testsuite/23_containers/multiset/modifiers/erase/51142.cc: Likewise. + * testsuite/23_containers/unordered_multiset/erase/51142.cc: Likewise. + * testsuite/23_containers/map/modifiers/erase/51142.cc: Likewise. + +2011-11-15 Jason Dick <dickphd@gmail.com> + + PR libstdc++/51133 + * include/tr1/poly_hermite.tcc (__poly_hermite_recursion): Fix + wrong sign in recursion relation. + 2011-11-14 Paolo Carlini <paolo.carlini@oracle.com> * include/c_global/cmath (frexp, modf, remquo): Do not mark constexpr, diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index fa755b47236..52218367919 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -9702,7 +9702,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes @@ -10618,7 +10618,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[123]*) objformat=aout ;; + freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -10636,7 +10636,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) @@ -12526,7 +12526,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi esac ;; - freebsd[12]*) + freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no @@ -14301,7 +14301,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[123]*) objformat=aout ;; + freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -14319,7 +14319,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml index af9b6da82fe..86142ec9c46 100644 --- a/libstdc++-v3/doc/xml/faq.xml +++ b/libstdc++-v3/doc/xml/faq.xml @@ -713,14 +713,15 @@ For those people who are not part of the ISO Library Group (i.e., nearly all of us needing to read this page in the first place), a public list of the library defects is occasionally - published <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">here</link>. + published on <link xmlns:xlink="http://www.w3.org/1999/xlink" + xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">the WG21 + website</link>. Some of these issues have resulted in code changes in libstdc++. </para> <para> If you think you've discovered a new bug that is not listed, - please post a message describing your problem - to <email>libstdc++@gcc.gnu.org</email> or the Usenet group - comp.lang.c++.moderated. + please post a message describing your problem to the author of + the library issues list or the Usenet group comp.lang.c++.moderated. </para> </answer> </qandaentry> diff --git a/libstdc++-v3/doc/xml/manual/abi.xml b/libstdc++-v3/doc/xml/manual/abi.xml index a8b92416e89..b79075df36a 100644 --- a/libstdc++-v3/doc/xml/manual/abi.xml +++ b/libstdc++-v3/doc/xml/manual/abi.xml @@ -596,8 +596,8 @@ compatible. </para> <para> - Most modern Linux and BSD versions, particularly ones using - gcc-3.1.x tools and more recent vintages, will meet the + Most modern GNU/Linux and BSD versions, particularly ones using + GCC 3.1 and later, will meet the requirements above, as does Solaris 2.5 and up. </para> </section> diff --git a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml index 49cbcab9ba3..d060f45a6d3 100644 --- a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml +++ b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml @@ -45,10 +45,10 @@ two meeting commitment for voting rights, may get a copy of the standard from their respective national standards organization. In the USA, this national standards - organization is ANSI and their web-site is right - <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ansi.org">here.</link> - (And if you've already registered with them, clicking this link will take you to directly to the place where you can - <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC+14882:2003">buy the standard on-line</link>.) + organization is + <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ansi.org">ANSI</link>. + (And if you've already registered with them you can + <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+14882-2003">buy the standard on-line</link>.) </para> </listitem> @@ -56,17 +56,16 @@ <para> The library working group bugs, and known defects, can be obtained here: - <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">http://www.open-std.org/jtc1/sc22/wg21 </link> + <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">http://www.open-std.org/jtc1/sc22/wg21</link> </para> </listitem> <listitem> <para> The newsgroup dedicated to standardization issues is - comp.std.c++: this FAQ for this group is quite useful and - can be - found <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.comeaucomputing.com/csc/faq.html"> - here </link>. + comp.std.c++: the + <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.comeaucomputing.com/csc/faq.html">FAQ</link> + for this group is quite useful. </para> </listitem> @@ -83,15 +82,15 @@ <para> Be familiar with the extensions that preceded these general GNU rules. These style issues for libstdc++ can be - found <link linkend="contrib.coding_style">here</link>. + found in <link linkend="contrib.coding_style">Coding Style</link>. </para> </listitem> <listitem> <para> And last but certainly not least, read the - library-specific information - found <link linkend="appendix.porting"> here</link>. + library-specific information found in + <link linkend="appendix.porting">Porting and Maintenance</link>. </para> </listitem> </itemizedlist> @@ -271,7 +270,7 @@ It has subdirectories: Files that are used in constructing the library, but are not installed. - testsuites/[backward, demangle, ext, performance, thread, 17_* to 27_*] + testsuites/[backward, demangle, ext, performance, thread, 17_* to 30_*] Test programs are here, and may be used to begin to exercise the library. Support for "make check" and "make check-install" is complete, and runs through all the subdirectories here when this diff --git a/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml b/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml index 525157f1814..f25d3cf5187 100644 --- a/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml +++ b/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml @@ -1163,11 +1163,11 @@ AC_DEFUN([AC_HEADER_STDCXX_11], [ #include <fstream> #include <functional> #include <future> + #include <initializer_list> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> - #include <initializer_list> #include <istream> #include <iterator> #include <limits> diff --git a/libstdc++-v3/doc/xml/manual/messages.xml b/libstdc++-v3/doc/xml/manual/messages.xml index d6ce1f7f7a3..4dea4b3738b 100644 --- a/libstdc++-v3/doc/xml/manual/messages.xml +++ b/libstdc++-v3/doc/xml/manual/messages.xml @@ -119,8 +119,9 @@ A couple of notes on the standard. <para> First, why is <code>messages_base::catalog</code> specified as a typedef to int? This makes sense for implementations that use -<code>catopen</code>, but not for others. Fortunately, it's not heavily -used and so only a minor irritant. +<code>catopen</code> and define <code>nl_catd</code> as int, but not for +others. Fortunately, it's not heavily used and so only a minor irritant. +This has been reported as a possible defect in the standard (LWG 2028). </para> <para> diff --git a/libstdc++-v3/doc/xml/manual/shared_ptr.xml b/libstdc++-v3/doc/xml/manual/shared_ptr.xml index 6e3392f88ee..be1aaf655f2 100644 --- a/libstdc++-v3/doc/xml/manual/shared_ptr.xml +++ b/libstdc++-v3/doc/xml/manual/shared_ptr.xml @@ -95,13 +95,13 @@ until the last weak reference is dropped. <term><classname>_Sp_counted_base_impl<Ptr, Deleter, Lp></classname></term> <listitem> <para> -Inherits from _Sp_counted_base and stores a pointer of type <type>Ptr</type> -and a deleter of type <code>Deleter</code>. <code>_Sp_deleter</code> is +Inherits from _Sp_counted_base and stores a pointer of type <code>Ptr</code> +and a deleter of type <code>Deleter</code>. <classname>_Sp_deleter</classname> is used when the user doesn't supply a custom deleter. Unlike Boost's, this default deleter is not "checked" because GCC already issues a warning if <function>delete</function> is used with an incomplete type. -This is the only derived type used by <classname>shared_ptr<Ptr></classname> -and it is never used by <classname>shared_ptr</classname>, which uses one of +This is the only derived type used by <classname>tr1::shared_ptr<Ptr></classname> +and it is never used by <classname>std::shared_ptr</classname>, which uses one of the following types, depending on how the shared_ptr is constructed. </para> </listitem> @@ -149,11 +149,6 @@ that simplifies the implementation slightly. </variablelist> - </section> - - <section><info><title>Thread Safety</title></info> - - <para> C++11-only features are: rvalue-ref/move support, allocator support, aliasing constructor, make_shared & allocate_shared. Additionally, @@ -161,6 +156,11 @@ the constructors taking <classname>auto_ptr</classname> parameters are deprecated in C++11 mode. </para> + + </section> + + <section><info><title>Thread Safety</title></info> + <para> The <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://boost.org/libs/smart_ptr/shared_ptr.htm#ThreadSafety">Thread @@ -243,7 +243,7 @@ available policies are: <orderedlist> <listitem> <para> - <type>_S_Atomic</type> + <constant>_S_Atomic</constant> </para> <para> Selected when GCC supports a builtin atomic compare-and-swap operation @@ -256,7 +256,7 @@ synchronisation. <listitem> <para> - <type>_S_Mutex</type> + <constant>_S_Mutex</constant> </para> <para> The _Sp_counted_base specialization for this policy contains a mutex, @@ -267,7 +267,7 @@ builtins aren't available so explicit memory barriers are needed in places. <listitem> <para> - <type>_S_Single</type> + <constant>_S_Single</constant> </para> <para> This policy uses a non-reentrant add_ref_lock() with no locking. It is @@ -285,32 +285,6 @@ used when libstdc++ is built without <literal>--enable-threads</literal>. </para> </section> - <section><info><title>Dual C++11 and TR1 Implementation</title></info> - - -<para> -The interface of <classname>tr1::shared_ptr</classname> was extended for C++11 -with support for rvalue-references and the other features from N2351. -The <classname>_Sp_counted_base</classname> base class is implemented in -<filename>tr1/boost_sp_shared_count.h</filename> and is common to the TR1 -and C++11 versions of <classname>shared_ptr</classname>. -</para> - -<para> -The classes derived from <classname>_Sp_counted_base</classname> (see Class Hierarchy -above) and <classname>__shared_count</classname> are implemented separately for C++11 -and TR1, in <filename>bits/shared_ptr.h</filename> and -<filename>tr1/shared_ptr.h</filename> respectively. -</para> - -<para> -The TR1 implementation is considered relatively stable, so is unlikely to -change unless bug fixes require it. If the code that is common to both -C++11 and TR1 versions needs to diverge further then it might be necessary to -duplicate <classname>_Sp_counted_base</classname> and only make changes to -the C++11 version. -</para> -</section> <section><info><title>Related functions and classes</title></info> @@ -377,34 +351,6 @@ be private. </section> -<!--- XXX - <listitem> - <type>_Sp_counted_base<Lp></type> - <para> -The base of the hierarchy is parameterized on the lock policy alone. -_Sp_counted_base doesn't depend on the type of pointer being managed, -it only maintains the reference counts and calls virtual functions when -the counts drop to zero. The managed object is destroyed when the last -strong reference is dropped, but the _Sp_counted_base itself must exist -until the last weak reference is dropped. - </para> - </listitem> - - <listitem> - <type>_Sp_counted_base_impl<Ptr, Deleter, Lp></type> - <para> -Inherits from _Sp_counted_base and stores a pointer of type <code>Ptr</code> -and a deleter of type <code>Deleter</code>. <code>_Sp_deleter</code> is -used when the user doesn't supply a custom deleter. Unlike Boost's, this -default deleter is not "checked" because GCC already issues a warning if -<code>delete</code> is used with an incomplete type. -This is the only derived type used by <code>tr1::shared_ptr<Ptr></code> -and it is never used by <code>std::shared_ptr</code>, which uses one of -the following types, depending on how the shared_ptr is constructed. - </para> - </listitem> ---> - <section xml:id="shared_ptr.using"><info><title>Use</title></info> diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml index 51785fcb812..f47710e3b90 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml @@ -384,10 +384,12 @@ particular release. <entry/> </row> <row> + <?dbhtml bgcolor="#B0B0B0" ?> <entry>20.3.2</entry> <entry>Class template <code>pair</code></entry> - <entry>Y</entry> - <entry/> + <entry>Partial</entry> + <entry>Piecewise construction requires an accessible copy/move + constructor.</entry> </row> <row> <entry>20.3.3</entry> @@ -2136,8 +2138,9 @@ particular release. <entry>Iostreams base classes</entry> <entry>Partial</entry> <entry> - Missing move and swap operations on <code>basic_ios</code>. Missing - <code>make_error_code</code> and <code>make_error_condition</code>. + Missing move and swap operations on <code>basic_ios</code>. + Missing <code>io_errc</code> and <code>iostream_category</code>. + <code>ios_base::failure</code> is not derived from <code>system_error</code>. </entry> </row> <row> @@ -2406,7 +2409,8 @@ particular release. <entry>30.4.1.3</entry> <entry>Timed mutex types</entry> <entry/> - <entry/> + <entry>On POSIX sytems these types are only defined if the OS + supports the POSIX Timeouts option. </entry> </row> <row> <entry>30.4.1.3.1</entry> @@ -2624,5 +2628,59 @@ particular release. </tgroup> </table> +<section xml:id="iso.2011.specific" xreflabel="Implementation Specific"><info><title>Implementation Specific Behavior</title></info> + + <para>For behaviour which is also specified by the 1998 and 2003 standards, + see <link linkend="iso.1998.specific">C++ 1998/2003 Implementation + Specific Behavior</link>. This section only documents behaviour which + is new in the 2011 standard. + </para> + + <para> + <emphasis>20.8.9.1.3 [func.bind.place]/1</emphasis> There are 29 + placeholders defined and the placeholder types are + <literal>CopyAssignable</literal>. + </para> + + <para> + <emphasis>30.2.3 [thread.req.native]/1</emphasis> + <classname>native_handle_type</classname> and + <methodname>native_handle</methodname> are provided. The handle types + are defined in terms of the Gthreads abstraction layer. + <itemizedlist> + <listitem><para><classname>thread</classname>: The native handle type is + a typedef for <code>__gthread_t</code> i.e. <code>pthread_t</code> + when GCC is configured with the <literal>posix</literal> thread + model. The value of the native handle is undefined for a thread + which is not joinable. + </para></listitem> + <listitem><para><classname>mutex</classname> and + <classname>timed_mutex</classname>: + The native handle type is <code>__gthread_mutex_t*</code> i.e. + <code>pthread_mutex_t*</code> for the <literal>posix</literal> + thread model. + </para></listitem> + <listitem><para><classname>recursive_mutex</classname> and + <classname>recursive_timed_mutex</classname>: + The native handle type is <code>__gthread_recursive_mutex_t*</code> + i.e. <code>pthread_mutex_t*</code> for the <literal>posix</literal> + thread model. + </para></listitem> + <listitem><para><classname>condition_variable</classname>: The native + handle type is <code>__gthread_cond_t*</code> i.e. + <code>pthread_cond_t*</code> for the <literal>posix</literal> + thread model. + </para></listitem> + </itemizedlist> + </para> + + <para> + <emphasis>30.6.1 [futures.overview]/2</emphasis> + <code>launch</code> is a scoped enumeration type with + overloaded operators to support bitmask operations. There are no + additional bitmask elements defined. + </para> + +</section> </section> diff --git a/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml b/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml index 321c4ba269c..58571f2dde7 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml @@ -1779,4 +1779,20 @@ release. </tgroup> </table> +<section xml:id="iso.tr1.specific" xreflabel="Implementation Specific"><info><title>Implementation Specific Behavior</title></info> + + <para>For behaviour which is specified by the 1998 and 2003 standards, + see <link linkend="iso.1998.specific">C++ 1998/2003 Implementation + Specific Behavior</link>. This section documents behaviour which + is required by TR1. + </para> + + <para> + <emphasis>3.6.4 [tr.func.bind.place]/1</emphasis> There are 29 + placeholders defined and the placeholder types are + <literal>Assignable</literal>. + </para> + +</section> + </section> diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml index 601ca20d1eb..d2d5e4b2850 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -1269,7 +1269,7 @@ A quick read of the relevant part of the GCC to display how ad hoc this is: On Solaris, both -pthreads and -threads (with subtly different meanings) are honored. On OSF, -pthread and -threads (with subtly different meanings) are - honored. On GNU/Linux i386, -pthread is honored. On FreeBSD, + honored. On GNU/Linux x86, -pthread is honored. On FreeBSD, -pthread is honored. Some other ports use other switches. AFAIK, none of this is properly documented anywhere other than in ``gcc -dumpspecs'' (look at lib and cpp entries). diff --git a/libstdc++-v3/doc/xml/manual/utilities.xml b/libstdc++-v3/doc/xml/manual/utilities.xml index 5c3a8fd4864..a60bd34c6d4 100644 --- a/libstdc++-v3/doc/xml/manual/utilities.xml +++ b/libstdc++-v3/doc/xml/manual/utilities.xml @@ -25,7 +25,7 @@ <para>If you don't know what functors are, you're not alone. Many people get slightly the wrong idea. In the interest of not reinventing the wheel, we will refer you to the introduction to the functor - concept written by SGI as chapter of their STL, in + concept written by SGI as part of their STL, in <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/functors.html">their http://www.sgi.com/tech/stl/functors.html</link>. </para> diff --git a/libstdc++-v3/include/backward/binders.h b/libstdc++-v3/include/backward/binders.h index f98b56aaede..076f8d2e219 100644 --- a/libstdc++-v3/include/backward/binders.h +++ b/libstdc++-v3/include/backward/binders.h @@ -80,7 +80,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * The type @c binder2nd and its creator function @c bind2nd do the same * thing, but the stored argument is passed as the second parameter instead - * of the first, e.g., @c bind2nd(std::minus<float>,1.3) will create a + * of the first, e.g., @c bind2nd(std::minus<float>(),1.3) will create a * functor whose @c operator() accepts a floating-point number, subtracts * 1.3 from it, and returns the result. (If @c bind1st had been used, * the functor would perform <em>1.3 - x</em> instead. @@ -89,10 +89,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * calling algorithms. Their return values will be temporary objects. * (The goal is to not require you to type names like * @c std::binder1st<std::plus<int>> for declaring a variable to hold the - * return value from @c bind1st(std::plus<int>,5). + * return value from @c bind1st(std::plus<int>(),5). * * These become more useful when combined with the composition functions. * + * These functions are deprecated in C++11 and can be replaced by + * @c std::bind (or @c std::tr1::bind) which is more powerful and flexible, + * supporting functions with any number of arguments. Uses of @c bind1st + * can be replaced by @c std::bind(f, x, std::placeholders::_1) and + * @c bind2nd by @c std::bind(f, std::placeholders::_1, x). * @{ */ /// One of the @link binders binder functors@endlink. diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index f0336611d3f..cf292a85385 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -93,6 +93,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1) +#define ATOMIC_BOOL_LOCK_FREE LOCKFREE_PROP (bool) #define ATOMIC_CHAR_LOCK_FREE LOCKFREE_PROP (char) #define ATOMIC_CHAR16_T_LOCK_FREE LOCKFREE_PROP (char16_t) #define ATOMIC_CHAR32_T_LOCK_FREE LOCKFREE_PROP (char32_t) @@ -101,7 +102,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define ATOMIC_INT_LOCK_FREE LOCKFREE_PROP (int) #define ATOMIC_LONG_LOCK_FREE LOCKFREE_PROP (long) #define ATOMIC_LLONG_LOCK_FREE LOCKFREE_PROP (long long) - +#define ATOMIC_POINTER_LOCK_FREE LOCKFREE_PROP (void *) // Base types for atomics. template<typename _IntTp> diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 00f9bccd419..169daf58613 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3044,7 +3044,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, string> { size_t - operator()(const string& __s) const + operator()(const string& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length()); } }; @@ -3055,7 +3055,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, wstring> { size_t - operator()(const wstring& __s) const + operator()(const wstring& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } }; @@ -3069,7 +3069,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, u16string> { size_t - operator()(const u16string& __s) const + operator()(const u16string& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length() * sizeof(char16_t)); } }; @@ -3080,7 +3080,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, u32string> { size_t - operator()(const u32string& __s) const + operator()(const u32string& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length() * sizeof(char32_t)); } }; diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index e77cb4e17bf..2b82b21f716 100644 --- a/libstdc++-v3/include/bits/functional_hash.h +++ b/libstdc++-v3/include/bits/functional_hash.h @@ -66,61 +66,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash<_Tp*> : public __hash_base<size_t, _Tp*> { size_t - operator()(_Tp* __p) const + operator()(_Tp* __p) const noexcept { return reinterpret_cast<size_t>(__p); } }; // Explicit specializations for integer types. #define _Cxx_hashtable_define_trivial_hash(_Tp) \ template<> \ - inline size_t \ - hash<_Tp>::operator()(_Tp __val) const \ - { return static_cast<size_t>(__val); } + struct hash<_Tp> : public __hash_base<size_t, _Tp> \ + { \ + size_t \ + operator()(_Tp __val) const noexcept \ + { return static_cast<size_t>(__val); } \ + }; /// Explicit specialization for bool. - _Cxx_hashtable_define_trivial_hash(bool); + _Cxx_hashtable_define_trivial_hash(bool) /// Explicit specialization for char. - _Cxx_hashtable_define_trivial_hash(char); + _Cxx_hashtable_define_trivial_hash(char) /// Explicit specialization for signed char. - _Cxx_hashtable_define_trivial_hash(signed char); + _Cxx_hashtable_define_trivial_hash(signed char) /// Explicit specialization for unsigned char. - _Cxx_hashtable_define_trivial_hash(unsigned char); + _Cxx_hashtable_define_trivial_hash(unsigned char) /// Explicit specialization for wchar_t. - _Cxx_hashtable_define_trivial_hash(wchar_t); + _Cxx_hashtable_define_trivial_hash(wchar_t) /// Explicit specialization for char16_t. - _Cxx_hashtable_define_trivial_hash(char16_t); + _Cxx_hashtable_define_trivial_hash(char16_t) /// Explicit specialization for char32_t. - _Cxx_hashtable_define_trivial_hash(char32_t); + _Cxx_hashtable_define_trivial_hash(char32_t) /// Explicit specialization for short. - _Cxx_hashtable_define_trivial_hash(short); + _Cxx_hashtable_define_trivial_hash(short) /// Explicit specialization for int. - _Cxx_hashtable_define_trivial_hash(int); + _Cxx_hashtable_define_trivial_hash(int) /// Explicit specialization for long. - _Cxx_hashtable_define_trivial_hash(long); + _Cxx_hashtable_define_trivial_hash(long) /// Explicit specialization for long long. - _Cxx_hashtable_define_trivial_hash(long long); + _Cxx_hashtable_define_trivial_hash(long long) /// Explicit specialization for unsigned short. - _Cxx_hashtable_define_trivial_hash(unsigned short); + _Cxx_hashtable_define_trivial_hash(unsigned short) /// Explicit specialization for unsigned int. - _Cxx_hashtable_define_trivial_hash(unsigned int); + _Cxx_hashtable_define_trivial_hash(unsigned int) /// Explicit specialization for unsigned long. - _Cxx_hashtable_define_trivial_hash(unsigned long); + _Cxx_hashtable_define_trivial_hash(unsigned long) /// Explicit specialization for unsigned long long. - _Cxx_hashtable_define_trivial_hash(unsigned long long); + _Cxx_hashtable_define_trivial_hash(unsigned long long) #undef _Cxx_hashtable_define_trivial_hash @@ -162,26 +165,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Specialization for float. template<> - inline size_t - hash<float>::operator()(float __val) const + struct hash<float> : public __hash_base<size_t, float> { - // 0 and -0 both hash to zero. - return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0; - } + size_t + operator()(float __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0; + } + }; /// Specialization for double. template<> - inline size_t - hash<double>::operator()(double __val) const + struct hash<double> : public __hash_base<size_t, double> { - // 0 and -0 both hash to zero. - return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0; - } + size_t + operator()(double __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0; + } + }; /// Specialization for long double. template<> - _GLIBCXX_PURE size_t - hash<long double>::operator()(long double __val) const; + struct hash<long double> + : public __hash_base<size_t, long double> + { + _GLIBCXX_PURE size_t + operator()(long double __val) const noexcept; + }; // @} group hashes diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 95d06b21262..dfa91f7cc8c 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // value type is Value. As a conforming extension, we allow for // value type != Value. - // _ExtractKey: function object that takes a object of type Value + // _ExtractKey: function object that takes an object of type Value // and returns a value of type _Key. // _Equal: function object that takes two objects of type k and returns @@ -78,9 +78,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // count. If so, returns make_pair(true, n), where n is the new // bucket count. If not, returns make_pair(false, <anything>). - // ??? Right now it is hard-wired that the number of buckets never - // shrinks. Should we allow _RehashPolicy to change that? - // __cache_hash_code: bool. true if we store the value of the hash // function along with the value. This is a time-space tradeoff. // Storing it may improve lookup speed by reducing the number of times @@ -94,6 +91,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // is always at most one, false if it may be an arbitrary number. This // true for unordered_set and unordered_map, false for unordered_multiset // and unordered_multimap. + /** + * Here's _Hashtable data structure, each _Hashtable has: + * - _Bucket[] _M_buckets + * - size_type _M_bucket_count + * - size_type _M_begin_bucket_index + * - size_type _M_element_count + * + * with _Bucket being _Node* and _Node: + * - _Node* _M_next + * - Tp _M_value + * - size_t _M_code if cache_hash_code is true + * + * In terms of Standard containers the hastable is like the aggregation of: + * - std::forward_list<_Node> containing the elements + * - std::vector<std::forward_list<_Node>::iterator> representing the buckets + * + * The first non-empty bucket with index _M_begin_bucket_index contains the + * first container node which is also the first bucket node whereas other + * non-empty buckets contain the node before the first bucket node. This is so + * to implement something like a std::forward_list::erase_after on container + * erase calls. + * + * Access to the bucket last element require a check on the hash code to see + * if the node is still in the bucket. Such a design impose a quite efficient + * hash functor and is one of the reasons it is highly advise to set + * __cache_hash_code to true. + * + * The container iterators are simply built from nodes. This way incrementing + * the iterator is perfectly efficient no matter how many empty buckets there + * are in the container. + * + * On insert we compute element hash code and thanks to it find the bucket + * index. If the element is the first one in the bucket we must find the + * previous non-empty bucket where the previous node rely. To keep this loop + * minimal it is important that the number of bucket is not too high compared + * to the number of elements. So the hash policy must be carefully design so + * that it computes a bucket count large enough to respect the user defined + * load factor but also not too large to limit impact on the insert operation. + * + * On erase, the simple iterator design impose to use the hash functor to get + * the index of the bucket to update. For this reason, when __cache_hash_code + * is set to false, there is a static assertion that the hash functor cannot + * throw. + * + * _M_begin_bucket_index is used to offer contant time access to the container + * begin iterator. + */ template<typename _Key, typename _Value, typename _Allocator, typename _ExtractKey, typename _Equal, @@ -130,6 +174,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __constant_iterators, __unique_keys> > { + static_assert(__or_<integral_constant<bool, __cache_hash_code>, + __detail::__is_noexcept_hash<_Key, _H1>>::value, + "Cache the hash code or qualify your hash functor with noexcept"); public: typedef _Allocator allocator_type; typedef _Value value_type; @@ -152,30 +199,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cache_hash_code> const_local_iterator; - typedef __detail::_Hashtable_iterator<value_type, __constant_iterators, - __cache_hash_code> - iterator; - typedef __detail::_Hashtable_const_iterator<value_type, - __constant_iterators, - __cache_hash_code> - const_iterator; + typedef local_iterator iterator; + typedef const_local_iterator const_iterator; template<typename _Key2, typename _Value2, typename _Ex2, bool __unique2, typename _Hashtable2> friend struct __detail::_Map_base; private: + typedef typename _RehashPolicy::_State _RehashPolicyState; typedef __detail::_Hash_node<_Value, __cache_hash_code> _Node; typedef typename _Allocator::template rebind<_Node>::other _Node_allocator_type; - typedef typename _Allocator::template rebind<_Node*>::other + typedef _Node* _Bucket; + //typedef __detail::_Bucket<_Value, __cache_hash_code> _Bucket; + typedef typename _Allocator::template rebind<_Bucket>::other _Bucket_allocator_type; typedef typename _Allocator::template rebind<_Value>::other _Value_allocator_type; _Node_allocator_type _M_node_allocator; - _Node** _M_buckets; + _Bucket* _M_buckets; size_type _M_bucket_count; size_type _M_begin_bucket_index; // First non-empty bucket. size_type _M_element_count; @@ -188,14 +233,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_deallocate_node(_Node* __n); + // Deallocate all nodes contained in the bucket array, buckets' nodes + // are not linked to each other + void + _M_deallocate_nodes(_Bucket*, size_type); + + // Deallocate the linked list of nodes pointed to by __n void - _M_deallocate_nodes(_Node**, size_type); + _M_deallocate_nodes(_Node* __n); - _Node** + _Bucket* _M_allocate_buckets(size_type __n); void - _M_deallocate_buckets(_Node**, size_type __n); + _M_deallocate_buckets(_Bucket*, size_type __n); + + // Gets bucket begin dealing with the difference between first non-empty + // bucket containing the first container node and the other non-empty + // buckets containing the node before the one belonging to the bucket. + _Node* + _M_bucket_begin(size_type __bkt) const; + + // Gets the bucket last node if any + _Node* + _M_bucket_end(size_type __bkt) const; + + // Gets the bucket node after the last if any + _Node* + _M_bucket_past_the_end(size_type __bkt) const + { + _Node* __end = _M_bucket_end(__bkt); + return __end ? __end->_M_next : nullptr; + } public: // Constructor, destructor, assignment, swap @@ -240,27 +309,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Basic container operations iterator begin() noexcept - { return iterator(_M_buckets + _M_begin_bucket_index); } + { return iterator(_M_buckets[_M_begin_bucket_index]); } const_iterator begin() const noexcept - { return const_iterator(_M_buckets + _M_begin_bucket_index); } + { return const_iterator(_M_buckets[_M_begin_bucket_index]); } iterator end() noexcept - { return iterator(_M_buckets + _M_bucket_count); } + { return iterator(nullptr); } const_iterator end() const noexcept - { return const_iterator(_M_buckets + _M_bucket_count); } + { return const_iterator(nullptr); } const_iterator cbegin() const noexcept - { return const_iterator(_M_buckets + _M_begin_bucket_index); } + { return const_iterator(_M_buckets[_M_begin_bucket_index]); } const_iterator cend() const noexcept - { return const_iterator(_M_buckets + _M_bucket_count); } + { return const_iterator(nullptr); } size_type size() const noexcept @@ -307,28 +376,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION local_iterator begin(size_type __n) - { return local_iterator(_M_buckets[__n]); } + { return local_iterator(_M_bucket_begin(__n)); } local_iterator - end(size_type) - { return local_iterator(0); } + end(size_type __n) + { return local_iterator(_M_bucket_past_the_end(__n)); } const_local_iterator begin(size_type __n) const - { return const_local_iterator(_M_buckets[__n]); } + { return const_local_iterator(_M_bucket_begin(__n)); } const_local_iterator - end(size_type) const - { return const_local_iterator(0); } + end(size_type __n) const + { return const_local_iterator(_M_bucket_past_the_end(__n)); } // DR 691. const_local_iterator cbegin(size_type __n) const - { return const_local_iterator(_M_buckets[__n]); } + { return const_local_iterator(_M_bucket_begin(__n)); } const_local_iterator - cend(size_type) const - { return const_local_iterator(0); } + cend(size_type __n) const + { return const_local_iterator(_M_bucket_past_the_end(__n)); } float load_factor() const noexcept @@ -366,9 +435,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: // Find and insert helper functions and types _Node* - _M_find_node(_Node*, const key_type&, + _M_find_node(size_type, const key_type&, typename _Hashtable::_Hash_code_type) const; + // Insert a node in an empty bucket + void + _M_insert_bucket_begin(size_type, _Node*); + + // Insert a node after an other one in a non-empty bucket + void + _M_insert_after(size_type, _Node*, _Node*); + + // Remove the bucket first node + void + _M_remove_bucket_begin(size_type __bkt, _Node* __next_n, + size_type __next_bkt); + + // Get the node before __n in the bucket __bkt + _Node* + _M_get_previous_node(size_type __bkt, _Node* __n); + template<typename _Arg> iterator _M_insert_bucket(_Arg&&, size_type, @@ -432,6 +518,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iterator erase(const_iterator); + // LWG 2059. + iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + size_type erase(const key_type&); @@ -449,8 +540,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: // Unconditionally change size of bucket array to n, restore hash policy - // resize value to __next_resize on exception. - void _M_rehash(size_type __n, size_type __next_resize); + // state to __state on exception. + void _M_rehash(size_type __n, const _RehashPolicyState& __state); }; @@ -471,7 +562,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __try { _M_node_allocator.construct(__n, std::forward<_Args>(__args)...); - __n->_M_next = 0; return __n; } __catch(...) @@ -501,18 +591,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: - _M_deallocate_nodes(_Node** __array, size_type __n) + _M_deallocate_nodes(_Bucket* __buckets, size_type __n) + { + for (size_type __i = 0; __i != __n; ++__i) + _M_deallocate_nodes(__buckets[__i]); + } + + template<typename _Key, typename _Value, + typename _Allocator, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + bool __chc, bool __cit, bool __uk> + void + _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: + _M_deallocate_nodes(_Node* __n) { - for (size_type __i = 0; __i < __n; ++__i) + while (__n) { - _Node* __p = __array[__i]; - while (__p) - { - _Node* __tmp = __p; - __p = __p->_M_next; - _M_deallocate_node(__tmp); - } - __array[__i] = 0; + _Node* __tmp = __n; + __n = __n->_M_next; + _M_deallocate_node(__tmp); } } @@ -522,18 +620,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool __chc, bool __cit, bool __uk> typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, - __chc, __cit, __uk>::_Node** + __chc, __cit, __uk>::_Bucket* _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: _M_allocate_buckets(size_type __n) { _Bucket_allocator_type __alloc(_M_node_allocator); - // We allocate one extra bucket to hold a sentinel, an arbitrary - // non-null pointer. Iterator increment relies on this. - _Node** __p = __alloc.allocate(__n + 1); - std::fill(__p, __p + __n, (_Node*) 0); - __p[__n] = reinterpret_cast<_Node*>(0x1000); + // We allocate one extra bucket to have _M_begin_bucket_index + // point to it as long as container is empty + _Bucket* __p = __alloc.allocate(__n + 1); + __builtin_memset(__p, 0, (__n + 1) * sizeof(_Bucket)); return __p; } @@ -544,7 +641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: - _M_deallocate_buckets(_Node** __p, size_type __n) + _M_deallocate_buckets(_Bucket* __p, size_type __n) { _Bucket_allocator_type __alloc(_M_node_allocator); __alloc.deallocate(__p, __n + 1); @@ -554,6 +651,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Allocator, typename _ExtractKey, typename _Equal, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, bool __chc, bool __cit, bool __uk> + typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, + _Equal, _H1, _H2, _Hash, _RehashPolicy, + __chc, __cit, __uk>::_Node* + _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: + _M_bucket_begin(size_type __bkt) const + { + if (__bkt == _M_begin_bucket_index) + return _M_buckets[__bkt]; + _Node* __n = _M_buckets[__bkt]; + return __n ? __n->_M_next : nullptr; + } + + template<typename _Key, typename _Value, + typename _Allocator, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + bool __chc, bool __cit, bool __uk> + typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, + _Equal, _H1, _H2, _Hash, _RehashPolicy, + __chc, __cit, __uk>::_Node* + _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: + _M_bucket_end(size_type __bkt) const + { + _Node* __n = _M_bucket_begin(__bkt); + if (__n) + for (;; __n = __n->_M_next) + if (!__n->_M_next + || this->_M_bucket_index(__n->_M_next, _M_bucket_count) + != __bkt) + break; + return __n; + } + + template<typename _Key, typename _Value, + typename _Allocator, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + bool __chc, bool __cit, bool __uk> _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: _Hashtable(size_type __bucket_hint, @@ -571,6 +706,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_rehash_policy() { _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint); + // We don't want the rehash policy to ask for the hashtable to shrink + // on the first insertion so we need to reset its previous resize level. + _M_rehash_policy._M_prev_resize = 0; _M_buckets = _M_allocate_buckets(_M_bucket_count); _M_begin_bucket_index = _M_bucket_count; } @@ -602,6 +740,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_bkt_for_elements(__detail:: __distance_fw(__f, __l))); + // We don't want the rehash policy to ask for the hashtable to shrink + // on the first insertion so we need to reset its previous resize + // level. + _M_rehash_policy._M_prev_resize = 0; _M_buckets = _M_allocate_buckets(_M_bucket_count); _M_begin_bucket_index = _M_bucket_count; __try @@ -637,17 +779,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_buckets = _M_allocate_buckets(_M_bucket_count); __try { - for (size_type __i = 0; __i < __ht._M_bucket_count; ++__i) + const _Node* __ht_n = __ht._M_buckets[__ht._M_begin_bucket_index]; + if (!__ht_n) + return; + + // Note that the copy constructor do not rely on hash code usage. + // First deal with the special first node that is directly store in + // the first non-empty bucket + _Node* __this_n = _M_allocate_node(__ht_n->_M_v); + this->_M_copy_code(__this_n, __ht_n); + _M_buckets[_M_begin_bucket_index] = __this_n; + __ht_n = __ht_n->_M_next; + // Second deal with following non-empty buckets containing previous + // nodes node. + for (size_type __i = __ht._M_begin_bucket_index + 1; + __i != __ht._M_bucket_count; ++__i) { - _Node* __n = __ht._M_buckets[__i]; - _Node** __tail = _M_buckets + __i; - while (__n) + if (!__ht._M_buckets[__i]) + continue; + + for (; __ht_n != __ht._M_buckets[__i]->_M_next; + __ht_n = __ht_n->_M_next) { - *__tail = _M_allocate_node(__n->_M_v); - this->_M_copy_code(*__tail, __n); - __tail = &((*__tail)->_M_next); - __n = __n->_M_next; + __this_n->_M_next = _M_allocate_node(__ht_n->_M_v); + this->_M_copy_code(__this_n->_M_next, __ht_n); + __this_n = __this_n->_M_next; } + + _M_buckets[__i] = __this_n; + } + // Last finalize copy of the nodes of the last non-empty bucket + for (; __ht_n; __ht_n = __ht_n->_M_next) + { + __this_n->_M_next = _M_allocate_node(__ht_n->_M_v); + this->_M_copy_code(__this_n->_M_next, __ht_n); + __this_n = __this_n->_M_next; } } __catch(...) @@ -732,8 +898,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __rehash_policy(const _RehashPolicy& __pol) { size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count); - if (__n_bkt > _M_bucket_count) - _M_rehash(__n_bkt, _M_rehash_policy._M_next_resize); + if (__n_bkt != _M_bucket_count) + _M_rehash(__n_bkt, _M_rehash_policy._M_state()); _M_rehash_policy = __pol; } @@ -750,8 +916,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count); - _Node* __p = _M_find_node(_M_buckets[__n], __k, __code); - return __p ? iterator(__p, _M_buckets + __n) : this->end(); + _Node* __p = _M_find_node(__n, __k, __code); + return __p ? iterator(__p) : this->end(); } template<typename _Key, typename _Value, @@ -767,8 +933,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count); - _Node* __p = _M_find_node(_M_buckets[__n], __k, __code); - return __p ? const_iterator(__p, _M_buckets + __n) : this->end(); + _Node* __p = _M_find_node(__n, __k, __code); + return __p ? const_iterator(__p) : this->end(); } template<typename _Key, typename _Value, @@ -784,10 +950,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count); + _Node* __p = _M_bucket_begin(__n); + if (!__p) + return 0; + std::size_t __result = 0; - for (_Node* __p = _M_buckets[__n]; __p; __p = __p->_M_next) - if (this->_M_compare(__k, __code, __p)) - ++__result; + for (;; __p = __p->_M_next) + { + if (this->_M_compare(__k, __code, __p)) + ++__result; + else if (__result) + // All equivalent values are next to each other, if we found a not + // equivalent value after an equivalent one it means that we won't + // find anymore an equivalent value. + break; + if (!__p->_M_next + || this->_M_bucket_index(__p->_M_next, _M_bucket_count) + != __n) + break; + } return __result; } @@ -809,21 +990,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count); - _Node** __head = _M_buckets + __n; - _Node* __p = _M_find_node(*__head, __k, __code); + _Node* __p = _M_find_node(__n, __k, __code); if (__p) { _Node* __p1 = __p->_M_next; - for (; __p1; __p1 = __p1->_M_next) - if (!this->_M_compare(__k, __code, __p1)) - break; + while (__p1 + && this->_M_bucket_index(__p1, _M_bucket_count) == __n + && this->_M_compare(__k, __code, __p1)) + __p1 = __p1->_M_next; - iterator __first(__p, __head); - iterator __last(__p1, __head); - if (!__p1) - __last._M_incr_bucket(); - return std::make_pair(__first, __last); + return std::make_pair(iterator(__p), iterator(__p1)); } else return std::make_pair(this->end(), this->end()); @@ -847,28 +1024,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count); - _Node** __head = _M_buckets + __n; - _Node* __p = _M_find_node(*__head, __k, __code); + _Node* __p = _M_find_node(__n, __k, __code); if (__p) { _Node* __p1 = __p->_M_next; - for (; __p1; __p1 = __p1->_M_next) - if (!this->_M_compare(__k, __code, __p1)) - break; + while (__p1 + && this->_M_bucket_index(__p1, _M_bucket_count) == __n + && this->_M_compare(__k, __code, __p1)) + __p1 = __p1->_M_next; - const_iterator __first(__p, __head); - const_iterator __last(__p1, __head); - if (!__p1) - __last._M_incr_bucket(); - return std::make_pair(__first, __last); + return std::make_pair(const_iterator(__p), const_iterator(__p1)); } else return std::make_pair(this->end(), this->end()); } - // Find the node whose key compares equal to k, beginning the search - // at p (usually the head of a bucket). Return nil if no node is found. + // Find the node whose key compares equal to k in the bucket n. Return nullptr + // if no node is found. template<typename _Key, typename _Value, typename _Allocator, typename _ExtractKey, typename _Equal, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, @@ -878,13 +1051,131 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __chc, __cit, __uk>::_Node* _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: - _M_find_node(_Node* __p, const key_type& __k, + _M_find_node(size_type __n, const key_type& __k, typename _Hashtable::_Hash_code_type __code) const { - for (; __p; __p = __p->_M_next) - if (this->_M_compare(__k, __code, __p)) - return __p; - return false; + _Node* __p = _M_bucket_begin(__n); + if (!__p) + return nullptr; + for (;; __p = __p->_M_next) + { + if (this->_M_compare(__k, __code, __p)) + return __p; + if (!(__p->_M_next) + || this->_M_bucket_index(__p->_M_next, _M_bucket_count) != __n) + break; + } + return nullptr; + } + + template<typename _Key, typename _Value, + typename _Allocator, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + bool __chc, bool __cit, bool __uk> + void + _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: + _M_insert_bucket_begin(size_type __bkt, _Node* __new_node) + { + _Node* __prev_n; + if (__bkt < _M_begin_bucket_index) + { + if (_M_begin_bucket_index != _M_bucket_count) + { + __new_node->_M_next = _M_buckets[_M_begin_bucket_index]; + _M_buckets[_M_begin_bucket_index] = __new_node; + } + __prev_n = __new_node; + _M_begin_bucket_index = __bkt; + } + else + { + // We need to find previous non-empty bucket to link the new node. + // There are several ways to find this previous bucket: + // 1. Move backward until we find it (the current method) + // 2. Start from the begin bucket index and move forward until we + // cross __n position. + // 3. Move forward until we find a non-empty bucket that will + // contain the previous node. + size_type __prev_bkt; + for (__prev_bkt = __bkt; __prev_bkt-- != 0;) + if (_M_buckets[__prev_bkt]) + break; + __prev_n = _M_bucket_end(__prev_bkt); + _M_insert_after(__prev_bkt, __prev_n, __new_node); + } + _M_buckets[__bkt] = __prev_n; + } + + template<typename _Key, typename _Value, + typename _Allocator, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + bool __chc, bool __cit, bool __uk> + void + _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: + _M_insert_after(size_type __bkt, _Node* __prev_n, _Node* __new_n) + { + if (__prev_n->_M_next) + { + size_type __next_bkt = + this->_M_bucket_index(__prev_n->_M_next, _M_bucket_count); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __new_n; + } + __new_n->_M_next = __prev_n->_M_next; + __prev_n->_M_next = __new_n; + } + + template<typename _Key, typename _Value, + typename _Allocator, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + bool __chc, bool __cit, bool __uk> + void + _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: + _M_remove_bucket_begin(size_type __bkt, _Node* __next, size_type __next_bkt) + { + if (!__next || __next_bkt != __bkt) + { + // Bucket is now empty + if (__next && __next_bkt != __bkt) + // Update next non-empty bucket before begin node + _M_buckets[__next_bkt] = _M_buckets[__bkt]; + _M_buckets[__bkt] = nullptr; + if (__bkt == _M_begin_bucket_index) + // We need to update begin bucket index + if (__next) + { + _M_begin_bucket_index = __next_bkt; + _M_buckets[_M_begin_bucket_index] = __next; + } + else + _M_begin_bucket_index = _M_bucket_count; + } + else if (__bkt == _M_begin_bucket_index) + _M_buckets[__bkt] = __next; + } + + template<typename _Key, typename _Value, + typename _Allocator, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + bool __chc, bool __cit, bool __uk> + typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, + _Equal, _H1, _H2, _Hash, _RehashPolicy, + __chc, __cit, __uk>::_Node* + _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: + _M_get_previous_node(size_type __bkt, _Node* __n) + { + _Node* __prev_n = nullptr; + if (__bkt != _M_begin_bucket_index || __n != _M_buckets[__bkt]) + { + __prev_n = _M_buckets[__bkt]; + while (__prev_n->_M_next != __n) + __prev_n = __prev_n->_M_next; + } + return __prev_n; } // Insert v in bucket n (assumes no element with its key already present). @@ -901,7 +1192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_insert_bucket(_Arg&& __v, size_type __n, typename _Hashtable::_Hash_code_type __code) { - const size_type __saved_next_resize = _M_rehash_policy._M_next_resize; + const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state(); std::pair<bool, std::size_t> __do_rehash = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1); @@ -912,27 +1203,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __n = this->_M_bucket_index(__k, __code, __do_rehash.second); } - _Node* __new_node = 0; + _Node* __new_node = nullptr; __try { // Allocate the new node before doing the rehash so that we // don't do a rehash if the allocation throws. __new_node = _M_allocate_node(std::forward<_Arg>(__v)); + this->_M_store_code(__new_node, __code); if (__do_rehash.first) - _M_rehash(__do_rehash.second, __saved_next_resize); + _M_rehash(__do_rehash.second, __saved_state); - __new_node->_M_next = _M_buckets[__n]; - this->_M_store_code(__new_node, __code); - _M_buckets[__n] = __new_node; + if (_M_buckets[__n]) + _M_insert_after(__n, _M_buckets[__n], __new_node); + else + _M_insert_bucket_begin(__n, __new_node); ++_M_element_count; - if (__n < _M_begin_bucket_index) - _M_begin_bucket_index = __n; - return iterator(__new_node, _M_buckets + __n); + return iterator(__new_node); } __catch(...) { if (!__new_node) - _M_rehash_policy._M_next_resize = __saved_next_resize; + _M_rehash_policy._M_reset(__saved_state); else _M_deallocate_node(__new_node); __throw_exception_again; @@ -957,8 +1248,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count); - if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code)) - return std::make_pair(iterator(__p, _M_buckets + __n), false); + if (_Node* __p = _M_find_node(__n, __k, __code)) + return std::make_pair(iterator(__p), false); return std::make_pair(_M_insert_bucket(std::forward<_Arg>(__v), __n, __code), true); } @@ -976,37 +1267,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: _M_insert(_Arg&& __v, std::false_type) { - const size_type __saved_next_resize = _M_rehash_policy._M_next_resize; + const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state(); std::pair<bool, std::size_t> __do_rehash = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1); - if (__do_rehash.first) - _M_rehash(__do_rehash.second, __saved_next_resize); const key_type& __k = this->_M_extract(__v); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count); // First find the node, avoid leaking new_node if compare throws. - _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code); - _Node* __new_node = _M_allocate_node(std::forward<_Arg>(__v)); - - if (__prev) + _Node* __prev = _M_find_node(__n, __k, __code); + _Node* __new_node = nullptr; + __try { - __new_node->_M_next = __prev->_M_next; - __prev->_M_next = __new_node; + // Second allocate new node so that we don't rehash if it throws + __new_node = _M_allocate_node(std::forward<_Arg>(__v)); + this->_M_store_code(__new_node, __code); + if (__do_rehash.first) + { + _M_rehash(__do_rehash.second, __saved_state); + __n = this->_M_bucket_index(__k, __code, _M_bucket_count); + // __prev is still valid because rehash do not invalidate nodes + } + + if (__prev) + // Insert after the previous equivalent node + _M_insert_after(__n, __prev, __new_node); + else if (_M_buckets[__n]) + // Bucket is not empty and the inserted node has no equivalent in + // the hashtable. We must insert the new node at the beginning or + // end of the bucket to preserve equivalent elements relative + // positions. + if (__n != _M_begin_bucket_index) + // We insert the new node at the beginning + _M_insert_after(__n, _M_buckets[__n], __new_node); + else + // We insert the new node at the end + _M_insert_after(__n, _M_bucket_end(__n), __new_node); + else + _M_insert_bucket_begin(__n, __new_node); + ++_M_element_count; + return iterator(__new_node); } - else + __catch(...) { - __new_node->_M_next = _M_buckets[__n]; - _M_buckets[__n] = __new_node; - if (__n < _M_begin_bucket_index) - _M_begin_bucket_index = __n; + if (!__new_node) + _M_rehash_policy._M_reset(__saved_state); + else + _M_deallocate_node(__new_node); + __throw_exception_again; } - this->_M_store_code(__new_node, __code); - ++_M_element_count; - return iterator(__new_node, _M_buckets + __n); } template<typename _Key, typename _Value, @@ -1020,12 +1332,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION insert(_InputIterator __first, _InputIterator __last) { size_type __n_elt = __detail::__distance_fw(__first, __last); - const size_type __saved_next_resize = _M_rehash_policy._M_next_resize; + const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state(); std::pair<bool, std::size_t> __do_rehash = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, __n_elt); if (__do_rehash.first) - _M_rehash(__do_rehash.second, __saved_next_resize); + _M_rehash(__do_rehash.second, __saved_state); for (; __first != __last; ++__first) this->insert(*__first); @@ -1042,31 +1354,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: erase(const_iterator __it) { - iterator __result(__it._M_cur_node, __it._M_cur_bucket); - ++__result; - - _Node* __cur = *__it._M_cur_bucket; - if (__cur == __it._M_cur_node) + _Node* __n = __it._M_cur; + std::size_t __bkt = this->_M_bucket_index(__n, _M_bucket_count); + + // Look for previous node to unlink it from the erased one, this is why + // we need buckets to contain the before begin node of the bucket to make + // this research fast. + _Node* __prev_n = _M_get_previous_node(__bkt, __n); + if (__n == _M_bucket_begin(__bkt)) + _M_remove_bucket_begin(__bkt, __n->_M_next, + __n->_M_next ? this->_M_bucket_index(__n->_M_next, _M_bucket_count) + : 0); + else if (__n->_M_next) { - *__it._M_cur_bucket = __cur->_M_next; - - // If _M_begin_bucket_index no longer indexes the first non-empty - // bucket - its single node is being erased - update it. - if (!_M_buckets[_M_begin_bucket_index]) - _M_begin_bucket_index = __result._M_cur_bucket - _M_buckets; - } - else - { - _Node* __next = __cur->_M_next; - while (__next != __it._M_cur_node) - { - __cur = __next; - __next = __cur->_M_next; - } - __cur->_M_next = __next->_M_next; + size_type __next_bkt = + this->_M_bucket_index(__n->_M_next, _M_bucket_count); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __prev_n; } - _M_deallocate_node(__it._M_cur_node); + if (__prev_n) + __prev_n->_M_next = __n->_M_next; + iterator __result(__n->_M_next); + _M_deallocate_node(__n); --_M_element_count; return __result; @@ -1084,64 +1394,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION erase(const key_type& __k) { typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k); - std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count); - size_type __result = 0; - - _Node** __slot = _M_buckets + __n; - while (*__slot && !this->_M_compare(__k, __code, *__slot)) - __slot = &((*__slot)->_M_next); + std::size_t __bkt = this->_M_bucket_index(__k, __code, _M_bucket_count); + // Look for the first matching node with its previous node at the same + // time + _Node* __n = _M_buckets[__bkt]; + if (!__n) + return 0; + _Node* __prev_n = nullptr; + if (__bkt != _M_begin_bucket_index) + { + __prev_n = __n; + __n = __n->_M_next; + } + bool __is_bucket_begin = true; + for (;; __prev_n = __n, __n = __n->_M_next) + { + if (this->_M_compare(__k, __code, __n)) + break; + if (!(__n->_M_next) + || this->_M_bucket_index(__n->_M_next, _M_bucket_count) != __bkt) + return 0; + __is_bucket_begin = false; + } - _Node** __saved_slot = 0; - while (*__slot && this->_M_compare(__k, __code, *__slot)) + // We found a matching node, start deallocation loop from it + std::size_t __next_bkt = __bkt; + _Node* __next_n = __n; + size_type __result = 0; + _Node* __saved_n = nullptr; + do { + _Node* __p = __next_n; + __next_n = __p->_M_next; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 526. Is it undefined if a function in the standard changes // in parameters? - if (std::__addressof(this->_M_extract((*__slot)->_M_v)) + if (std::__addressof(this->_M_extract(__p->_M_v)) != std::__addressof(__k)) - { - _Node* __p = *__slot; - *__slot = __p->_M_next; - _M_deallocate_node(__p); - --_M_element_count; - ++__result; - } + _M_deallocate_node(__p); else - { - __saved_slot = __slot; - __slot = &((*__slot)->_M_next); - } - } - - if (__saved_slot) - { - _Node* __p = *__saved_slot; - *__saved_slot = __p->_M_next; - _M_deallocate_node(__p); + __saved_n = __p; --_M_element_count; ++__result; + if (!__next_n) + break; + __next_bkt = this->_M_bucket_index(__next_n, _M_bucket_count); } - - // If the entire bucket indexed by _M_begin_bucket_index has been - // erased look forward for the first non-empty bucket. - if (!_M_buckets[_M_begin_bucket_index]) - { - if (!_M_element_count) - _M_begin_bucket_index = _M_bucket_count; - else - { - ++_M_begin_bucket_index; - while (!_M_buckets[_M_begin_bucket_index]) - ++_M_begin_bucket_index; - } - } - + while (__next_bkt == __bkt && this->_M_compare(__k, __code, __next_n)); + + if (__saved_n) + _M_deallocate_node(__saved_n); + if (__is_bucket_begin) + _M_remove_bucket_begin(__bkt, __next_n, __next_bkt); + else if (__next_n && __next_bkt != __bkt) + _M_buckets[__next_bkt] = __prev_n; + if (__prev_n) + __prev_n->_M_next = __next_n; return __result; } - // ??? This could be optimized by taking advantage of the bucket - // structure, but it's not clear that it's worth doing. It probably - // wouldn't even be an optimization unless the load factor is large. template<typename _Key, typename _Value, typename _Allocator, typename _ExtractKey, typename _Equal, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, @@ -1153,9 +1464,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: erase(const_iterator __first, const_iterator __last) { - while (__first != __last) - __first = this->erase(__first); - return iterator(__last._M_cur_node, __last._M_cur_bucket); + _Node* __n = __first._M_cur; + _Node* __last_n = __last._M_cur; + if (__n == __last_n) + return iterator(__n); + + std::size_t __bkt = this->_M_bucket_index(__n, _M_bucket_count); + + _Node* __prev_n = _M_get_previous_node(__bkt, __n); + bool __is_bucket_begin = __n == _M_bucket_begin(__bkt); + std::size_t __n_bkt = __bkt; + for (;;) + { + do + { + _Node* __tmp = __n; + __n = __n->_M_next; + _M_deallocate_node(__tmp); + --_M_element_count; + if (!__n) + break; + __n_bkt = this->_M_bucket_index(__n, _M_bucket_count); + } + while (__n != __last_n && __n_bkt == __bkt); + if (__is_bucket_begin) + _M_remove_bucket_begin(__bkt, __n, __n_bkt); + if (__n == __last_n) + break; + __is_bucket_begin = true; + __bkt = __n_bkt; + } + + if (__n && __n_bkt != __bkt) + _M_buckets[__n_bkt] = __prev_n; + if (__prev_n) + __prev_n->_M_next = __n; + return iterator(__n); } template<typename _Key, typename _Value, @@ -1167,7 +1511,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: clear() noexcept { - _M_deallocate_nodes(_M_buckets, _M_bucket_count); + _M_deallocate_nodes(_M_buckets[_M_begin_bucket_index]); + __builtin_memset(_M_buckets, 0, _M_bucket_count * sizeof(_Bucket)); _M_element_count = 0; _M_begin_bucket_index = _M_bucket_count; } @@ -1181,11 +1526,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: rehash(size_type __n) { - const size_type __saved_next_resize = _M_rehash_policy._M_next_resize; + const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state(); _M_rehash(std::max(_M_rehash_policy._M_next_bkt(__n), _M_rehash_policy._M_bkt_for_elements(_M_element_count + 1)), - __saved_next_resize); + __saved_state); } template<typename _Key, typename _Value, @@ -1195,46 +1540,75 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: - _M_rehash(size_type __n, size_type __next_resize) + _M_rehash(size_type __n, const _RehashPolicyState& __state) { - _Node** __new_array = 0; + _Bucket* __new_buckets = nullptr; + _Node* __p = _M_buckets[_M_begin_bucket_index]; __try { - __new_array = _M_allocate_buckets(__n); + __new_buckets = _M_allocate_buckets(__n); + // First loop to store each node in its new bucket + while (__p) + { + _Node* __next = __p->_M_next; + std::size_t __new_index = this->_M_bucket_index(__p, __n); + if (!__new_buckets[__new_index]) + // Store temporarily bucket end node in _M_buckets if possible. + // This will boost second loop where we need to access bucket + // end node quickly. + if (__new_index < _M_bucket_count) + _M_buckets[__new_index] = __p; + __p->_M_next = __new_buckets[__new_index]; + __new_buckets[__new_index] = __p; + __p = __next; + } _M_begin_bucket_index = __n; - for (size_type __i = 0; __i < _M_bucket_count; ++__i) - while (_Node* __p = _M_buckets[__i]) + _Node* __prev_node = nullptr; + // Second loop to link all nodes together and to fix bucket values so + // that they contain the before begin node of the bucket. + for (size_type __i = 0; __i != __n; ++__i) + if (__new_buckets[__i]) { - std::size_t __new_index = this->_M_bucket_index(__p, __n); - _M_buckets[__i] = __p->_M_next; - __p->_M_next = __new_array[__new_index]; - __new_array[__new_index] = __p; - if (__new_index < _M_begin_bucket_index) - _M_begin_bucket_index = __new_index; + if (__prev_node) + { + __prev_node->_M_next = __new_buckets[__i]; + __new_buckets[__i] = __prev_node; + } + else + _M_begin_bucket_index = __i; + if (__i < _M_bucket_count) + __prev_node = _M_buckets[__i]; + else + { + __prev_node = __new_buckets[__i]; + while (__prev_node->_M_next) + __prev_node = __prev_node->_M_next; + } } _M_deallocate_buckets(_M_buckets, _M_bucket_count); _M_bucket_count = __n; - _M_buckets = __new_array; + _M_buckets = __new_buckets; } __catch(...) { - if (__new_array) + if (__new_buckets) { // A failure here means that a hash function threw an exception. // We can't restore the previous state without calling the hash // function again, so the only sensible recovery is to delete // everything. - _M_deallocate_nodes(__new_array, __n); - _M_deallocate_buckets(__new_array, __n); - _M_deallocate_nodes(_M_buckets, _M_bucket_count); + _M_deallocate_nodes(__new_buckets, __n); + _M_deallocate_buckets(__new_buckets, __n); + _M_deallocate_nodes(__p); + __builtin_memset(_M_buckets, 0, sizeof(_Bucket) * _M_bucket_count); _M_element_count = 0; _M_begin_bucket_index = _M_bucket_count; - _M_rehash_policy._M_next_resize = 0; + _M_rehash_policy._M_reset(_RehashPolicyState()); } else // A failure here means that buckets allocation failed. We only // have to restore hash policy previous state. - _M_rehash_policy._M_next_resize = __next_resize; + _M_rehash_policy._M_reset(__state); __throw_exception_again; } } diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index acb7e99a8df..44c749af515 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -59,6 +59,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __distance_fw(__first, __last, _Tag()); } + // Helper type used to detect when the hash functor is noexcept qualified or + // not + template <typename _Key, typename _Hash> + struct __is_noexcept_hash : std::integral_constant<bool, + noexcept(declval<const _Hash&>()(declval<const _Key&>()))> + {}; + // Auxiliary types used for all instantiations of _Hashtable: nodes // and iterators. @@ -211,155 +218,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; - template<typename _Value, bool __cache> - struct _Hashtable_iterator_base - { - _Hashtable_iterator_base(_Hash_node<_Value, __cache>* __node, - _Hash_node<_Value, __cache>** __bucket) - : _M_cur_node(__node), _M_cur_bucket(__bucket) { } - - void - _M_incr() - { - _M_cur_node = _M_cur_node->_M_next; - if (!_M_cur_node) - _M_incr_bucket(); - } - - void - _M_incr_bucket(); - - _Hash_node<_Value, __cache>* _M_cur_node; - _Hash_node<_Value, __cache>** _M_cur_bucket; - }; - - // Global iterators, used for arbitrary iteration within a hash - // table. Larger and more expensive than local iterators. - template<typename _Value, bool __cache> - void - _Hashtable_iterator_base<_Value, __cache>:: - _M_incr_bucket() - { - ++_M_cur_bucket; - - // This loop requires the bucket array to have a non-null sentinel. - while (!*_M_cur_bucket) - ++_M_cur_bucket; - _M_cur_node = *_M_cur_bucket; - } - - template<typename _Value, bool __cache> - inline bool - operator==(const _Hashtable_iterator_base<_Value, __cache>& __x, - const _Hashtable_iterator_base<_Value, __cache>& __y) - { return __x._M_cur_node == __y._M_cur_node; } - - template<typename _Value, bool __cache> - inline bool - operator!=(const _Hashtable_iterator_base<_Value, __cache>& __x, - const _Hashtable_iterator_base<_Value, __cache>& __y) - { return __x._M_cur_node != __y._M_cur_node; } - - template<typename _Value, bool __constant_iterators, bool __cache> - struct _Hashtable_iterator - : public _Hashtable_iterator_base<_Value, __cache> - { - typedef _Value value_type; - typedef typename std::conditional<__constant_iterators, - const _Value*, _Value*>::type - pointer; - typedef typename std::conditional<__constant_iterators, - const _Value&, _Value&>::type - reference; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - _Hashtable_iterator() - : _Hashtable_iterator_base<_Value, __cache>(0, 0) { } - - _Hashtable_iterator(_Hash_node<_Value, __cache>* __p, - _Hash_node<_Value, __cache>** __b) - : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { } - - explicit - _Hashtable_iterator(_Hash_node<_Value, __cache>** __b) - : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { } - - reference - operator*() const - { return this->_M_cur_node->_M_v; } - - pointer - operator->() const - { return std::__addressof(this->_M_cur_node->_M_v); } - - _Hashtable_iterator& - operator++() - { - this->_M_incr(); - return *this; - } - - _Hashtable_iterator - operator++(int) - { - _Hashtable_iterator __tmp(*this); - this->_M_incr(); - return __tmp; - } - }; - - template<typename _Value, bool __constant_iterators, bool __cache> - struct _Hashtable_const_iterator - : public _Hashtable_iterator_base<_Value, __cache> - { - typedef _Value value_type; - typedef const _Value* pointer; - typedef const _Value& reference; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - _Hashtable_const_iterator() - : _Hashtable_iterator_base<_Value, __cache>(0, 0) { } - - _Hashtable_const_iterator(_Hash_node<_Value, __cache>* __p, - _Hash_node<_Value, __cache>** __b) - : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { } - - explicit - _Hashtable_const_iterator(_Hash_node<_Value, __cache>** __b) - : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { } - - _Hashtable_const_iterator(const _Hashtable_iterator<_Value, - __constant_iterators, __cache>& __x) - : _Hashtable_iterator_base<_Value, __cache>(__x._M_cur_node, - __x._M_cur_bucket) { } - - reference - operator*() const - { return this->_M_cur_node->_M_v; } - - pointer - operator->() const - { return std::__addressof(this->_M_cur_node->_M_v); } - - _Hashtable_const_iterator& - operator++() - { - this->_M_incr(); - return *this; - } - - _Hashtable_const_iterator - operator++(int) - { - _Hashtable_const_iterator __tmp(*this); - this->_M_incr(); - return __tmp; - } - }; - - // Many of class template _Hashtable's template parameters are policy // classes. These are defaults for the policies. @@ -388,7 +246,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _Prime_rehash_policy { _Prime_rehash_policy(float __z = 1.0) - : _M_max_load_factor(__z), _M_growth_factor(2.f), _M_next_resize(0) { } + : _M_max_load_factor(__z), _M_prev_resize(0), _M_next_resize(0) { } float max_load_factor() const noexcept @@ -410,10 +268,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, std::size_t __n_ins) const; + typedef std::pair<std::size_t, std::size_t> _State; + + _State + _M_state() const + { return std::make_pair(_M_prev_resize, _M_next_resize); } + + void + _M_reset(const _State& __state) + { + _M_prev_resize = __state.first; + _M_next_resize = __state.second; + } + enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 }; float _M_max_load_factor; - float _M_growth_factor; + mutable std::size_t _M_prev_resize; mutable std::size_t _M_next_resize; }; @@ -429,15 +300,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // Optimize lookups involving the first elements of __prime_list. // (useful to speed-up, eg, constructors) - static const unsigned char __fast_bkt[12] + static const unsigned long __fast_bkt[12] = { 2, 2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11 }; - const unsigned long __p - = __n <= 11 ? __fast_bkt[__n] - : *std::lower_bound(__prime_list + 5, - __prime_list + _S_n_primes, __n); - _M_next_resize = __builtin_floor(__p * (long double)_M_max_load_factor); - return __p; + const unsigned long* __p + = __n <= 11 ? __fast_bkt + __n + : std::lower_bound(__prime_list + 5, + __prime_list + _S_n_primes, __n); + + _M_prev_resize = __builtin_floor(*__p * (long double)_M_max_load_factor); + if (__p != __fast_bkt) + _M_prev_resize = std::min(_M_prev_resize, + static_cast<std::size_t>(*(__p - 1))); + // Lets guaranty a minimal grow step of 11: + if (*__p - __n < 11) + __p = std::lower_bound(__prime_list + 5, + __prime_list + _S_n_primes, __n + 11); + _M_next_resize = __builtin_floor(*__p * (long double)_M_max_load_factor); + return *__p; } // Return the smallest prime p such that alpha p >= n, where alpha @@ -461,17 +341,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, std::size_t __n_ins) const { - if (__n_elt + __n_ins > _M_next_resize) + if (__n_elt + __n_ins >= _M_next_resize) { - long double __min_bkts = ((__n_elt + __n_ins) - / (long double)_M_max_load_factor); - if (__min_bkts > __n_bkt) - { - __min_bkts = std::max(__min_bkts, (long double)_M_growth_factor - * __n_bkt); - return std::make_pair(true, - _M_next_bkt(__builtin_ceil(__min_bkts))); - } + long double __min_bkts = (__n_elt + __n_ins) + / (long double)_M_max_load_factor; + if (__min_bkts >= __n_bkt) + return std::make_pair(true, + _M_next_bkt(__builtin_floor(__min_bkts) + 1)); else { _M_next_resize @@ -479,6 +355,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::make_pair(false, 0); } } + else if (__n_elt + __n_ins < _M_prev_resize) + { + long double __min_bkts = (__n_elt + __n_ins) + / (long double)_M_max_load_factor; + return std::make_pair(true, + _M_next_bkt(__builtin_floor(__min_bkts) + 1)); + } else return std::make_pair(false, 0); } @@ -538,8 +421,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::size_t __n = __h->_M_bucket_index(__k, __code, __h->_M_bucket_count); - typename _Hashtable::_Node* __p = - __h->_M_find_node(__h->_M_buckets[__n], __k, __code); + typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code); if (!__p) return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()), __n, __code)->second; @@ -557,8 +439,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::size_t __n = __h->_M_bucket_index(__k, __code, __h->_M_bucket_count); - typename _Hashtable::_Node* __p = - __h->_M_find_node(__h->_M_buckets[__n], __k, __code); + typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code); if (!__p) return __h->_M_insert_bucket(std::make_pair(std::move(__k), mapped_type()), @@ -577,8 +458,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::size_t __n = __h->_M_bucket_index(__k, __code, __h->_M_bucket_count); - typename _Hashtable::_Node* __p = - __h->_M_find_node(__h->_M_buckets[__n], __k, __code); + typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code); if (!__p) __throw_out_of_range(__N("_Map_base::at")); return (__p->_M_v).second; @@ -595,8 +475,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::size_t __n = __h->_M_bucket_index(__k, __code, __h->_M_bucket_count); - typename _Hashtable::_Node* __p = - __h->_M_find_node(__h->_M_buckets[__n], __k, __code); + typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code); if (!__p) __throw_out_of_range(__N("_Map_base::at")); return (__p->_M_v).second; diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index 32addf95105..33128dd4ed6 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -619,7 +619,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, shared_ptr<_Tp>> { size_t - operator()(const shared_ptr<_Tp>& __s) const + operator()(const shared_ptr<_Tp>& __s) const noexcept { return std::hash<_Tp*>()(__s.get()); } }; diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index fbbadd1aaaa..c0677547553 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -1450,7 +1450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>> { size_t - operator()(const __shared_ptr<_Tp, _Lp>& __s) const + operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept { return std::hash<_Tp*>()(__s.get()); } }; diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 8f286400aec..bec63ff03f9 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -1075,7 +1075,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, _GLIBCXX_STD_C::vector<bool, _Alloc>> { size_t - operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const; + operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>&) const noexcept; }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index 45824f04079..f1c4cfefa57 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -617,6 +617,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator erase(const_iterator __position) { return _M_t.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_t.erase(__position); } #else /** * @brief Erases an element from a %map. diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index fd5a5a8cffb..ae4389e2709 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -536,6 +536,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator erase(const_iterator __position) { return _M_t.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_t.erase(__position); } #else /** * @brief Erases an element from a %multimap. diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 8c5f0c30a0f..ee56bbc7525 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -767,6 +767,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_erase_aux(__position); return __result._M_const_cast(); } + + // LWG 2059. + iterator + erase(iterator __position) + { + iterator __result = __position; + ++__result; + _M_erase_aux(__position); + return __result; + } #else void erase(iterator __position) diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 869d931330c..0a127996e52 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -545,7 +545,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, unique_ptr<_Tp, _Dp>> { size_t - operator()(const unique_ptr<_Tp, _Dp>& __u) const + operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept { typedef unique_ptr<_Tp, _Dp> _UP; return std::hash<typename _UP::pointer>()(__u.get()); diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index c77bab12fba..7c810d3801f 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -40,7 +40,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER class _Hash = hash<_Key>, class _Pred = std::equal_to<_Key>, class _Alloc = std::allocator<std::pair<const _Key, _Tp> >, - bool __cache_hash_code = false> + bool __cache_hash_code = + __not_<__and_<is_integral<_Key>, + __detail::__is_noexcept_hash<_Key, _Hash>>>::value> class __unordered_map : public _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, std::_Select1st<std::pair<const _Key, _Tp> >, _Pred, @@ -109,7 +111,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER class _Hash = hash<_Key>, class _Pred = std::equal_to<_Key>, class _Alloc = std::allocator<std::pair<const _Key, _Tp> >, - bool __cache_hash_code = false> + bool __cache_hash_code = + __not_<__and_<is_integral<_Key>, + __detail::__is_noexcept_hash<_Key, _Hash>>>::value> class __unordered_multimap : public _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h index 12b7bda138f..9aef0829749 100644 --- a/libstdc++-v3/include/bits/unordered_set.h +++ b/libstdc++-v3/include/bits/unordered_set.h @@ -40,7 +40,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER class _Hash = hash<_Value>, class _Pred = std::equal_to<_Value>, class _Alloc = std::allocator<_Value>, - bool __cache_hash_code = false> + bool __cache_hash_code = + __not_<__and_<is_integral<_Value>, + __detail::__is_noexcept_hash<_Value, _Hash>>>::value> class __unordered_set : public _Hashtable<_Value, _Value, _Alloc, std::_Identity<_Value>, _Pred, @@ -121,7 +123,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER class _Hash = hash<_Value>, class _Pred = std::equal_to<_Value>, class _Alloc = std::allocator<_Value>, - bool __cache_hash_code = false> + bool __cache_hash_code = + __not_<__and_<is_integral<_Value>, + __detail::__is_noexcept_hash<_Value, _Hash>>>::value> class __unordered_multiset : public _Hashtable<_Value, _Value, _Alloc, std::_Identity<_Value>, _Pred, diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index b74684228c1..d9c3b659e6b 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -818,7 +818,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Alloc> size_t hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>:: - operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const + operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const noexcept { size_t __hash = 0; using _GLIBCXX_STD_C::_S_word_bit; diff --git a/libstdc++-v3/include/debug/bitset b/libstdc++-v3/include/debug/bitset index 21d281787ad..3d865c1c1c2 100644 --- a/libstdc++-v3/include/debug/bitset +++ b/libstdc++-v3/include/debug/bitset @@ -51,7 +51,7 @@ namespace __debug public: // In C++0x we rely on normal reference type to preserve the property // of bitset to be use as a literal. - // TODO: Find an other solution. + // TODO: Find another solution. #ifdef __GXX_EXPERIMENTAL_CXX0X__ typedef typename _Base::reference reference; #else @@ -272,11 +272,14 @@ namespace __debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // 11. Bitset minor problems - bool + _GLIBCXX_CONSTEXPR bool operator[](size_t __pos) const { +#ifndef __GXX_EXPERIMENTAL_CXX0X__ + // TODO: Check in debug-mode too. __glibcxx_check_subscript(__pos); - return _M_base()[__pos]; +#endif + return _Base::operator[](__pos); } using _Base::to_ulong; @@ -414,7 +417,7 @@ namespace __debug : public __hash_base<size_t, __debug::bitset<_Nb>> { size_t - operator()(const __debug::bitset<_Nb>& __b) const + operator()(const __debug::bitset<_Nb>& __b) const noexcept { return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); } }; #endif diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h index e80c1e3b4b7..9abfee867d0 100644 --- a/libstdc++-v3/include/debug/map.h +++ b/libstdc++-v3/include/debug/map.h @@ -271,6 +271,10 @@ namespace __debug this->_M_invalidate_if(_Equal(__position.base())); return iterator(_Base::erase(__position.base()), this); } + + iterator + erase(iterator __position) + { return erase(const_iterator(__position)); } #else void erase(iterator __position) diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h index cf18d7cc114..e43094f8b4d 100644 --- a/libstdc++-v3/include/debug/multimap.h +++ b/libstdc++-v3/include/debug/multimap.h @@ -254,6 +254,10 @@ namespace __debug this->_M_invalidate_if(_Equal(__position.base())); return iterator(_Base::erase(__position.base()), this); } + + iterator + erase(iterator __position) + { return erase(const_iterator(__position)); } #else void erase(iterator __position) diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map index 6eeff6429e4..6ad46b627d3 100644 --- a/libstdc++-v3/include/debug/unordered_map +++ b/libstdc++-v3/include/debug/unordered_map @@ -334,6 +334,10 @@ namespace __debug } iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator erase(const_iterator __first, const_iterator __last) { __glibcxx_check_erase_range(__first, __last); @@ -391,11 +395,11 @@ namespace __debug static _Base_local_iterator _S_to_local(_Base_iterator __it) - { return _Base_local_iterator(__it._M_cur_node); } + { return _Base_local_iterator(__it._M_cur); } static _Base_const_local_iterator _S_to_local(_Base_const_iterator __it) - { return _Base_const_local_iterator(__it._M_cur_node); } + { return _Base_const_local_iterator(__it._M_cur); } }; template<typename _Key, typename _Tp, typename _Hash, @@ -709,6 +713,10 @@ namespace __debug } iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator erase(const_iterator __first, const_iterator __last) { __glibcxx_check_erase_range(__first, __last); @@ -766,11 +774,11 @@ namespace __debug static _Base_local_iterator _S_to_local(_Base_iterator __it) - { return _Base_local_iterator(__it._M_cur_node); } + { return _Base_local_iterator(__it._M_cur); } static _Base_const_local_iterator _S_to_local(_Base_const_iterator __it) - { return _Base_const_local_iterator(__it._M_cur_node); } + { return _Base_const_local_iterator(__it._M_cur); } }; template<typename _Key, typename _Tp, typename _Hash, diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set index 0cc3a12cf37..2f41bc3a25d 100644 --- a/libstdc++-v3/include/debug/unordered_set +++ b/libstdc++-v3/include/debug/unordered_set @@ -330,6 +330,10 @@ namespace __debug } iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator erase(const_iterator __first, const_iterator __last) { __glibcxx_check_erase_range(__first, __last); @@ -390,11 +394,11 @@ namespace __debug static _Base_local_iterator _S_to_local(_Base_iterator __it) - { return _Base_local_iterator(__it._M_cur_node); } + { return _Base_local_iterator(__it._M_cur); } static _Base_const_local_iterator _S_to_local(_Base_const_iterator __it) - { return _Base_const_local_iterator(__it._M_cur_node); } + { return _Base_const_local_iterator(__it._M_cur); } }; template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> @@ -696,6 +700,10 @@ namespace __debug } iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator erase(const_iterator __first, const_iterator __last) { __glibcxx_check_erase_range(__first, __last); @@ -751,11 +759,11 @@ namespace __debug static _Base_local_iterator _S_to_local(_Base_iterator __it) - { return _Base_local_iterator(__it._M_cur_node); } + { return _Base_local_iterator(__it._M_cur); } static _Base_const_local_iterator _S_to_local(_Base_const_iterator __it) - { return _Base_const_local_iterator(__it._M_cur_node); } + { return _Base_const_local_iterator(__it._M_cur); } }; template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index 82662b44605..5ee0fabc32a 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -625,7 +625,7 @@ namespace __debug : public __hash_base<size_t, __debug::vector<bool, _Alloc>> { size_t - operator()(const __debug::vector<bool, _Alloc>& __b) const + operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>() (__b._M_base()); } }; diff --git a/libstdc++-v3/include/ext/vstring.h b/libstdc++-v3/include/ext/vstring.h index a613e364d3a..8c4120a3be2 100644 --- a/libstdc++-v3/include/ext/vstring.h +++ b/libstdc++-v3/include/ext/vstring.h @@ -2769,7 +2769,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, __gnu_cxx::__vstring> { size_t - operator()(const __gnu_cxx::__vstring& __s) const + operator()(const __gnu_cxx::__vstring& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length()); } }; @@ -2780,7 +2780,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, __gnu_cxx::__wvstring> { size_t - operator()(const __gnu_cxx::__wvstring& __s) const + operator()(const __gnu_cxx::__wvstring& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } }; @@ -2793,7 +2793,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, __gnu_cxx::__u16vstring> { size_t - operator()(const __gnu_cxx::__u16vstring& __s) const + operator()(const __gnu_cxx::__u16vstring& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length() * sizeof(char16_t)); } }; @@ -2804,7 +2804,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, __gnu_cxx::__u32vstring> { size_t - operator()(const __gnu_cxx::__u32vstring& __s) const + operator()(const __gnu_cxx::__u32vstring& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), __s.length() * sizeof(char32_t)); } }; diff --git a/libstdc++-v3/include/profile/bitset b/libstdc++-v3/include/profile/bitset index bd4aa3e152f..17ee49b5a60 100644 --- a/libstdc++-v3/include/profile/bitset +++ b/libstdc++-v3/include/profile/bitset @@ -232,10 +232,10 @@ namespace __profile // _GLIBCXX_RESOLVE_LIB_DEFECTS // 11. Bitset minor problems - bool + _GLIBCXX_CONSTEXPR bool operator[](size_t __pos) const { - return _M_base()[__pos]; + return _Base::operator[](__pos); } using _Base::to_ulong; @@ -372,7 +372,7 @@ namespace __profile : public __hash_base<size_t, __profile::bitset<_Nb>> { size_t - operator()(const __profile::bitset<_Nb>& __b) const + operator()(const __profile::bitset<_Nb>& __b) const noexcept { return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); } }; #endif diff --git a/libstdc++-v3/include/profile/map.h b/libstdc++-v3/include/profile/map.h index 622bc575ad2..eb5c5d90d9c 100644 --- a/libstdc++-v3/include/profile/map.h +++ b/libstdc++-v3/include/profile/map.h @@ -327,6 +327,10 @@ namespace __profile __profcxx_map_to_unordered_map_erase(this, size(), 1); return __i; } + + iterator + erase(iterator __position) + { return erase(const_iterator(__position)); } #else void erase(iterator __position) diff --git a/libstdc++-v3/include/profile/multimap.h b/libstdc++-v3/include/profile/multimap.h index 547a221b330..b71be4570bd 100644 --- a/libstdc++-v3/include/profile/multimap.h +++ b/libstdc++-v3/include/profile/multimap.h @@ -226,6 +226,10 @@ namespace __profile iterator erase(const_iterator __position) { return iterator(_Base::erase(__position)); } + + iterator + erase(iterator __position) + { return iterator(_Base::erase(__position)); } #else void erase(iterator __position) diff --git a/libstdc++-v3/include/profile/vector b/libstdc++-v3/include/profile/vector index 86aefd649e3..0526c5aabb7 100644 --- a/libstdc++-v3/include/profile/vector +++ b/libstdc++-v3/include/profile/vector @@ -529,7 +529,7 @@ namespace __profile : public __hash_base<size_t, __profile::vector<bool, _Alloc>> { size_t - operator()(const __profile::vector<bool, _Alloc>& __b) const + operator()(const __profile::vector<bool, _Alloc>& __b) const noexcept { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>() (__b._M_base()); } }; diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index 813ed4b2599..e07c5e08970 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -1555,7 +1555,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, _GLIBCXX_STD_C::bitset<_Nb>> { size_t - operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const + operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const noexcept { const size_t __clength = (_Nb + __CHAR_BIT__ - 1) / __CHAR_BIT__; return std::_Hash_impl::hash(__b._M_getdata(), __clength); @@ -1567,7 +1567,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, _GLIBCXX_STD_C::bitset<0>> { size_t - operator()(const _GLIBCXX_STD_C::bitset<0>&) const + operator()(const _GLIBCXX_STD_C::bitset<0>&) const noexcept { return 0; } }; diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 4a04eca8969..465fc569b23 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -843,22 +843,24 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) : public integral_constant<int, 0> { }; - /// The type of placeholder objects defined by libstdc++. + /** @brief The type of placeholder objects defined by libstdc++. + * @ingroup binders + */ template<int _Num> struct _Placeholder { }; _GLIBCXX_END_NAMESPACE_VERSION /** @namespace std::placeholders - * @brief ISO C++ 0x entities sub namespace for functional. + * @brief ISO C++11 entities sub-namespace for functional. * @ingroup binders - * - * Define a large number of placeholders. There is no way to - * simplify this with variadic templates, because we're introducing - * unique names for each. */ namespace placeholders { _GLIBCXX_BEGIN_NAMESPACE_VERSION + /* Define a large number of placeholders. There is no way to + * simplify this with variadic templates, because we're introducing + * unique names for each. + */ extern const _Placeholder<1> _1; extern const _Placeholder<2> _2; extern const _Placeholder<3> _3; @@ -903,6 +905,11 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) : public integral_constant<int, _Num> { }; + template<int _Num> + struct is_placeholder<const _Placeholder<_Num> > + : public integral_constant<int, _Num> + { }; + /** * Used by _Safe_tuple_element to indicate that there is no tuple * element at this position. @@ -1424,8 +1431,56 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) * @brief Class template _Bind is always a bind expression. * @ingroup binders */ + template<typename _Signature> + struct is_bind_expression<const _Bind<_Signature> > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template<typename _Signature> + struct is_bind_expression<volatile _Bind<_Signature> > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template<typename _Signature> + struct is_bind_expression<const volatile _Bind<_Signature>> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template<typename _Result, typename _Signature> + struct is_bind_expression<_Bind_result<_Result, _Signature>> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template<typename _Result, typename _Signature> + struct is_bind_expression<const _Bind_result<_Result, _Signature>> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template<typename _Result, typename _Signature> + struct is_bind_expression<volatile _Bind_result<_Result, _Signature>> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ template<typename _Result, typename _Signature> - struct is_bind_expression<_Bind_result<_Result, _Signature> > + struct is_bind_expression<const volatile _Bind_result<_Result, _Signature>> : public true_type { }; // Trait type used to remove std::bind() from overload set via SFINAE diff --git a/libstdc++-v3/include/std/iomanip b/libstdc++-v3/include/std/iomanip index ea2c44acf6f..e725b2514df 100644 --- a/libstdc++-v3/include/std/iomanip +++ b/libstdc++-v3/include/std/iomanip @@ -1,7 +1,7 @@ // Standard stream manipulators -*- C++ -*- // 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 @@ -262,18 +262,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, _Get_money<_MoneyT> __f) { - typedef istreambuf_iterator<_CharT, _Traits> _Iter; - typedef money_get<_CharT, _Iter> _MoneyGet; - - ios_base::iostate __err = ios_base::goodbit; - const _MoneyGet& __mg = use_facet<_MoneyGet>(__is.getloc()); - - __mg.get(_Iter(__is.rdbuf()), _Iter(), __f._M_intl, - __is, __err, __f._M_mon); - - if (ios_base::goodbit != __err) - __is.setstate(__err); - + typename basic_istream<_CharT, _Traits>::sentry __cerb(__is, false); + if (__cerb) + { + ios_base::iostate __err = ios_base::goodbit; + __try + { + typedef istreambuf_iterator<_CharT, _Traits> _Iter; + typedef money_get<_CharT, _Iter> _MoneyGet; + + const _MoneyGet& __mg = use_facet<_MoneyGet>(__is.getloc()); + __mg.get(_Iter(__is.rdbuf()), _Iter(), __f._M_intl, + __is, __err, __f._M_mon); + } + __catch(__cxxabiv1::__forced_unwind&) + { + __is._M_setstate(ios_base::badbit); + __throw_exception_again; + } + __catch(...) + { __is._M_setstate(ios_base::badbit); } + if (ios_base::goodbit != __err) + __is.setstate(__err); + } return __is; } @@ -298,16 +309,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, _Put_money<_MoneyT> __f) { - typedef ostreambuf_iterator<_CharT, _Traits> _Iter; - typedef money_put<_CharT, _Iter> _MoneyPut; - - const _MoneyPut& __mp = use_facet<_MoneyPut>(__os.getloc()); - const _Iter __end = __mp.put(_Iter(__os.rdbuf()), __f._M_intl, - __os, __os.fill(), __f._M_mon); - - if (__end.failed()) - __os.setstate(ios_base::badbit); - + typename basic_ostream<_CharT, _Traits>::sentry __cerb(__os); + if (__cerb) + { + __try + { + typedef ostreambuf_iterator<_CharT, _Traits> _Iter; + typedef money_put<_CharT, _Iter> _MoneyPut; + const _MoneyPut& __mp = use_facet<_MoneyPut>(__os.getloc()); + const _Iter __end = __mp.put(_Iter(__os.rdbuf()), __f._M_intl, + __os, __os.fill(), __f._M_mon); + if (__end.failed()) + __os.setstate(ios_base::badbit); + } + __catch(__cxxabiv1::__forced_unwind&) + { + __os._M_setstate(ios_base::badbit); + __throw_exception_again; + } + __catch(...) + { __os._M_setstate(ios_base::badbit); } + } return __os; } diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index 565261e709b..19482bc2181 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -361,7 +361,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, error_code> { size_t - operator()(const error_code& __e) const + operator()(const error_code& __e) const noexcept { const size_t __tmp = std::_Hash_impl::hash(__e._M_value); return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp); diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 8cc06903ebf..1d1733731bf 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -221,7 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __hash_base<size_t, thread::id> { size_t - operator()(const thread::id& __id) const + operator()(const thread::id& __id) const noexcept { return std::_Hash_impl::hash(__id._M_thread); } }; diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 51be289d506..282d4509d3a 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -69,35 +69,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __add_r_ref<_Tp&> { typedef _Tp& type; }; - // To work around c++/49225 aka c++/48322. - template<typename...> - struct __conv_types { }; - - template<typename _Tuple1, typename _Tuple2> - struct __one_by_one_convertible - : public false_type { }; - - template<typename _Tp, typename _Up> - struct __one_by_one_convertible<__conv_types<_Tp>, __conv_types<_Up>> - : public is_convertible<_Tp, _Up>::type { }; - - template<typename _T1, typename... _TR, typename _U1, typename... _UR> - struct __one_by_one_convertible<__conv_types<_T1, _TR...>, - __conv_types<_U1, _UR...>> - : public __and_<is_convertible<_T1, _U1>, - __one_by_one_convertible<__conv_types<_TR...>, - __conv_types<_UR...>>>::type - { }; - - template<typename _Tuple1, typename _Tuple2> - struct __all_convertible; - - template<typename... _TTypes, typename... _UTypes> - struct __all_convertible<__conv_types<_TTypes...>, - __conv_types<_UTypes...>> - : public __one_by_one_convertible<__conv_types<_TTypes...>, - __conv_types<_UTypes...>>::type { }; - template<std::size_t _Idx, typename _Head, bool _IsEmpty> struct _Head_base; @@ -408,11 +379,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(__elements...) { } template<typename... _UElements, typename = typename - enable_if<__and_<integral_constant<bool, sizeof...(_UElements) - == sizeof...(_Elements)>, - __all_convertible<__conv_types<_UElements...>, - __conv_types<_Elements...>> - >::value>::type> + enable_if<__and_<is_convertible<_UElements, + _Elements>...>::value>::type> explicit constexpr tuple(_UElements&&... __elements) : _Inherited(std::forward<_UElements>(__elements)...) { } @@ -422,21 +390,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr tuple(tuple&&) = default; template<typename... _UElements, typename = typename - enable_if<__and_<integral_constant<bool, sizeof...(_UElements) - == sizeof...(_Elements)>, - __all_convertible<__conv_types<const _UElements&...>, - __conv_types<_Elements...>> - >::value>::type> + enable_if<__and_<is_convertible<const _UElements&, + _Elements>...>::value>::type> constexpr tuple(const tuple<_UElements...>& __in) : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) { } template<typename... _UElements, typename = typename - enable_if<__and_<integral_constant<bool, sizeof...(_UElements) - == sizeof...(_Elements)>, - __all_convertible<__conv_types<_UElements...>, - __conv_types<_Elements...>> - >::value>::type> + enable_if<__and_<is_convertible<_UElements, + _Elements>...>::value>::type> constexpr tuple(tuple<_UElements...>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index a0208590bb5..46e3f800cab 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -745,6 +745,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Implementation for non-reference types. To meet the proper // variable definition semantics, we also need to test for // is_destructible in this case. + // This form should be simplified by a single expression: + // ::delete ::new _Tp(declval<_Arg>()), see c++/51222. struct __do_is_direct_constructible_impl { template<typename _Tp, typename _Arg, typename @@ -778,9 +780,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct remove_reference; template<typename _From, typename _To, bool - = is_reference<_From>::value> + = __not_<__or_<is_void<_From>, + is_function<_From>>>::value> struct __is_base_to_derived_ref; + // Detect whether we have a downcast situation during + // reference binding. template<typename _From, typename _To> struct __is_base_to_derived_ref<_From, _To, true> { @@ -803,6 +808,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_rvalue_reference<_To>>::value> struct __is_lvalue_to_rvalue_ref; + // Detect whether we have an lvalue of non-function type + // bound to a reference-compatible rvalue-reference. template<typename _From, typename _To> struct __is_lvalue_to_rvalue_ref<_From, _To, true> { @@ -810,8 +817,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _From>::type>::type __src_t; typedef typename remove_cv<typename remove_reference< _To>::type>::type __dst_t; - typedef __or_<is_same<__src_t, __dst_t>, - is_base_of<__dst_t, __src_t>> type; + typedef __and_<__not_<is_function<__src_t>>, + __or_<is_same<__src_t, __dst_t>, + is_base_of<__dst_t, __src_t>>> type; static constexpr bool value = type::value; }; @@ -823,9 +831,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Here we handle direct-initialization to a reference type as // equivalent to a static_cast modulo overshooting conversions. // These are restricted to the following conversions: - // a) A glvalue of a base class to a derived class reference + // a) A base class value to a derived class reference // b) An lvalue to an rvalue-reference of reference-compatible - // types + // types that are not functions template<typename _Tp, typename _Arg> struct __is_direct_constructible_ref_cast : public __and_<__is_static_castable<_Arg, _Tp>, @@ -850,7 +858,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Since default-construction and binary direct-initialization have // been handled separately, the implementation of the remaining - // n-ary construction cases is rather straightforward. + // n-ary construction cases is rather straightforward. We can use + // here a functional cast, because array types are excluded anyway + // and this form is never interpreted as a C cast. struct __do_is_nary_constructible_impl { template<typename _Tp, typename... _Args, typename diff --git a/libstdc++-v3/include/std/typeindex b/libstdc++-v3/include/std/typeindex index a92c2969b97..fa07ac620e6 100644 --- a/libstdc++-v3/include/std/typeindex +++ b/libstdc++-v3/include/std/typeindex @@ -76,7 +76,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !_M_target->before(*__rhs._M_target); } size_t - hash_code() const + hash_code() const noexcept { return _M_target->hash_code(); } const char* @@ -97,7 +97,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef type_index argument_type; size_t - operator()(const type_index& __ti) const + operator()(const type_index& __ti) const noexcept { return __ti.hash_code(); } }; diff --git a/libstdc++-v3/include/tr1/functional b/libstdc++-v3/include/tr1/functional index 7651326955a..ff2bd2a7134 100644 --- a/libstdc++-v3/include/tr1/functional +++ b/libstdc++-v3/include/tr1/functional @@ -43,9 +43,20 @@ #include <tr1/functional_hash.h> #include <ext/type_traits.h> #include <bits/move.h> // for std::__addressof +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# include <type_traits> // for integral_constant, true_type, false_type +#endif namespace std _GLIBCXX_VISIBILITY(default) { +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template<int> struct _Placeholder; + template<typename> class _Bind; + template<typename, typename> class _Bind_result; +_GLIBCXX_END_NAMESPACE_VERSION +#endif + namespace tr1 { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -847,16 +858,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION - /** @namespace std::placeholders - * @brief ISO C++ 0x entities sub namespace for functional. - * - * Define a large number of placeholders. There is no way to - * simplify this with variadic templates, because we're introducing - * unique names for each. + /** @namespace std::tr1::placeholders + * @brief Sub-namespace for tr1/functional. */ namespace placeholders { _GLIBCXX_BEGIN_NAMESPACE_VERSION + /* Define a large number of placeholders. There is no way to + * simplify this with variadic templates, because we're introducing + * unique names for each. + */ namespace { _Placeholder<1> _1; @@ -904,6 +915,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<int _Num> const int is_placeholder<_Placeholder<_Num> >::value; +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<int _Num> + struct is_placeholder<std::_Placeholder<_Num>> + : std::integral_constant<int, _Num> + { }; + + template<int _Num> + struct is_placeholder<const std::_Placeholder<_Num>> + : std::integral_constant<int, _Num> + { }; +#endif + /** * Stores a tuple of indices. Used by bind() to extract the elements * in a tuple. @@ -1347,6 +1370,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Signature> const bool is_bind_expression<_Bind<_Signature> >::value; + /// Class template _Bind is always a bind expression. + template<typename _Signature> + struct is_bind_expression<const _Bind<_Signature> > + { static const bool value = true; }; + + template<typename _Signature> + const bool is_bind_expression<const _Bind<_Signature> >::value; + + /// Class template _Bind is always a bind expression. + template<typename _Signature> + struct is_bind_expression<volatile _Bind<_Signature> > + { static const bool value = true; }; + + template<typename _Signature> + const bool is_bind_expression<volatile _Bind<_Signature> >::value; + + /// Class template _Bind is always a bind expression. + template<typename _Signature> + struct is_bind_expression<const volatile _Bind<_Signature> > + { static const bool value = true; }; + + template<typename _Signature> + const bool is_bind_expression<const volatile _Bind<_Signature> >::value; + /// Class template _Bind_result is always a bind expression. template<typename _Result, typename _Signature> struct is_bind_expression<_Bind_result<_Result, _Signature> > @@ -1355,6 +1402,70 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Result, typename _Signature> const bool is_bind_expression<_Bind_result<_Result, _Signature> >::value; + /// Class template _Bind_result is always a bind expression. + template<typename _Result, typename _Signature> + struct is_bind_expression<const _Bind_result<_Result, _Signature> > + { static const bool value = true; }; + + template<typename _Result, typename _Signature> + const bool + is_bind_expression<const _Bind_result<_Result, _Signature> >::value; + + /// Class template _Bind_result is always a bind expression. + template<typename _Result, typename _Signature> + struct is_bind_expression<volatile _Bind_result<_Result, _Signature> > + { static const bool value = true; }; + + template<typename _Result, typename _Signature> + const bool + is_bind_expression<volatile _Bind_result<_Result, _Signature> >::value; + + /// Class template _Bind_result is always a bind expression. + template<typename _Result, typename _Signature> + struct + is_bind_expression<const volatile _Bind_result<_Result, _Signature> > + { static const bool value = true; }; + + template<typename _Result, typename _Signature> + const bool + is_bind_expression<const volatile _Bind_result<_Result, + _Signature> >::value; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Signature> + struct is_bind_expression<std::_Bind<_Signature>> + : true_type { }; + + template<typename _Signature> + struct is_bind_expression<const std::_Bind<_Signature>> + : true_type { }; + + template<typename _Signature> + struct is_bind_expression<volatile std::_Bind<_Signature>> + : true_type { }; + + template<typename _Signature> + struct is_bind_expression<const volatile std::_Bind<_Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<std::_Bind_result<_Result, _Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<const std::_Bind_result<_Result, _Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<volatile std::_Bind_result<_Result, _Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<const volatile std::_Bind_result<_Result, + _Signature>> + : true_type { }; +#endif + /// bind template<typename _Functor, typename... _ArgTypes> inline @@ -2147,6 +2258,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<typename> struct is_placeholder; + + template<int _Num> + struct is_placeholder<tr1::_Placeholder<_Num>> + : integral_constant<int, _Num> + { }; + + template<int _Num> + struct is_placeholder<const tr1::_Placeholder<_Num>> + : integral_constant<int, _Num> + { }; + + template<typename> struct is_bind_expression; + + template<typename _Signature> + struct is_bind_expression<tr1::_Bind<_Signature>> + : true_type { }; + + template<typename _Signature> + struct is_bind_expression<const tr1::_Bind<_Signature>> + : true_type { }; + + template<typename _Signature> + struct is_bind_expression<volatile tr1::_Bind<_Signature>> + : true_type { }; + + template<typename _Signature> + struct is_bind_expression<const volatile tr1::_Bind<_Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<tr1::_Bind_result<_Result, _Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<const tr1::_Bind_result<_Result, _Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<volatile tr1::_Bind_result<_Result, _Signature>> + : true_type { }; + + template<typename _Result, typename _Signature> + struct is_bind_expression<const volatile tr1::_Bind_result<_Result, + _Signature>> + : true_type { }; + +_GLIBCXX_END_NAMESPACE_VERSION +#endif } #endif // _GLIBCXX_TR1_FUNCTIONAL diff --git a/libstdc++-v3/include/tr1/hashtable.h b/libstdc++-v3/include/tr1/hashtable.h index 5d1e02c2592..5e17b238a1f 100644 --- a/libstdc++-v3/include/tr1/hashtable.h +++ b/libstdc++-v3/include/tr1/hashtable.h @@ -813,7 +813,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Find the node whose key compares equal to k, beginning the search - // at p (usually the head of a bucket). Return nil if no node is found. + // at p (usually the head of a bucket). Return zero if no node is found. template<typename _Key, typename _Value, typename _Allocator, typename _ExtractKey, typename _Equal, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, @@ -829,7 +829,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for (; __p; __p = __p->_M_next) if (this->_M_compare(__k, __code, __p)) return __p; - return false; + return 0; } // Insert v in bucket n (assumes no element with its key already present). diff --git a/libstdc++-v3/include/tr1/poly_hermite.tcc b/libstdc++-v3/include/tr1/poly_hermite.tcc index e86b3777c74..95e8079d543 100644 --- a/libstdc++-v3/include/tr1/poly_hermite.tcc +++ b/libstdc++-v3/include/tr1/poly_hermite.tcc @@ -1,6 +1,6 @@ // Special functions -*- C++ -*- -// Copyright (C) 2006, 2007, 2008, 2009, 2010 +// Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -84,7 +84,7 @@ namespace tr1 unsigned int __i; for (__H_nm2 = __H_0, __H_nm1 = __H_1, __i = 2; __i <= __n; ++__i) { - __H_n = 2 * (__x * __H_nm1 + (__i - 1) * __H_nm2); + __H_n = 2 * (__x * __H_nm1 - (__i - 1) * __H_nm2); __H_nm2 = __H_nm1; __H_nm1 = __H_n; } diff --git a/libstdc++-v3/libsupc++/eh_tm.cc b/libstdc++-v3/libsupc++/eh_tm.cc index f5815a180df..a64610283ff 100644 --- a/libstdc++-v3/libsupc++/eh_tm.cc +++ b/libstdc++-v3/libsupc++/eh_tm.cc @@ -45,7 +45,9 @@ free_any_cxa_exception (_Unwind_Exception *eo) __cxa_free_dependent_exception (dep); } +#ifdef _GLIBCXX_ATOMIC_BUILTINS_4 if (__sync_sub_and_fetch (&h->referenceCount, 1) == 0) +#endif __cxa_free_exception (h + 1); } diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo index 69311d69e9a..22ef49fa7b2 100644 --- a/libstdc++-v3/libsupc++/typeinfo +++ b/libstdc++-v3/libsupc++/typeinfo @@ -140,7 +140,7 @@ namespace std { return !operator==(__arg); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ - size_t hash_code() const throw() + size_t hash_code() const noexcept { # if !__GXX_MERGED_TYPEINFO_NAMES return _Hash_bytes(name(), __builtin_strlen(name()), diff --git a/libstdc++-v3/scripts/run_doxygen b/libstdc++-v3/scripts/run_doxygen index 7b601bce0a8..af2d0fc3809 100644 --- a/libstdc++-v3/scripts/run_doxygen +++ b/libstdc++-v3/scripts/run_doxygen @@ -267,8 +267,8 @@ done rm stdheader # Some of the pages for generated modules have text that confuses certain -# implementations of man(1), e.g., Linux's. We need to have another top-level -# *roff tag to /stop/ the .SH NAME entry. +# implementations of man(1), e.g. on GNU/Linux. We need to have another +# top-level *roff tag to /stop/ the .SH NAME entry. problematic=`egrep --files-without-match '^\.SH SYNOPSIS' [A-Z]*.3` #problematic='Containers.3 Sequences.3 Assoc_containers.3 Iterator_types.3' diff --git a/libstdc++-v3/src/compatibility-ldbl.cc b/libstdc++-v3/src/compatibility-ldbl.cc index a9bdb8b0986..a103856adfa 100644 --- a/libstdc++-v3/src/compatibility-ldbl.cc +++ b/libstdc++-v3/src/compatibility-ldbl.cc @@ -1,6 +1,6 @@ // Compatibility symbols for -mlong-double-64 compatibility -*- C++ -*- -// Copyright (C) 2006, 2008, 2009, 2010 +// Copyright (C) 2006, 2008, 2009, 2010, 2011 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -69,14 +69,7 @@ namespace std _GLIBCXX_VISIBILITY(default) // For std::tr1::hash<long double>::operator() #define _GLIBCXX_LONG_DOUBLE_COMPAT_IMPL - -namespace std _GLIBCXX_VISIBILITY(default) -{ - namespace tr1 - { -#include "hash-long-double-aux.cc" - } -} +#include "hash-long-double-tr1-aux.cc" // std::tr1::hash<long double>::operator() // and std::hash<long double>::operator() diff --git a/libstdc++-v3/src/hash-long-double-aux.cc b/libstdc++-v3/src/hash-long-double-aux.cc deleted file mode 100644 index d54d635f83e..00000000000 --- a/libstdc++-v3/src/hash-long-double-aux.cc +++ /dev/null @@ -1,50 +0,0 @@ -// std::hash and std::tr1::hash definitions, long double bits -*- C++ -*- - -// Copyright (C) 2010 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. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - - // For long double, careful with random padding bits (e.g., on x86, - // 10 bytes -> 12 bytes) and resort to frexp. - template<> - size_t - hash<long double>::operator()(long double __val) const - { - // 0 and -0 both hash to zero. - if (__val == 0.0L) - return 0; - - int __exponent; - __val = __builtin_frexpl(__val, &__exponent); - __val = __val < 0.0l ? -(__val + 0.5l) : __val; - - const long double __mult = __SIZE_MAX__ + 1.0l; - __val *= __mult; - - // Try to use all the bits of the mantissa (really necessary only - // on 32-bit targets, at least for 80-bit floating point formats). - const size_t __hibits = (size_t)__val; - __val = (__val - (long double)__hibits) * __mult; - - const size_t __coeff = __SIZE_MAX__ / __LDBL_MAX_EXP__; - - return __hibits + (size_t)__val + __coeff * __exponent; - } diff --git a/libstdc++-v3/src/hash-long-double-tr1-aux.cc b/libstdc++-v3/src/hash-long-double-tr1-aux.cc new file mode 100644 index 00000000000..70ed45bbfbe --- /dev/null +++ b/libstdc++-v3/src/hash-long-double-tr1-aux.cc @@ -0,0 +1,56 @@ +// std::tr1::hash definitions, long double bits -*- C++ -*- + +// Copyright (C) 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 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +namespace std _GLIBCXX_VISIBILITY(default) +{ + namespace tr1 + { + // For long double, careful with random padding bits (e.g., on x86, + // 10 bytes -> 12 bytes) and resort to frexp. + template<> + size_t + hash<long double>::operator()(long double __val) const + { + // 0 and -0 both hash to zero. + if (__val == 0.0L) + return 0; + + int __exponent; + __val = __builtin_frexpl(__val, &__exponent); + __val = __val < 0.0l ? -(__val + 0.5l) : __val; + + const long double __mult = __SIZE_MAX__ + 1.0l; + __val *= __mult; + + // Try to use all the bits of the mantissa (really necessary only + // on 32-bit targets, at least for 80-bit floating point formats). + const size_t __hibits = (size_t)__val; + __val = (__val - (long double)__hibits) * __mult; + + const size_t __coeff = __SIZE_MAX__ / __LDBL_MAX_EXP__; + + return __hibits + (size_t)__val + __coeff * __exponent; + } + } +} diff --git a/libstdc++-v3/src/hash_c++0x.cc b/libstdc++-v3/src/hash_c++0x.cc index 852498df602..d685074540b 100644 --- a/libstdc++-v3/src/hash_c++0x.cc +++ b/libstdc++-v3/src/hash_c++0x.cc @@ -1,6 +1,6 @@ // std::hash definitions -*- C++ -*- -// Copyright (C) 2010 Free Software Foundation, Inc. +// Copyright (C) 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 @@ -30,5 +30,27 @@ namespace std _GLIBCXX_VISIBILITY(default) { -#include "hash-long-double-aux.cc" + _GLIBCXX_PURE size_t + hash<long double>::operator()(long double __val) const noexcept + { + // 0 and -0 both hash to zero. + if (__val == 0.0L) + return 0; + + int __exponent; + __val = __builtin_frexpl(__val, &__exponent); + __val = __val < 0.0l ? -(__val + 0.5l) : __val; + + const long double __mult = __SIZE_MAX__ + 1.0l; + __val *= __mult; + + // Try to use all the bits of the mantissa (really necessary only + // on 32-bit targets, at least for 80-bit floating point formats). + const size_t __hibits = (size_t)__val; + __val = (__val - (long double)__hibits) * __mult; + + const size_t __coeff = __SIZE_MAX__ / __LDBL_MAX_EXP__; + + return __hibits + (size_t)__val + __coeff * __exponent; + } } diff --git a/libstdc++-v3/src/hash_tr1.cc b/libstdc++-v3/src/hash_tr1.cc index e707e827a11..a5ac87e585b 100644 --- a/libstdc++-v3/src/hash_tr1.cc +++ b/libstdc++-v3/src/hash_tr1.cc @@ -1,6 +1,6 @@ // std::tr1::hash definitions -*- 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 @@ -25,12 +25,12 @@ #include <string> #include <tr1/functional> +#include "hash-long-double-tr1-aux.cc" + namespace std _GLIBCXX_VISIBILITY(default) { namespace tr1 { -#include "hash-long-double-aux.cc" - #ifndef _GLIBCXX_LONG_DOUBLE_COMPAT_IMPL template<> size_t diff --git a/libstdc++-v3/testsuite/20_util/bind/cv_quals_3.cc b/libstdc++-v3/testsuite/20_util/bind/cv_quals_3.cc new file mode 100644 index 00000000000..6affa1168e2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bind/cv_quals_3.cc @@ -0,0 +1,65 @@ +// 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/>. + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <functional> + +struct X +{ + int operator()() const { return 0; } + int operator()() volatile { return 1; } + int operator()() const volatile { return 2; } + void operator()() { }; +}; + +void test01() +{ + static_assert( std::is_placeholder<decltype(std::placeholders::_1)>::value, + "decltype(_1) is a placeholder type" ); + + const auto b0 = std::bind(X()); + static_assert( std::is_bind_expression<decltype(b0)>::value, + "const-qualified wrapper is a bind expression" ); + + volatile auto b1 = std::bind(X()); + static_assert( std::is_bind_expression<decltype(b1)>::value, + "volatile-qualified wrapper is a bind expression" ); + + const volatile auto b2 = std::bind(X()); + static_assert( std::is_bind_expression<decltype(b2)>::value, + "const-volatile-qualified wrapper is a bind expression" ); + + const auto b3 = std::bind<int>(X()); + static_assert( std::is_bind_expression<decltype(b3)>::value, + "const-qualified wrapper is a bind expression" ); + + volatile auto b4 = std::bind<int>(X()); + static_assert( std::is_bind_expression<decltype(b4)>::value, + "volatile-qualified wrapper is a bind expression" ); + + const volatile auto b5 = std::bind<int>(X()); + static_assert( std::is_bind_expression<decltype(b5)>::value, + "const-volatile-qualified wrapper is a bind expression" ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc index f5a08c2630a..fa2123114d5 100644 --- a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc +++ b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc @@ -29,8 +29,12 @@ int inc(int& i) { return ++i; } void test01() { const int dummy = 0; - std::bind(&inc, _1)(0); // { dg-error "no match|rvalue" } - std::bind(&inc, std::ref(dummy))(); // { dg-error "no match|const" } + std::bind(&inc, _1)(0); // { dg-error "no match" } + // { dg-error "rvalue|const" "" { target *-*-* } 1206 } + // { dg-error "rvalue|const" "" { target *-*-* } 1219 } + // { dg-error "rvalue|const" "" { target *-*-* } 1233 } + // { dg-error "rvalue|const" "" { target *-*-* } 1247 } + std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" } } struct Inc diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc index 1f4065b92a8..33ab45b4bbc 100644 --- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc @@ -19,7 +19,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// { dg-error "static assertion failed" "" { target *-*-* } 1759 } +// { dg-error "static assertion failed" "" { target *-*-* } 1769 } #include <utility> diff --git a/libstdc++-v3/testsuite/20_util/is_constructible/51185.cc b/libstdc++-v3/testsuite/20_util/is_constructible/51185.cc new file mode 100644 index 00000000000..faf3969fe83 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_constructible/51185.cc @@ -0,0 +1,39 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// 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 <type_traits> + +struct A { }; +struct B : A { }; + +// libstdc++/51185 +void f() +{ + static_assert(!std::is_constructible<B &&, A>(), ""); + static_assert(!std::is_constructible<B const &&, A>(), ""); + static_assert(!std::is_constructible<B const &&, A const>(), ""); + static_assert(!std::is_constructible<B volatile &&, A>(), ""); + static_assert(!std::is_constructible<B volatile &&, A volatile>(), ""); + static_assert(!std::is_constructible<B const volatile &&, A>(), ""); + static_assert(!std::is_constructible<B const volatile &&, A const>(), ""); + static_assert(!std::is_constructible<B const volatile &&, A volatile>(), ""); + static_assert(!std::is_constructible<B const volatile &&, + A const volatile>(), ""); +} diff --git a/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc b/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc index 24fde938988..06895e32bb0 100644 --- a/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc +++ b/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc @@ -817,3 +817,5 @@ static_assert(!std::is_constructible<const int&, ExplicitTo<double&&>>::value, "Error"); static_assert(!std::is_constructible<int&&, ExplicitTo<double&&>>::value, "Error"); + +static_assert(std::is_constructible<void(&&)(), void(&)()>::value, "Error"); diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc index d61daf35853..b8bd23f841f 100644 --- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1545 } -// { dg-error "declaration of" "" { target *-*-* } 1509 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1555 } +// { dg-error "declaration of" "" { target *-*-* } 1519 } diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc index ee74be9f267..96940119ed9 100644 --- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1463 } -// { dg-error "declaration of" "" { target *-*-* } 1427 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1473 } +// { dg-error "declaration of" "" { target *-*-* } 1437 } diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc index ad998356c83..73a0d0f7029 100644 --- a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc +++ b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc @@ -44,4 +44,4 @@ void test01() tuple<Type> t(allocator_arg, a, 1); } -// { dg-error "no matching function" "" { target *-*-* } 141 } +// { dg-error "no matching function" "" { target *-*-* } 112 } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc index 13cc4e5d196..2d1b4ca86a0 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc @@ -31,6 +31,7 @@ class tstring : public std::basic_string<char> public: tstring() : std::basic_string<char>() {} tstring(tstring&& s) : std::basic_string<char>(std::move(s)) {} + tstring& operator=(tstring&& s) = default; }; void test01() diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc index e0b8b24a0cb..42026c90bd8 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc @@ -31,6 +31,7 @@ class twstring : public std::basic_string<wchar_t> public: twstring() : std::basic_string<wchar_t>() {} twstring(twstring&& s) : std::basic_string<wchar_t>(std::move(s)) {} + twstring& operator=(twstring&&) = default; }; void test01() diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc new file mode 100644 index 00000000000..14ab8e71275 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc @@ -0,0 +1,36 @@ +// { dg-do compile } +// { dg-require-normal-mode "" } +// { 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> + +int main() +{ + // bitset base type + typedef std::_Base_bitset<6> bitset_base; + constexpr bitset_base base = bitset_base(); + + constexpr auto r1 __attribute__((unused)) = base._M_getword(2); + // constexpr auto r2 = base._M_getdata(); // error, pointer to this + auto r2 __attribute__((unused)) = base._M_getdata(); + constexpr auto r3 __attribute__((unused)) = base._M_hiword(); + + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc index fc171c8238f..384f01a5dff 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc @@ -22,15 +22,6 @@ int main() { - // bitset base type - typedef std::_Base_bitset<6> bitset_base; - constexpr bitset_base base = bitset_base(); - - constexpr auto r1 __attribute__((unused)) = base._M_getword(2); - // constexpr auto r2 = base._M_getdata(); // error, pointer to this - auto r2 __attribute__((unused)) = base._M_getdata(); - constexpr auto r3 __attribute__((unused)) = base._M_hiword(); - // bitset operators typedef std::bitset<6> bitset_type; constexpr bitset_type a = bitset_type(); diff --git a/libstdc++-v3/testsuite/23_containers/map/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/map/modifiers/erase/51142.cc new file mode 100644 index 00000000000..f50b7b7e9fd --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/map/modifiers/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <map> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator<(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::map<X, int>& s, X x) +{ + std::map<X, int>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/multimap/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/multimap/modifiers/erase/51142.cc new file mode 100644 index 00000000000..ee687f77cf6 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/multimap/modifiers/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <map> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator<(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::multimap<X, int>& s, X x) +{ + std::multimap<X, int>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/multiset/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/multiset/modifiers/erase/51142.cc new file mode 100644 index 00000000000..c5beb6a8dd5 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/multiset/modifiers/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <set> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator<(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::multiset<X>& s, X x) +{ + std::multiset<X>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/set/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/set/modifiers/erase/51142.cc new file mode 100644 index 00000000000..4fb296a95fc --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/set/modifiers/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <set> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator<(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::set<X>& s, X x) +{ + std::set<X>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc new file mode 100644 index 00000000000..eab637df235 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <unordered_map> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator==(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::unordered_map<X, int>& s, X x) +{ + std::unordered_map<X, int>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc new file mode 100644 index 00000000000..678aa5dd989 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <unordered_map> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator==(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::unordered_multimap<X, int>& s, X x) +{ + std::unordered_multimap<X, int>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/copy.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/copy.cc new file mode 100644 index 00000000000..7e50c302d11 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/copy.cc @@ -0,0 +1,45 @@ +// { 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/>. + + +// NOTE: This makes use of the fact that we know how moveable +// is implemented on set (via swap). If the implementation changed +// this test may begin to fail. + +#include <unordered_set> +#include <utility> +#include <testsuite_hooks.h> + +int main() +{ + bool test __attribute__((unused)) = true; + + const int nb = 10000; + std::unordered_multiset<int> ref; + for (int i = 0; i != nb; ++i) + { + ref.insert(i); + ref.insert(i); + } + + std::unordered_multiset<int> copy(ref); + VERIFY( copy.size() == ref.size() ); + VERIFY( std::equal(ref.begin(), ref.end(), copy.begin()) ); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc index 327dc4bd0b2..e48e31149e3 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc @@ -23,6 +23,18 @@ #include <string> #include <testsuite_hooks.h> +namespace +{ + std::size_t + get_nb_bucket_elems(const std::unordered_multiset<std::string>& us) + { + std::size_t nb = 0; + for (std::size_t b = 0; b != us.bucket_count(); ++b) + nb += us.bucket_size(b); + return nb; + } +} + void test01() { bool test __attribute__((unused)) = true; @@ -45,14 +57,17 @@ void test01() ms1.insert("one line behind"); ms1.insert("because to why"); VERIFY( ms1.size() == 11 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( ms1.erase("eeilo") == 1 ); VERIFY( ms1.size() == 10 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); iterator it1 = ms1.find("eeilo"); VERIFY( it1 == ms1.end() ); VERIFY( ms1.erase("tillsammans") == 1 ); VERIFY( ms1.size() == 9 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); iterator it2 = ms1.find("tillsammans"); VERIFY( it2 == ms1.end() ); @@ -61,17 +76,20 @@ void test01() VERIFY( it3 != ms1.end() ); VERIFY( ms1.erase(*it3) == 1 ); VERIFY( ms1.size() == 8 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); it3 = ms1.find("belonging (no longer mix)"); VERIFY( it3 == ms1.end() ); VERIFY( !ms1.erase("abra") ); VERIFY( ms1.size() == 8 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( !ms1.erase("eeilo") ); VERIFY( ms1.size() == 8 ); VERIFY( ms1.erase("because to why") == 2 ); VERIFY( ms1.size() == 6 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); iterator it4 = ms1.find("because to why"); VERIFY( it4 == ms1.end() ); @@ -87,11 +105,13 @@ void test01() VERIFY( ms1.erase(*it5) == 1 ); VERIFY( ms1.size() == 5 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); it5 = ms1.find("umbra/penumbra"); VERIFY( it5 == ms1.end() ); VERIFY( ms1.erase(*it6) == 1 ); VERIFY( ms1.size() == 4 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); it6 = ms1.find("one line behind"); VERIFY( it6 == ms1.end() ); @@ -103,6 +123,7 @@ void test01() VERIFY( ms1.erase(*it8) == 1 ); VERIFY( ms1.size() == 3 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( ++it7 == it9 ); iterator it10 = it9; @@ -110,15 +131,18 @@ void test01() iterator it11 = it10; VERIFY( ms1.erase(*it9) == 1 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( ms1.size() == 2 ); VERIFY( ++it10 == ms1.end() ); VERIFY( ms1.erase(ms1.begin()) != ms1.end() ); VERIFY( ms1.size() == 1 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( ms1.begin() == it11 ); VERIFY( ms1.erase(*ms1.begin()) == 1 ); VERIFY( ms1.size() == 0 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( ms1.begin() == ms1.end() ); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc index c5eea6eeebc..ba1659aedfd 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc @@ -23,6 +23,20 @@ #include <string> #include <testsuite_hooks.h> +namespace +{ + std::size_t + get_nb_bucket_elems(const std::unordered_multiset<std::string>& us) + { + std::size_t nb = 0; + for (std::size_t b = 0; b != us.bucket_count(); ++b) + { + nb += us.bucket_size(b); + } + return nb; + } +} + // libstdc++/24061 void test01() { @@ -49,6 +63,7 @@ void test01() ms1.insert("love is not enough"); ms1.insert("every day is exactly the same"); VERIFY( ms1.size() == 13 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); iterator it1 = ms1.begin(); ++it1; @@ -56,6 +71,7 @@ void test01() ++it2; iterator it3 = ms1.erase(it1); VERIFY( ms1.size() == 12 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( it3 == it2 ); VERIFY( *it3 == *it2 ); @@ -68,6 +84,7 @@ void test01() ++it5; iterator it6 = ms1.erase(it4, it5); VERIFY( ms1.size() == 10 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( it6 == it5 ); VERIFY( *it6 == *it5 ); @@ -79,6 +96,7 @@ void test01() ++it8; const_iterator it9 = ms1.erase(it7); VERIFY( ms1.size() == 9 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( it9 == it8 ); VERIFY( *it9 == *it8 ); @@ -91,11 +109,13 @@ void test01() ++it11; const_iterator it12 = ms1.erase(it10, it11); VERIFY( ms1.size() == 5 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( it12 == it11 ); VERIFY( *it12 == *it11 ); iterator it13 = ms1.erase(ms1.begin(), ms1.end()); VERIFY( ms1.size() == 0 ); + VERIFY( get_nb_bucket_elems(ms1) == ms1.size() ); VERIFY( it13 == ms1.end() ); VERIFY( it13 == ms1.begin() ); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc new file mode 100644 index 00000000000..4db6af0fa25 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <unordered_set> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator==(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::unordered_multiset<X>& s, X x) +{ + std::unordered_multiset<X>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc index 571346fd5c2..59cd8c9857b 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc @@ -25,6 +25,19 @@ #include <unordered_set> #include <testsuite_hooks.h> +namespace +{ + template <typename _Tp> + std::size_t + get_nb_bucket_elems(const std::unordered_multiset<_Tp>& us) + { + std::size_t nb = 0; + for (std::size_t b = 0; b != us.bucket_count(); ++b) + nb += us.bucket_size(b); + return nb; + } +} + void test01() { bool test __attribute__((unused)) = true; @@ -38,8 +51,9 @@ void test01() "magenta", "yellow", "orange", "pink", "gray" }; s.insert(A+0, A+N); - VERIFY(s.size() == static_cast<unsigned int>(N)); - VERIFY(std::distance(s.begin(), s.end()) == N); + VERIFY( s.size() == static_cast<unsigned int>(N) ); + VERIFY( std::distance(s.begin(), s.end()) == N ); + VERIFY( get_nb_bucket_elems(s) == N ); for (int i = 0; i < N; ++i) { std::string str = A[i]; @@ -62,6 +76,7 @@ void test02() s.insert(A+0, A+N); VERIFY(s.size() == static_cast<unsigned int>(N)); VERIFY(std::distance(s.begin(), s.end()) == N); + VERIFY( get_nb_bucket_elems(s) == N ); VERIFY(std::count(s.begin(), s.end(), 2) == 1); VERIFY(std::count(s.begin(), s.end(), 3) == 1); diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc index f275e9a9bdd..ebc38b2402a 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc @@ -24,6 +24,19 @@ #include <unordered_set> #include <testsuite_hooks.h> +namespace +{ + std::size_t + get_nb_bucket_elems(const std::unordered_multiset<std::string>& us) + { + std::size_t nb = 0; + for (std::size_t b = 0; b != us.bucket_count(); ++b) + nb += us.bucket_size(b); + return nb; + } +} + + void test01() { bool test __attribute__((unused)) = true; @@ -33,7 +46,8 @@ void test01() VERIFY(s.empty()); Set::iterator i = s.insert("abcde"); - VERIFY(s.size() == 1); + VERIFY( s.size() == 1 ); + VERIFY( get_nb_bucket_elems(s) == 1 ); VERIFY(std::distance(s.begin(), s.end()) == 1); VERIFY(i == s.begin()); VERIFY(*i == "abcde"); @@ -50,6 +64,7 @@ void test02() s.insert("abcde"); Set::iterator i = s.insert("abcde"); VERIFY(s.size() == 2); + VERIFY( get_nb_bucket_elems(s) == 2 ); VERIFY(std::distance(s.begin(), s.end()) == 2); VERIFY(*i == "abcde"); diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc index 14b8e16817a..4dc9fba5b68 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc @@ -26,6 +26,19 @@ #include <testsuite_hooks.h> #include <testsuite_rvalref.h> +namespace +{ + template <typename _Tp> + std::size_t + get_nb_bucket_elems(const std::unordered_multiset<_Tp>& us) + { + std::size_t nb = 0; + for (std::size_t b = 0; b != us.bucket_count(); ++b) + nb += us.bucket_size(b); + return nb; + } +} + void test01() { bool test __attribute__((unused)) = true; @@ -37,6 +50,7 @@ void test01() Set::iterator i = s.insert(rvalstruct(1)); VERIFY( s.size() == 1 ); + VERIFY( get_nb_bucket_elems(s) == 1 ); VERIFY( std::distance(s.begin(), s.end()) == 1 ); VERIFY( i == s.begin() ); VERIFY( (*i).val == 1 ); @@ -54,6 +68,7 @@ void test02() s.insert(rvalstruct(2)); Set::iterator i = s.insert(rvalstruct(2)); VERIFY( s.size() == 2 ); + VERIFY( get_nb_bucket_elems(s) == 2 ); VERIFY( std::distance(s.begin(), s.end()) == 2 ); VERIFY( (*i).val == 2 ); diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc new file mode 100644 index 00000000000..14864604289 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc @@ -0,0 +1,38 @@ +// 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/>. +// + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <unordered_set> + +struct X +{ + template<typename T> + X(T&) {} +}; + +bool operator==(const X&, const X&) { return false; } + +// LWG 2059. +void erasor(std::unordered_set<X>& s, X x) +{ + std::unordered_set<X>::iterator it = s.find(x); + if (it != s.end()) + s.erase(it); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/rehash.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/rehash.cc new file mode 100644 index 00000000000..91dc0fd402e --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/rehash.cc @@ -0,0 +1,62 @@ +// 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/>. +// +// { dg-options "-std=gnu++0x" } + +#include <unordered_set> +#include <testsuite_hooks.h> + +void test01() +{ + bool test __attribute__((unused)) = true; + std::unordered_set<int> us; + typedef typename std::unordered_set<int>::size_type size_type; + bool rehashed = false; + for (int i = 0; i != 100000; ++i) + { + size_type bkt_count = us.bucket_count(); + us.insert(i); + if (bkt_count != us.bucket_count()) + { + // Container has been rehashed, lets check that it won't be rehash again + // if we remove and restore the last 2 inserted elements: + rehashed = true; + bkt_count = us.bucket_count(); + VERIFY( us.erase(i) == 1 ); + VERIFY( bkt_count == us.bucket_count() ); + if (i > 0) + { + VERIFY( us.erase(i - 1) == 1 ); + VERIFY( bkt_count == us.bucket_count() ); + + VERIFY( us.insert(i - 1).second ); + VERIFY( bkt_count == us.bucket_count() ); + } + VERIFY( us.insert(i).second ); + VERIFY( bkt_count == us.bucket_count() ); + } + } + + // At lest we check a rehash once: + VERIFY( rehashed ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc new file mode 100644 index 00000000000..aa52e6b07d4 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc @@ -0,0 +1,41 @@ +// { dg-do compile } +// { dg-options "-std=gnu++0x" } +// { dg-require-normal-mode "" } + +// 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 Pred 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/>. + +// { dg-error "static assertion failed" "" { target *-*-* } 177 } + +#include <unordered_set> + +namespace +{ + struct hash_without_noexcept + { + std::size_t operator() (int) const + { return 0; } + }; +} + +void +test01() +{ + std::__unordered_set<int, hash_without_noexcept, + std::equal_to<int>, std::allocator<int>, + false> us; +} diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/char/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/char/51288.cc new file mode 100644 index 00000000000..281a2e2d39c --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/char/51288.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-namedlocale "en_US.UTF-8" } + +// 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 <sstream> +#include <iomanip> +#include <testsuite_hooks.h> + +// libstdc++/51288 +void test01() +{ + bool test __attribute__((unused)) = true; + + std::locale loc_us = std::locale("en_US.UTF-8"); + + std::istringstream iss; + iss.imbue(loc_us); + + iss.str(" $1.23"); + + std::string str; + iss >> std::get_money(str); + + VERIFY( str == "123" ); + VERIFY( iss.eof() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc new file mode 100644 index 00000000000..2ec02302c31 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-namedlocale "en_US.UTF-8" } + +// 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 <sstream> +#include <iomanip> +#include <testsuite_hooks.h> + +// libstdc++/51288 +void test01() +{ + bool test __attribute__((unused)) = true; + + std::locale loc_us = std::locale("en_US.UTF-8"); + + std::wistringstream iss; + iss.imbue(loc_us); + + iss.str(L" $1.23"); + + std::wstring str; + iss >> std::get_money(str); + + VERIFY( str == L"123" ); + VERIFY( iss.eof() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/char/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/char/51288.cc new file mode 100644 index 00000000000..d2cc9cb7012 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/char/51288.cc @@ -0,0 +1,49 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-namedlocale "en_US.UTF-8" } + +// 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 <sstream> +#include <iomanip> +#include <testsuite_hooks.h> + +// libstdc++/51288 +void test01() +{ + bool test __attribute__((unused)) = true; + + std::locale loc_us = std::locale("en_US.UTF-8"); + + std::ostringstream oss; + oss.imbue(loc_us); + + const std::string str("123"); + + oss.setstate(std::ios_base::failbit); + + oss << std::put_money(str); + + VERIFY( oss.str().empty() ); + VERIFY( oss.fail() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc new file mode 100644 index 00000000000..548c0a7c2b4 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc @@ -0,0 +1,49 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-namedlocale "en_US.UTF-8" } + +// 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 <sstream> +#include <iomanip> +#include <testsuite_hooks.h> + +// libstdc++/51288 +void test01() +{ + bool test __attribute__((unused)) = true; + + std::locale loc_us = std::locale("en_US.UTF-8"); + + std::wostringstream oss; + oss.imbue(loc_us); + + const std::wstring str(L"123"); + + oss.setstate(std::ios_base::failbit); + + oss << std::put_money(str); + + VERIFY( oss.str().empty() ); + VERIFY( oss.fail() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc b/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc index a56d5852424..d35e6aaba35 100644 --- a/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc +++ b/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc @@ -1,12 +1,12 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x -fno-inline -save-temps" } +// { dg-options "-std=gnu++0x -fno-inline -save-temps -g0" } // { dg-require-cstdint "" } // { dg-require-gthreads "" } // { dg-require-atomic-builtins "" } // { dg-final { scan-assembler-not "_ZNSt6futureIvEC2Ev" } } // { dg-final { scan-assembler-not "_ZNSt6futureIiEC2Ev" } } -// Copyright (C) 2010 Free Software Foundation, Inc. +// Copyright (C) 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 diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc b/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc index 159077bc820..6f06ffeb647 100644 --- a/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc +++ b/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc @@ -1,12 +1,12 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x -fno-inline -save-temps" } +// { dg-options "-std=gnu++0x -fno-inline -save-temps -g0" } // { dg-require-cstdint "" } // { dg-require-gthreads "" } // { dg-require-atomic-builtins "" } // { dg-final { scan-assembler-not "_ZNSt13shared_futureIvEC2Ev" } } // { dg-final { scan-assembler-not "_ZNSt13shared_futureIiEC2Ev" } } -// Copyright (C) 2010 Free Software Foundation, Inc. +// Copyright (C) 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 diff --git a/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc index 602d40ff46a..049443543f2 100644 --- a/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc +++ b/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc @@ -1,7 +1,7 @@ -// { dg-do run { target *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } } -// { dg-options " -std=gnu++0x -pthread" { target *-*-linux* alpha*-*-osf* mips-sgi-irix6* } } +// { dg-do run { target *-*-linux* *-*-solaris* *-*-cygwin mips-sgi-irix6* } } +// { dg-options " -std=gnu++0x -pthread" { target *-*-linux* mips-sgi-irix6* } } // { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } } -// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } } +// { dg-options " -std=gnu++0x " { target *-*-cygwin } } // { dg-require-cstdint "" } // { dg-require-gthreads "" } diff --git a/libstdc++-v3/testsuite/performance/23_containers/copy_construct/unordered_set.cc b/libstdc++-v3/testsuite/performance/23_containers/copy_construct/unordered_set.cc new file mode 100644 index 00000000000..f214d1dd666 --- /dev/null +++ b/libstdc++-v3/testsuite/performance/23_containers/copy_construct/unordered_set.cc @@ -0,0 +1,43 @@ +// { 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 <unordered_set> +#include <testsuite_performance.h> + +int main() +{ + using namespace __gnu_test; + + time_counter time; + resource_counter resource; + + std::unordered_set<int> ref; + for (int i = 0; i != 500000; ++i) + ref.insert(i); + + start_counters(time, resource); + + for (unsigned i = 0; i < 500; ++i) + std::unordered_set<int> v(ref); + + stop_counters(time, resource); + report_performance(__FILE__, "unordered_set<int> copy", time, resource); + + return 0; +} diff --git a/libstdc++-v3/testsuite/tr1/3_function_objects/bind/cv_quals.cc b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/cv_quals.cc new file mode 100644 index 00000000000..5ea373647fc --- /dev/null +++ b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/cv_quals.cc @@ -0,0 +1,53 @@ +// 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/>. + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include <tr1/functional> + +struct X +{ + int operator()() const { return 0; } + int operator()() volatile { return 1; } + int operator()() const volatile { return 2; } + void operator()() { }; +}; + +void test01() +{ + static_assert( std::tr1::is_placeholder<__typeof(std::tr1::placeholders::_1)>::value, + "decltype(_1) is a placeholder type" ); + + const auto b0 = std::tr1::bind(X()); + static_assert( std::tr1::is_bind_expression<__typeof(b0)>::value, + "const-qualified wrapper is a bind expression" ); + + volatile auto b1 = std::tr1::bind(X()); + static_assert( std::tr1::is_bind_expression<__typeof(b1)>::value, + "volatile-qualified wrapper is a bind expression" ); + + const volatile auto b2 = std::tr1::bind(X()); + static_assert( std::tr1::is_bind_expression<__typeof(b2)>::value, + "const-volatile-qualified wrapper is a bind expression" ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/tr1/3_function_objects/bind/mixed.cc b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/mixed.cc new file mode 100644 index 00000000000..2d96bb7ec86 --- /dev/null +++ b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/mixed.cc @@ -0,0 +1,139 @@ +// { dg-options "-std=gnu++11" } +// 2011-11-20 Jonathan Wakely <jwakely.gcc -at- gmail.com> +// +// 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/>. + +// 3.6 function object binders +#include <tr1/functional> +#include <functional> +#include <testsuite_hooks.h> + +// std::tr1::bind and std::bind should work together + +namespace p1 = std::placeholders; +namespace p2 = std::tr1::placeholders; + +using std::multiplies; +using std::minus; + +void test01() +{ + static_assert( std::is_placeholder<decltype(p2::_2)>::value == 2, + "TR1 placeholder is a std placeholder" ); + static_assert( std::tr1::is_placeholder<decltype(p1::_1)>::value == 1, + "std placeholder is a TR2 placeholder" ); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + + auto b1 = std::bind(minus<int>(), 6, p2::_2); + auto b2 = std::tr1::bind(minus<int>(), 6, p1::_2); + + int five = 5; + int seven = 7; + + VERIFY( std::tr1::bind(multiplies<int>(), p1::_1, b1)(five, seven) == -5 ); + VERIFY( std::bind(multiplies<int>(), p2::_1, b2)(seven, five) == 7 ); + + VERIFY( std::tr1::bind<int>(multiplies<int>(), p1::_1, b1)(five, seven) == -5 ); + VERIFY( std::bind<int>(multiplies<int>(), p2::_1, b2)(seven, five) == 7 ); + + static_assert( std::is_bind_expression<decltype(b2)>::value, + "TR1 bind expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(b1)>::value, + "std bind expression is a TR2 bind expression" ); + + const auto c1 = b1; + const auto c2 = b2; + + static_assert( std::is_bind_expression<decltype(c2)>::value, + "const TR1 bind expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(c1)>::value, + "const std bind expression is a TR2 bind expression" ); + + volatile auto v1 = b1; + volatile auto v2 = b2; + + static_assert( std::is_bind_expression<decltype(v2)>::value, + "volatile TR1 bind expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(v1)>::value, + "volatile std bind expression is a TR2 bind expression" ); + + const volatile auto cv1 = b1; + const volatile auto cv2 = b2; + + static_assert( std::is_bind_expression<decltype(cv2)>::value, + "const volatile TR1 bind expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(cv1)>::value, + "const volatile std bind expression is a TR2 bind expression" ); +} + +void test03() +{ + bool test __attribute__((unused)) = true; + + auto b1 = std::bind<int>(minus<int>(), 6, p2::_2); + auto b2 = std::tr1::bind<int>(minus<int>(), 6, p1::_2); + + int five = 5; + int seven = 7; + VERIFY( std::tr1::bind(multiplies<int>(), p1::_1, b1)(five, seven) == -5 ); + VERIFY( std::bind(multiplies<int>(), p2::_1, b2)(seven, five) == 7 ); + + VERIFY( std::tr1::bind<int>(multiplies<int>(), p1::_1, b1)(five, seven) == -5 ); + VERIFY( std::bind<int>(multiplies<int>(), p2::_1, b2)(seven, five) == 7 ); + + static_assert( std::is_bind_expression<decltype(b2)>::value, + "TR1 bind<R> expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(b1)>::value, + "std bind<R> expression is a TR2 bind expression" ); + + const auto c1 = b1; + const auto c2 = b2; + + static_assert( std::is_bind_expression<decltype(c2)>::value, + "const TR1 bind<R> expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(c1)>::value, + "const std bind<R> expression is a TR2 bind expression" ); + + volatile auto v1 = b1; + volatile auto v2 = b2; + + static_assert( std::is_bind_expression<decltype(v2)>::value, + "volatile TR1 bind<R> expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(v1)>::value, + "volatile std bind<R> expression is a TR2 bind expression" ); + + const volatile auto cv1 = b1; + const volatile auto cv2 = b2; + + static_assert( std::is_bind_expression<decltype(cv2)>::value, + "const volatile TR1 bind<R> expression is a std bind expression" ); + static_assert( std::tr1::is_bind_expression<decltype(cv1)>::value, + "const volatile std bind<R> expression is a TR2 bind expression" ); +} + +int main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/util/testsuite_tr1.h b/libstdc++-v3/testsuite/util/testsuite_tr1.h index f0638960b27..1452e3e9f88 100644 --- a/libstdc++-v3/testsuite/util/testsuite_tr1.h +++ b/libstdc++-v3/testsuite/util/testsuite_tr1.h @@ -199,6 +199,7 @@ namespace __gnu_test struct NoexceptMoveConsClass { NoexceptMoveConsClass(NoexceptMoveConsClass&&) noexcept(true); + NoexceptMoveConsClass& operator=(NoexceptMoveConsClass&&) = default; }; struct ExceptMoveConsClass @@ -220,6 +221,7 @@ namespace __gnu_test struct NoexceptMoveAssignClass { + NoexceptMoveAssignClass(NoexceptMoveAssignClass&&) = default; NoexceptMoveAssignClass& operator=(NoexceptMoveAssignClass&&) noexcept(true); }; |