diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h index 3347ccd4a42..4ee00ef6e80 100644 --- a/include/llvm/ADT/OwningPtr.h +++ b/include/llvm/ADT/OwningPtr.h @@ -17,6 +17,7 @@ #include "llvm/Support/Compiler.h" #include #include +#include namespace llvm { @@ -39,6 +40,17 @@ public: return *this; } + OwningPtr(std::unique_ptr &&Other) : Ptr(Other.release()) {} + + OwningPtr &operator=(std::unique_ptr &&Other) { + reset(Other.release()); + return *this; + } + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + operator std::unique_ptr() && { return std::unique_ptr(take()); } +#endif + ~OwningPtr() { delete Ptr; } @@ -61,6 +73,8 @@ public: return Tmp; } + std::unique_ptr take_unique() { return std::unique_ptr(take()); } + T &operator*() const { assert(Ptr && "Cannot dereference null pointer"); return *Ptr; diff --git a/unittests/ADT/OwningPtrTest.cpp b/unittests/ADT/OwningPtrTest.cpp index 75db2ba20be..aef4d97bd66 100644 --- a/unittests/ADT/OwningPtrTest.cpp +++ b/unittests/ADT/OwningPtrTest.cpp @@ -174,4 +174,82 @@ TEST_F(OwningPtrTest, Swap) { EXPECT_EQ(2u, TrackDestructor::Destructions); } +TEST_F(OwningPtrTest, UniqueToOwningConstruction) { + TrackDestructor::ResetCounts(); + { + std::unique_ptr A(new TrackDestructor(3)); + OwningPtr B = std::move(A); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, UniqueToOwningAssignment) { + TrackDestructor::ResetCounts(); + { + std::unique_ptr A(new TrackDestructor(3)); + OwningPtr B(new TrackDestructor(4)); + B = std::move(A); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(1u, TrackDestructor::Destructions); + } + EXPECT_EQ(2u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, TakeUniqueConstruction) { + TrackDestructor::ResetCounts(); + { + OwningPtr A(new TrackDestructor(3)); + std::unique_ptr B = A.take_unique(); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_FALSE(A.isValid()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +#if LLVM_HAS_RVALUE_REFERENCE_THIS +TEST_F(OwningPtrTest, OwningToUniqueConstruction) { + TrackDestructor::ResetCounts(); + { + OwningPtr A(new TrackDestructor(3)); + std::unique_ptr B = std::move(A); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_FALSE(A.isValid()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} +#endif }