Index: llvm/include/llvm/ADT/MaybeOwned.h =================================================================== --- /dev/null +++ llvm/include/llvm/ADT/MaybeOwned.h @@ -0,0 +1,103 @@ +//===- llvm/ADT/MaybeOwned.h - Owned or borrowed smart ptr ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MaybeOwned template class that is essentially +// a variant of a unique_ptr and a T&. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_MAYBEOWNED_H +#define LLVM_ADT_MAYBEOWNED_H + +#include + +namespace llvm { +template class MaybeOwned { + std::unique_ptr Owned; + T *Borrowed; + +public: + MaybeOwned() : Borrowed(nullptr) {} + + MaybeOwned(T &Ref) : Borrowed(&Ref) {} + + template , std::unique_ptr>::value>::type * = 0> + MaybeOwned(std::unique_ptr Ptr) + : Owned(std::move(Ptr)), Borrowed(Owned.get()) {} + + MaybeOwned(MaybeOwned &&Other) = default; + + MaybeOwned &operator=(MaybeOwned &&Other) = default; + + T &operator*() { return *Borrowed; } + const T &operator*() const { return *Borrowed; } + + T *operator->() { return Borrowed; } + const T *operator->() const { return Borrowed; } +}; + +template +bool operator<(const MaybeOwned &L, const MaybeOwned &R) { + return L.Borrowed < R.Borrowed; +} + +template +bool operator<=(const MaybeOwned &L, const MaybeOwned &R) { + return L.Borrowed <= R.Borrowed; +} + +template +bool operator>(const MaybeOwned &L, const MaybeOwned &R) { + return L.Borrowed > R.Borrowed; +} + +template +bool operator>=(const MaybeOwned &L, const MaybeOwned &R) { + return L.Borrowed >= R.Borrowed; +} + +template +bool operator==(const MaybeOwned &L, const MaybeOwned &R) { + return L.Borrowed == R.Borrowed; +} + +template +bool operator!=(const MaybeOwned &L, const MaybeOwned &R) { + return L.Borrowed != R.Borrowed; +} + +template bool operator<(const MaybeOwned &L, const T *R) { + return L.Borrowed < R.Borrowed; +} + +template bool operator<=(const MaybeOwned &L, const T *R) { + return L.Borrowed <= R.Borrowed; +} + +template bool operator>(const MaybeOwned &L, const T *R) { + return L.Borrowed > R.Borrowed; +} + +template bool operator>=(const MaybeOwned &L, const T *R) { + return L.Borrowed >= R.Borrowed; +} + +template bool operator==(const MaybeOwned &L, const T *R) { + return L.Borrowed == R.Borrowed; +} + +template bool operator!=(const MaybeOwned &L, const T *R) { + return L.Borrowed != R.Borrowed; +} + +} // end namespace llvm + +#endif // LLVM_ADT_MAYBEOWNED_H Index: llvm/unittests/ADT/CMakeLists.txt =================================================================== --- llvm/unittests/ADT/CMakeLists.txt +++ llvm/unittests/ADT/CMakeLists.txt @@ -38,6 +38,7 @@ MakeUniqueTest.cpp MappedIteratorTest.cpp MapVectorTest.cpp + MaybeOwnedTest.cpp OptionalTest.cpp PackedVectorTest.cpp PointerEmbeddedIntTest.cpp Index: llvm/unittests/ADT/MaybeOwnedTest.cpp =================================================================== --- /dev/null +++ llvm/unittests/ADT/MaybeOwnedTest.cpp @@ -0,0 +1,82 @@ +//===- llvm/ADT/MaybeOwnedTest.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/MaybeOwned.h" +#include "gtest/gtest.h" + +using namespace llvm; + +struct Foo { + Foo(bool &D, bool &M, int &N) : D(D), M(M), N(N) {} + ~Foo() { D = true; } + Foo(Foo &&F) : D(F.D), M(F.M), N(F.N) { M = true; } + + bool &D; + bool &M; + + int &N; +}; + +TEST(MaybeOwnedTest, Borrowed) { + bool D = false, M = false; + int N = 42; + { + Foo F(D, M, N); + { + MaybeOwned A; + { + MaybeOwned B(F); + EXPECT_EQ(42, B->N); + EXPECT_EQ(42, (*B).N); + ++B->N; + A = std::move(B); + } + EXPECT_FALSE(D); + EXPECT_FALSE(M); + + EXPECT_EQ(43, A->N); + EXPECT_EQ(43, (*A).N); + ++A->N; + } + EXPECT_FALSE(D); + EXPECT_FALSE(M); + + EXPECT_EQ(44, F.N); + } + EXPECT_TRUE(D); + EXPECT_FALSE(M); +} + +TEST(MaybeOwnedTest, Owned) { + bool D = false, M = false; + int N = 42; + + { + std::unique_ptr F = llvm::make_unique(D, M, N); + { + MaybeOwned A; + { + MaybeOwned B(std::move(F)); + EXPECT_EQ(42, B->N); + EXPECT_EQ(42, (*B).N); + ++B->N; + A = std::move(B); + } + EXPECT_FALSE(D); + EXPECT_FALSE(M); + + EXPECT_EQ(43, A->N); + EXPECT_EQ(43, (*A).N); + ++A->N; + } + EXPECT_TRUE(D); + EXPECT_FALSE(M); + EXPECT_EQ(44, N); + } +}