[llvm] r215478 - APInt: Make self-move-assignment a no-op to fix stage3 clang-cl
David Blaikie
dblaikie at gmail.com
Tue Aug 12 15:29:58 PDT 2014
On Tue, Aug 12, 2014 at 3:01 PM, Reid Kleckner <reid at kleckner.net> wrote:
> Author: rnk
> Date: Tue Aug 12 17:01:39 2014
> New Revision: 215478
>
> URL: http://llvm.org/viewvc/llvm-project?rev=215478&view=rev
> Log:
> APInt: Make self-move-assignment a no-op to fix stage3 clang-cl
>
> It's not clear what the semantics of a self-move should be. The
> consensus appears to be that a self-move should leave the object in a
> moved-from state, which is what our existing move assignment operator
> does.
>
> However, the MSVC 2013 STL will perform self-moves in some cases. In
> particular, when doing a std::stable_sort of an already sorted APSInt
> vector of an appropriate size, one of the merge steps will self-move
> half of the elements.
>
> We don't notice this when building with MSVC, because MSVC will not
> synthesize the move assignment operator for APSInt. Presumably
I'm assuming you're going to look into this a bit further, though?
(other than just 'presumably') both to understand when/how long we
need this workaround in place, and whether we need to do anything to
Clang for MSVC compatibility here?
> MSVC
> does this because APInt, the base class, has user-declared special
> members that implicitly delete move special members. Instead, MSVC
> selects the copy-assign operator, which defends against self-assignment.
> Clang, on the other hand, selects the move-assign operator, and we get
> garbage APInts.
I'm curious how Clang synthesizes a move assignment operator if the
base class's move assignment is implicitly deleted. Any idea what's
going on there?
>
> Modified:
> llvm/trunk/include/llvm/ADT/APInt.h
> llvm/trunk/unittests/ADT/APIntTest.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/APInt.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=215478&r1=215477&r2=215478&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/APInt.h (original)
> +++ llvm/trunk/include/llvm/ADT/APInt.h Tue Aug 12 17:01:39 2014
> @@ -656,13 +656,22 @@ public:
>
> /// @brief Move assignment operator.
> APInt &operator=(APInt &&that) {
> - if (!isSingleWord())
> + if (!isSingleWord()) {
> + // The MSVC STL shipped in 2013 requires that self move assignment be a
> + // no-op. Otherwise algorithms like stable_sort will produce answers
> + // where half of the output is left in a moved-from state.
> + if (this == &that)
> + return *this;
> delete[] pVal;
> + }
>
> - BitWidth = that.BitWidth;
> VAL = that.VAL;
>
> + // If 'this == &that', avoid zeroing our own bitwidth by storing to 'that'
> + // first.
> + unsigned ThatBitWidth = that.BitWidth;
> that.BitWidth = 0;
> + BitWidth = ThatBitWidth;
>
> return *this;
> }
>
> Modified: llvm/trunk/unittests/ADT/APIntTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=215478&r1=215477&r2=215478&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/ADT/APIntTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/APIntTest.cpp Tue Aug 12 17:01:39 2014
> @@ -678,4 +678,21 @@ TEST(APIntTest, nearestLogBase2) {
> EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX);
> }
>
> +TEST(APIntTest, SelfMoveAssignment) {
> + APInt X(32, 0xdeadbeef);
> + X = std::move(X);
> + EXPECT_EQ(32, X.getBitWidth());
> + EXPECT_EQ(0xdeadbeefULL, X.getLimitedValue());
> +
> + uint64_t Bits[] = {0xdeadbeefdeadbeefULL, 0xdeadbeefdeadbeefULL};
> + APInt Y(128, Bits);
> + Y = std::move(Y);
> + EXPECT_EQ(128, Y.getBitWidth());
> + EXPECT_EQ(~0ULL, Y.getLimitedValue());
> + const uint64_t *Raw = Y.getRawData();
> + EXPECT_EQ(2, Y.getNumWords());
> + EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]);
> + EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]);
> +}
> +
> }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list