Summary:
In r348529, I improved the library-defined diagnostic for using containers
with a non-const comparator/hasher. However, the check is now performed
too early, which leads to the diagnostic being emitted in cases where it
shouldn't. See PR41360 for details.
This patch moves the diagnostic to the destructor of the containers, which
means that the diagnostic will only be emitted when the container is instantiated
at a point where the comparator and the key/value are required to be complete.
We still retain better diagnostics than before r348529, because the diagnostics
are performed in the containers themselves instead of __tree and __hash_table.
As a drive-by fix, I improved the diagnostic to mention that we can't find
a _viable_ const call operator, as suggested by EricWF in PR41360.
Reviewers: EricWF, mclow.lists
Subscribers: christof, jkorous, dexonsmith, libcxx-commits, zoecarver
Tags: #libc
Differential Revision: https://reviews.llvm.org/D60540
llvm-svn: 358189
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
to reflect the new license. These used slightly different spellings that
defeated my regular expressions.
We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.
Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.
llvm-svn: 351648
Summary:
When providing a non-const-callable comparator in a map or set, the
warning diagnostic does not include the point of instantiation of
the container that triggered the warning, which makes it difficult
to track down the problem. This commit improves the diagnostic by
placing it directly in the body of the associative container.
The same change is applied to unordered associative containers, which
had a similar problem.
Finally, this commit cleans up the forward declarations of several
map and unordered_map helpers, which are not needed anymore.
<rdar://problem/41370747>
Reviewers: EricWF, mclow.lists
Subscribers: christof, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D48955
llvm-svn: 348529
This commit adds a merge member function to all the map and set containers,
which splices nodes from the source container. This completes support for
P0083r3.
Differential revision: https://reviews.llvm.org/D48896
llvm-svn: 345744
This commit adds a node handle type, (located in __node_handle), and adds
extract() and insert() members to all map and set types, as well as their
implementations in __tree and __hash_table.
The second half of this feature is adding merge() members, which splice nodes
in bulk from one container into another. This will be committed in a follow-up.
Differential revision: https://reviews.llvm.org/D46845
llvm-svn: 338472
These containers type-punned between pair<K, V> and pair<const K, V> as an
optimization. This commit instead provides access to the pair via a pair of
references that assign through to the underlying object. It's still undefined to
mutate a const object, but clang doesn't optimize on this for data members, so
this should be safe.
Differential revision: https://reviews.llvm.org/D47607
llvm-svn: 333948
Seems to have broken some tests since I first wrote this a while
back. Will reland after checking what went wrong with the tests.
This reverts commit 7023194c8d11a081fd01ed25308b3d60193c6a06.
llvm-svn: 322039
Summary:
This patch improves how libc++ handles min/max macros within the headers. Previously libc++ would undef them and emit a warning.
This patch changes libc++ to use `#pragma push_macro` to save the macro before undefining it, and `#pragma pop_macro` to restore the macros and the end of the header.
Reviewers: mclow.lists, bcraig, compnerd, EricWF
Reviewed By: EricWF
Subscribers: cfe-commits, krytarowski
Differential Revision: https://reviews.llvm.org/D33080
llvm-svn: 304357
Summary:
__compressed_pair takes and passes it's constructor arguments by value. This causes arguments to be moved 3 times instead of once. This patch addresses that issue and fixes `constexpr` on the constructors.
I would rather have this fix than D27564, and I'm fairly confident it's not ABI breaking but I'm not 100% sure.
I prefer this solution because it removes a lot of code and makes the implementation *much* smaller.
Reviewers: mclow.lists, K-ballo
Reviewed By: K-ballo
Subscribers: K-ballo, cfe-commits
Differential Revision: https://reviews.llvm.org/D27565
llvm-svn: 300140
r296565 attempted to add better diagnostics when an unordered container
is instantiated with a hash that doesn't meet the Hash requirements.
However I mistakenly checked the wrong set of requirements. Specifically
it checked if the hash met the requirements for specializations of
std::hash. However these requirements are stricter than the generic
Hash requirements.
This patch fixes the assertions to only check the Hash requirements.
llvm-svn: 296919
This patch adds a static assertion that the specified hash meets
the requirements of an enabled hash, and it ensures that the static
assertion is evaluated before __compressed_pair is instantiated.
That way the static assertion diagnostic is emitted first.
llvm-svn: 296565
Summary:
On Windows the identifier `__deallocate` is defined as a macro by one of the Windows system headers. Previously libc++ worked around this by `#undef __deallocate` and generating a warning. However this causes the WIN32 version of `__threading_support` to always generate a warning on Windows. This is not OK.
This patch renames all usages of `__deallocate` internally as to not conflict with the macro.
Reviewers: mclow.lists, majnemer, rnk, rsmith, smeenai, compnerd
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D28426
llvm-svn: 291332
The name _LIBCPP_TYPE_VIS_ONLY is no longer accurate because both
_LIBCPP_TYPE_VIS and _LIBCPP_TYPE_VIS_ONLY expand to
__attribute__((__type_visibility__)) with Clang. The only remaining difference
is that _LIBCPP_TYPE_VIS_ONLY can be applied to templates whereas
_LIBCPP_TYPE_VIS cannot (due to dllimport/dllexport not being allowed on
templates).
This patch renames _LIBCPP_TYPE_VIS_ONLY to _LIBCPP_TEMPLATE_VIS.
llvm-svn: 291035
Summary: The `max_size()` method of containers should respect both the allocator's reported `max_size` and the range of the `difference_type`. This patch makes all containers choose the smallest of those two values.
Reviewers: mclow.lists, EricWF
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D26885
llvm-svn: 287729
Summary:
This patch attempts to fix the undefined behavior in __hash_table by changing the node pointer types used throughout. The pointer types are changed for raw pointers in the current ABI and for fancy pointers in ABI V2 (since the fancy pointer types may not be ABI compatible).
The UB in `__hash_table` arises because tree downcasts the embedded end node and then deferences that pointer. Currently there are 2 node types in __hash_table:
* `__hash_node_base` which contains the `__next_` pointer.
* `__hash_node` which contains `__hash_` and `__value_`.
Currently the bucket list, iterators, and `__next_` pointers store pointers to `__hash_node` even though they all need to store `__hash_node_base` pointers.
This patch makes that change by introducing a `__next_pointer` typedef which is a pointer to `__hash_node` in the current ABI and `__hash_node_base` afterwards.
One notable change is to the type of `__bucket_list` which used to be defined as `unique_ptr<__node_pointer[], ...>` and is now `unique_ptr<__next_pointer[], ...>` meaning that we now allocate and deallocate different types using a different allocator. I'm going to give this part of the change more thought since it may introduce compatibility issues.
This change is similar to D20786.
Reviewers: mclow.lists, EricWF
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D20787
llvm-svn: 276533
This patch implements a simple optimization in __hash_table::find. When iterating
the found bucket we only constrain the bucket elements hash if it doesn't
already match the unconstrained hash of the specified key. This prevent
the performance of an expensive modulo operation.
Since the bucket element almost always matches the key, especially when the
load factor is low, this optimization has large performance impacts. For
a unordered_set<int> of random integers this patch improves the performance of
'find(...)' by 40%.
llvm-svn: 275734
This cleans up a previous optimization attempt in hash, and results in
additional performance improvements over that previous attempt. Additionally
this new optimization does not hinder the power of 2 bucket count optimization.
llvm-svn: 275114
Summary: The current implementations of __hash_table::find used by std::unordered_set/unordered_map call key_eq on each key that lands in the same bucket as the key you're looking for. However, since equal objects mush hash to the same value, you can short-circuit the possibly expensive call to key_eq by checking the hashes first.
Reviewers: EricWF
Subscribers: kmensah, cfe-commits
Differential Revision: http://reviews.llvm.org/D21510
llvm-svn: 274857
This patch improves the performance of unordered_set's find by 45% when
the value exists within the set. __hash_tables find method
needs to check if it's reached the end of the bucket by constraining the
hash of the current node and checking it against the bucket index. However
constraining the hash is an expensive operations and it can be avoided if the
two unconstrained hashes are equal. This patch applies that optimization.
This patch also adds a top level directory called benchmarks. 'benchmarks/'
is intended to store any/all benchmarks written for the standard library.
Currently nothing is done with files under 'benchmarks/' but I would like
to move towards introducing a formal format and test runner.
llvm-svn: 274423
In cases where emplace is called with two arguments and the first one
matches the key_type we can Key to check for duplicates before allocating.
This patch expands on work done by dexonsmith@apple.com.
llvm-svn: 266498
unordered_set::emplace and unordered_map::emplace construct a node, then
try to insert it. If insertion fails, the node gets deleted.
To avoid this unnecessary malloc traffic, check to see if the argument
to emplace has the appropriate key_type. If so, we can use that key
directly and delay the malloc until we're sure we're inserting something
new.
Test updates by Eric Fiselier, who rewrote the old allocation tests to
include the new cases.
There are two orthogonal future directions:
1. Apply the same optimization to set and map.
2. Extend the optimization to when the argument is not key_type, but can
be converted to it without side effects. Ideally, we could do this
whenever key_type is trivially destructible and the argument is
trivially convertible to key_type, but in practise the relevant type
traits "blow up sometimes". At least, we should catch a few simple
cases (such as when both are primitive types).
llvm-svn: 263746
This patch is fairly large and contains a number of changes. The main change
is teaching '__hash_table' how to handle '__hash_value_type'. Unfortunately
this change is a rampant layering violation, but it's required to make
unordered_map conforming without re-writing all of __hash_table.
After this change 'unordered_map' can delegate to '__hash_table' in almost all cases.
The major changes found in this patch are:
* Teach __hash_table to differentiate between the true container value type
and the node value type by introducing the "__container_value_type" and
"__node_value_type" typedefs. In the case of unordered_map '__container_value_type'
is 'pair<const Key, Value>' and '__node_value_type' is '__hash_value_type'.
* Switch almost all overloads in '__hash_table' previously taking 'value_type'
(AKA '__node_value_type) to take '__container_value_type' instead. Previously
'pair<K, V>' would be implicitly converted to '__hash_value_type<K, V>' because
of the function signature.
* Add '__get_key', '__get_value', '__get_ptr', and '__move' static functions to
'__key_value_types'. These functions allow '__hash_table' to unwrap
'__node_value_type' objects into '__container_value_type' and its sub-parts.
* Pass '__hash_value_type::__value_' to 'a.construct(p, ...)' instead of
'__hash_value_type' itself. The C++14 standard requires that 'a.construct()'
and 'a.destroy()' are only ever instantiated for the containers value type.
* Remove '__hash_value_type's constructors and destructors. We should never
construct an instance of this type.
(TODO this is UB but we already do it in plenty of places).
* Add a generic "try-emplace" function to '__hash_table' called
'__emplace_unique_key_args(Key const&, Args...)'.
The following changes were done as cleanup:
* Introduce the '_LIBCPP_CXX03_LANG' macro to be used in place of
'_LIBCPP_HAS_NO_VARIADICS' or '_LIBCPP_HAS_NO_RVALUE_REFERENCE'.
* Cleanup C++11 only overloads that assume an incomplete C++11 implementation.
For example this patch removes the __construct_node overloads that do
manual pack expansion.
* Forward 'unordered_map::emplace' to '__hash_table' and remove dead code
resulting from the change. This includes almost all
'unordered_map::__construct_node' overloads.
The following changes are planed for future revisions:
* Fix LWG issue #2469 by delegating 'unordered_map::operator[]' to use
'__emplace_unique_key_args'.
* Rewrite 'unordered_map::try_emplace' in terms of '__emplace_unique_key_args'.
* Optimize '__emplace_unique' to call '__emplace_unique_key_args' when possible.
This prevent unneeded allocations when inserting duplicate entries.
The additional follow up work needed after this patch:
* Respect the lifetime rules for '__hash_value_type' by actually constructing it.
* Make '__insert_multi' act similar to '__insert_unique' for objects of type
'T&' and 'T const &&' with 'T = __container_value_type'.
llvm-svn: 260513
This time I kept <ext/hash_map> working!
This patch is the first in a series of patches that's meant to better
support unordered_map. unordered_map has a special "value_type" that
differs from pair<const Key, Value>. In order to meet the EmplaceConstructible
and CopyInsertable requirements we need to teach __hash_table about this
special value_type.
This patch creates a "__hash_node_types" traits class that contains
all of the typedefs needed by the unordered containers and it's iterators.
These typedefs include ones for each node type and node pointer type,
as well as special typedefs for "unordered_map"'s value type.
As a result of this change all of the unordered containers now all support
incomplete types.
As a drive-by fix I changed the difference_type in __hash_table to always
be ptrdiff_t. There is a corresponding change to size_type but it cannot
take affect until an ABI break.
This patch will be followed up shortly with fixes for various unordered_map
bugs and problems.
llvm-svn: 260431
This patch is the first in a series of patches that's meant to better
support unordered_map. unordered_map has a special "value_type" that
differs from pair<const Key, Value>. In order to meet the EmplaceConstructible
and CopyInsertable requirements we need to teach __hash_table about this
special value_type.
This patch creates a "__hash_node_types" traits class that contains
all of the typedefs needed by the unordered containers and it's iterators.
These typedefs include ones for each node type and node pointer type,
as well as special typedefs for "unordered_map"'s value type.
As a result of this change all of the unordered containers now all support
incomplete types.
As a drive-by fix I changed the difference_type in __hash_table to always
be ptrdiff_t. There is a corresponding change to size_type but it cannot
take affect until an ABI break.
This patch will be followed up shortly with fixes for various unordered_map
fixes.
llvm-svn: 260012
Rename the version of __construct_node() that takes a hash as an
argument to __construct_node_hash(), and use perfect-forwarding when
Rvalue references are available. The primary motivation is to allow
other types through, since unordered_map's value_type is different from
__hash_table's value_type -- a follow-up will take advantage of this --
but the rename is general "goodness".
There should be no functionality change here (aside from enabling the
follow-up).
llvm-svn: 258511
This change moves visibility attributes from out-of-class method
definitions to in-class declaration. This is needed for a switch to
attribute((internal_linkage)) (see http://reviews.llvm.org/D13925)
which can only appear on the first declaration.
This change does not touch istream/ostream/streambuf. They are
handled separately in http://reviews.llvm.org/D14409.
llvm-svn: 252385
Summary:
Throughout the libc++ headers, there are a few instances where
_VSTD::move() is used to return a local variable. Howard commented in
r189039 that these were there "for non-obvious reasons such as to help
things limp along in C++03 language mode".
However, when compiling these headers with warnings on, and in C++11 or
higher mode (like we do in FreeBSD), they cause the following complaints
about pessimizing moves:
In file included from tests.cpp:26:
In file included from tests.hpp:29:
/usr/include/c++/v1/map:1368:12: error: moving a local object in a return statement prevents copy elision [-Werror,-Wpessimizing-move]
return _VSTD::move(__h); // explicitly moved for C++03
^
/usr/include/c++/v1/__config:368:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_NAMESPACE
^
Attempt to fix this by adding a _LIBCPP_EXPLICIT_MOVE() macro to
__config, which gets defined to _VSTD::move for pre-C++11, and to
nothing for C++11 and later.
I am not completely satisfied with the macro name (I also considered
_LIBCPP_COMPAT_MOVE and some other variants), so suggestions are
welcome. :)
Reviewers: mclow.lists, howard.hinnant, EricWF
Subscribers: arthur.j.odwyer, cfe-commits
Differential Revision: http://reviews.llvm.org/D11394
llvm-svn: 245421
Although CMake adds warning flags, they are ignored in the libc++ headers
because the headers '#pragma system header' themselves.
This patch disables the system header pragma when building libc++ and fixes
the warnings that arose.
The warnings fixed were:
1. <memory> - anonymous structs are a GNU extension
2. <functional> - anonymous structs are a GNU extension.
3. <__hash_table> - Embedded preprocessor directives have undefined behavior.
4. <string> - Definition is missing noexcept from declaration.
5. <__std_stream> - Unused variable.
llvm-svn: 242623