WTF::Vector: incorrectly use memcpy for types that have user-defined move constructor/assignment. |
|||||||
Issue descriptionOS: Linux and Mac. I tried debug GN non-component build on my Linux machine. mac_chromium_rel_ng and linux_chromium_rel_ng trybots showed the same problem. What steps will reproduce the problem? (1) Some types are incorrectly considered trivially move assignable, such as mojo::MoveOnlyType defined in the following file: https://code.google.com/p/chromium/codesearch#chromium/src/mojo/public/cpp/bindings/tests/container_test_util.h&l=33 (2) Assume that you have a WTF::Vector<mojo::MoveOnlyType> vec. (3) Resize |vec| to its capacity (say, |capacity0|) (4) And then, resize |vec| again to an even bigger size (say, |capacity0 + 2|) to force a re-allocation. (5) It is expected that mojo::MoveOnlyType's move constructor/assignment operator is called to move the existing elements to the new storage. (6) However, memcpy() is used which is wrong. One interesting finding is that the current mojo::MoveOnlyType uses MOVE_ONLY_TYPE_FOR_CPP_03 macro, which contains the following lines: ========================================= private: MoveOnlyType(const MoveOnlyType& other) = delete; void operator=(const MoveOnlyType& other) = delete; ========================================= If I made the following changes then WTF::Vector will do the right thing: ========================================= private: MoveOnlyType(const MoveOnlyType& other) {} void operator=(const MoveOnlyType& other) {} ========================================= +CC bratell@opera.com who originally wrote IsTriviallyMoveAssignable in wtf/TypeTraits.h
,
Mar 7 2016
,
Mar 7 2016
yutak@: Would you take a look at this?
,
Mar 8 2016
Yeah, I could confirm that type is detected as trivially movable; looking.
,
Mar 8 2016
So the core issue here is __has_trivial_assign(T) is true if T's copy assignment operator is declared as deleted. This is kind of surprising. Maybe we could adjust the TypeTraits.h a little bit...?
,
Mar 8 2016
IIUC, __has_trivial_assign means the assignment operator is trivial, but it does not imply the type is assignable. From the spec: > ISO/IEC 14882:2011, 12.8.25 > A copy/move assignment operator for class X is trivial if it is not user-provided and if > — class X has no virtual functions (10.3) and no virtual base classes (10.1), and > — the assignment operator selected to copy/move each direct base class subobject is trivial, and > — for each non-static data member of X that is of class type (or array thereof), the assignment operator > selected to copy/move that member is trivial; > otherwise the copy/move assignment operator is non-trivial. Since a deleted function is not considered user-provided, the copy assignment operator of mojo::MoveOnlyType is trivial even though it's deleted. Can we check if it's assignable as well in IsTriviallyMoveAssignable?
,
Mar 8 2016
> Since a deleted function is not considered user-provided, the copy assignment operator of mojo::MoveOnlyType is trivial even though it's deleted. > Can we check if it's assignable as well in IsTriviallyMoveAssignable? Yeah, I've started to think that is the least intrusive option here. This means that we have to write std::is_assignable equivalents ourselves, since libstdc++ 4.6 doesn't provide it, which is a bit unfortunate, but definitely doable. I investigated another option to use std::is_pod instead of __has_trivial_assign, but that seemed infeasible since there are a lot of complexities around that.
,
Mar 8 2016
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/4a08542fb0f317809a3fca5ff092cfa60c1e52ac commit 4a08542fb0f317809a3fca5ff092cfa60c1e52ac Author: yutak <yutak@chromium.org> Date: Tue Mar 08 10:19:06 2016 WTF: Move TypeTraits.cpp to test-only target. This patch renames TypeTraits.cpp to TypeTraitsTest.cpp and makes it part of wtf_unittest instead of wtf target. Additionally, its content is surrounded with anonymous namespace to indicate that the classes defined there are not exposed in WTF namespace. The file only contains static_assert assertions, so it doesn't have to be compiled into wtf. This change is a preparation of the fix for bug 592767 . BUG= 592767 Review URL: https://codereview.chromium.org/1772163003 Cr-Commit-Position: refs/heads/master@{#379800} [rename] https://crrev.com/4a08542fb0f317809a3fca5ff092cfa60c1e52ac/third_party/WebKit/Source/wtf/TypeTraitsTest.cpp [modify] https://crrev.com/4a08542fb0f317809a3fca5ff092cfa60c1e52ac/third_party/WebKit/Source/wtf/wtf.gypi
,
Mar 8 2016
__has_trivial_assign() is old, way older than =delete and move semantics. Maybe there is something better in C++11 type traits?
,
Mar 10 2016
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/d7225e41c5557ef72e5ca439fcf8287be37e7c0f commit d7225e41c5557ef72e5ca439fcf8287be37e7c0f Author: yutak <yutak@chromium.org> Date: Thu Mar 10 04:05:01 2016 WTF: Fix Vector<T> memcpy'ing incorrectly for some T. The core issue here is the implementation of IsTriviallyCopyAssignable and IsTriviallyMoveAssignable was incorrect. They both use a compiler builtin __has_trivial_assign(T), but it returns true if T's copy assignment operator is declared as deleted. To workaround that, a new type trait IsAssignable<T, From> is implemented in the same way as std::is_assignable (as it's not available at this time), and the assignability is used to limit the scope of IsTrivially{Copy,Move}Assignable. IsMoveAssignable isn't really right even with my patch for the reason stated in the comments in the patch. I think it's impossible to workaround that, though. A bunch of static_asserts are added to test some invariants related to this change. BUG= 592767 Review URL: https://codereview.chromium.org/1771303002 Cr-Commit-Position: refs/heads/master@{#380329} [modify] https://crrev.com/d7225e41c5557ef72e5ca439fcf8287be37e7c0f/third_party/WebKit/Source/wtf/TypeTraits.h [modify] https://crrev.com/d7225e41c5557ef72e5ca439fcf8287be37e7c0f/third_party/WebKit/Source/wtf/TypeTraitsTest.cpp [modify] https://crrev.com/d7225e41c5557ef72e5ca439fcf8287be37e7c0f/third_party/WebKit/Source/wtf/VectorTest.cpp
,
Mar 11 2016
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a commit 1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a Author: yutak <yutak@chromium.org> Date: Fri Mar 11 05:17:52 2016 WTF TypeTraits: Fix IsTrivially{DefaultConstructible,Destructible}. This is a follow-up of an earlier CL: https://codereview.chromium.org/1771303002/ This patch fixes two type traits so they can properly consider deleted constructors and destructors. The strategy is pretty similar to the one of the previous CL. BUG= 592767 Review URL: https://codereview.chromium.org/1785653002 Cr-Commit-Position: refs/heads/master@{#380519} [modify] https://crrev.com/1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a/third_party/WebKit/Source/wtf/TypeTraits.h [modify] https://crrev.com/1d3fb1ed5618c3ac47842ed8f9100a7b4cfdbc2a/third_party/WebKit/Source/wtf/TypeTraitsTest.cpp
,
Mar 11 2016
I think this is fixed now.
,
Jun 23 2016
Renaming Blink>Architecture to Blink>Internals |
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by yzshen@chromium.org
, Mar 7 2016Labels: OS-Linux OS-Mac