Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -536,6 +536,52 @@ } }; +class SwitchControlledDeleterBase { + bool TurnedOff; +public: + SwitchControlledDeleterBase() : TurnedOff(false) {} + void TurnOff() { TurnedOff = true; } + bool GetTurnedOff() const { return TurnedOff; } +}; + +template +class SwitchControlledDeleter : public SwitchControlledDeleterBase { +public: + void operator()(T* p) { + if (!GetTurnedOff()) + delete(p); + } +}; + +/// \brief unique_ptr that allows accessing a raw pointer after release. +/// +/// Intended for use in cases when conditional releases are mixed with raw +/// pointer access. +/// +/// Example: +/// +/// unique_ptr_deferred_release P(new P); +/// if (cond) { +/// P.deferred_release(); +/// } +/// assert(P.get()); // 'true' regardless of whether deferred_release() was +/// // called or not. +/// NonOwningFunction(P.get()); +template> +class unique_ptr_deferred_release : public std::unique_ptr { +public: + explicit unique_ptr_deferred_release(T* p) + : std::unique_ptr(p) {}; + typename std::unique_ptr::pointer deferred_release() { + std::unique_ptr::get_deleter().TurnOff(); + return std::unique_ptr::get(); + } + bool released() const { + return !std::unique_ptr::get() || + std::unique_ptr::get_deleter().GetTurnedOff(); + } +}; + template struct pair_hash { size_t operator()(const std::pair &P) const { Index: unittests/ADT/CMakeLists.txt =================================================================== --- unittests/ADT/CMakeLists.txt +++ unittests/ADT/CMakeLists.txt @@ -38,6 +38,7 @@ TinyPtrVectorTest.cpp TripleTest.cpp TwineTest.cpp + UniquePtrDeferredRelease.cpp VariadicFunctionTest.cpp ) Index: unittests/ADT/UniquePtrDeferredRelease.cpp =================================================================== --- unittests/ADT/UniquePtrDeferredRelease.cpp +++ unittests/ADT/UniquePtrDeferredRelease.cpp @@ -0,0 +1,55 @@ +//===- UniquePtrCondRelease.cpp - unique_ptr_deferred_release unit tests --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/STLExtras.h" + +using namespace llvm; + +namespace { + +TEST(UniquePtrDeferredRelease, Release) { + unique_ptr_deferred_release P(new int); + EXPECT_TRUE(P); + + int *Tmp = P.release(); + EXPECT_FALSE(P); + EXPECT_TRUE(P.released()); + EXPECT_FALSE(P.get()); + + delete Tmp; +} + +TEST(UniquePtrDeferredRelease, DeferredRelease) { + unique_ptr_deferred_release P(new int); + EXPECT_TRUE(P); + + P.deferred_release(); + EXPECT_TRUE(P); + EXPECT_TRUE(P.released()); + EXPECT_TRUE(P.get()); + + delete P.get(); +} + +TEST(UniquePtrDeferredRelease, Swap) { + unique_ptr_deferred_release P1(new int); + unique_ptr_deferred_release P2(new int); + P1.deferred_release(); + P1.swap(P2); + EXPECT_TRUE(P1); + EXPECT_FALSE(P1.released()); + EXPECT_TRUE(P1.get()); + EXPECT_TRUE(P2); + EXPECT_TRUE(P2.released()); + EXPECT_TRUE(P2.get()); + + delete P2.get(); +} +} // end anonymous namespace