Index: include/llvm/ADT/ScopeExit.h =================================================================== --- /dev/null +++ include/llvm/ADT/ScopeExit.h @@ -0,0 +1,52 @@ +//===- llvm/ADT/ScopeExit.h - Execute code at scope exit --------*- 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 make_scope_exit function, which executes user-defined +// cleanup logic at scope exit. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCOPE_EXIT_H +#define LLVM_ADT_SCOPE_EXIT_H + +#include "llvm/Support/Compiler.h" + +#include +#include + +namespace llvm { +namespace detail { + +template class LLVM_ATTRIBUTE_UNUSED_RESULT scope_exit { + Callable ExitFunction; + +public: + template + explicit scope_exit(Fp &&F) : ExitFunction(std::forward(F)) {} + + ~scope_exit() { ExitFunction(); } +}; + +} // end namespace detail + +// Keeps the callable object that is passed in, and execute it at the +// destruction of the returned object (usually at the scope exit where the +// returned object is kept). +// +// Interface is specified by p0052r2. +template +detail::scope_exit::type> +make_scope_exit(Callable &&F) { + return detail::scope_exit::type>( + std::forward(F)); +} + +} // end namespace llvm + +#endif Index: unittests/ADT/CMakeLists.txt =================================================================== --- unittests/ADT/CMakeLists.txt +++ unittests/ADT/CMakeLists.txt @@ -34,6 +34,7 @@ PriorityWorklistTest.cpp RangeAdapterTest.cpp SCCIteratorTest.cpp + ScopeExitTest.cpp SequenceTest.cpp SetVectorTest.cpp SmallPtrSetTest.cpp Index: unittests/ADT/ScopeExitTest.cpp =================================================================== --- /dev/null +++ unittests/ADT/ScopeExitTest.cpp @@ -0,0 +1,58 @@ +//===- llvm/unittest/ADT/ScopeExit.cpp - Scope exit unit tests --*- 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/ScopeExit.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(ScopeExitTest, Basic) { + bool Called = false; + { + auto g = make_scope_exit([&] { Called = true; }); + EXPECT_FALSE(Called); + } + EXPECT_TRUE(Called); +} + +TEST(ScopeExitTest, Move) { + struct Callable { + bool &CopyConstructed; + bool &MoveConstructed; + + void operator()() const {} + + Callable(bool &CopyConstructed, bool &MoveConstructed) + : CopyConstructed(CopyConstructed), MoveConstructed(MoveConstructed) {} + + Callable(const Callable &Rhs) + : CopyConstructed(Rhs.CopyConstructed), + MoveConstructed(Rhs.MoveConstructed) { + Rhs.CopyConstructed = true; + } + + Callable(Callable &&Rhs) + : CopyConstructed(Rhs.CopyConstructed), + MoveConstructed(Rhs.MoveConstructed) { + Rhs.MoveConstructed = true; + } + }; + + bool Copied = false; + bool Moved = false; + Callable f(Copied, Moved); + ASSERT_FALSE(Copied); + ASSERT_FALSE(Moved); + auto g = make_scope_exit(std::move(f)); + EXPECT_FALSE(Copied); + EXPECT_TRUE(Moved); +} +}