[llvm-commits] [lld] r172993 - in /lld/trunk: include/lld/Core/ErrorOr.h include/lld/Core/LLVM.h include/lld/Driver/LinkerOptions.h lib/ReaderWriter/ELF/ReaderELF.cpp unittests/CMakeLists.txt unittests/ErrorOrTest.cpp
Michael J. Spencer
bigcheesegs at gmail.com
Sun Jan 20 13:27:05 PST 2013
Author: mspencer
Date: Sun Jan 20 15:27:05 2013
New Revision: 172993
URL: http://llvm.org/viewvc/llvm-project?rev=172993&view=rev
Log:
[Core] Use LLVM's ErrorOr<T>.
Removed:
lld/trunk/include/lld/Core/ErrorOr.h
lld/trunk/unittests/ErrorOrTest.cpp
Modified:
lld/trunk/include/lld/Core/LLVM.h
lld/trunk/include/lld/Driver/LinkerOptions.h
lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp
lld/trunk/unittests/CMakeLists.txt
Removed: lld/trunk/include/lld/Core/ErrorOr.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/ErrorOr.h?rev=172992&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/ErrorOr.h (original)
+++ lld/trunk/include/lld/Core/ErrorOr.h (removed)
@@ -1,317 +0,0 @@
-//===- lld/Core/ErrorOr.h - Error Smart Pointer ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Provides ErrorOr<T> smart pointer.
-///
-/// This should be moved to LLVMSupport when someone has time to make it c++03.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ERROR_OR_H
-#define LLD_CORE_ERROR_OR_H
-
-#include "llvm/Support/AlignOf.h"
-#include "llvm/Support/system_error.h"
-
-#include <atomic>
-#include <cassert>
-#include <type_traits>
-
-namespace lld {
-struct ErrorHolderBase {
- llvm::error_code Error;
- std::atomic<uint16_t> RefCount;
- bool HasUserData;
-
- ErrorHolderBase() : RefCount(1) {}
-
- void aquire() {
- ++RefCount;
- }
-
- void release() {
- if (RefCount.fetch_sub(1) == 1)
- delete this;
- }
-
-protected:
- virtual ~ErrorHolderBase() {}
-};
-
-template<class T>
-struct ErrorHolder : ErrorHolderBase {
- ErrorHolder(T &&UD) : UserData(UD) {}
- T UserData;
-};
-
-template<class Tp> struct ErrorOrUserDataTraits : std::false_type {};
-
-template<class T, class V>
-typename std::enable_if< std::is_constructible<T, V>::value
- , typename std::remove_reference<V>::type>::type &&
- moveIfMoveConstructible(V &t) {
- return std::move(t);
-}
-
-template<class T, class V>
-typename std::enable_if< !std::is_constructible<T, V>::value
- , typename std::remove_reference<V>::type>::type &
-moveIfMoveConstructible(V &t) {
- return t;
-}
-
-/// \brief Represents either an error or a value T.
-///
-/// ErrorOr<T> is a pointer-like class that represents the result of an
-/// operation. The result is either an error, or a value of type T. This is
-/// designed to emulate the usage of returning a pointer where nullptr indicates
-/// failure. However instead of just knowing that the operation failed, we also
-/// have an error_code and optional user data that describes why it failed.
-///
-/// It is used like the following.
-/// \code
-/// ErrorOr<Buffer> getBuffer();
-/// void handleError(error_code ec);
-///
-/// auto buffer = getBuffer();
-/// if (!buffer)
-/// handleError(buffer);
-/// buffer->write("adena");
-/// \endcode
-///
-/// ErrorOr<T> also supports user defined data for specific error_codes. To use
-/// this feature you must first add a template specialization of
-/// ErrorOrUserDataTraits derived from std::true_type for your type in the lld
-/// namespace. This specialization must have a static error_code error()
-/// function that returns the error_code this data is used with.
-///
-/// getError<UserData>() may be called to get either the stored user data, or
-/// a default constructed UserData if none was stored.
-///
-/// Example:
-/// \code
-/// struct InvalidArgError {
-/// InvalidArgError() {}
-/// InvalidArgError(std::string S) : ArgName(S) {}
-/// std::string ArgName;
-/// };
-///
-/// namespace lld {
-/// template<>
-/// struct ErrorOrUserDataTraits<InvalidArgError> : std::true_type {
-/// static error_code error() {
-/// return make_error_code(errc::invalid_argument);
-/// }
-/// };
-/// } // end namespace lld
-///
-/// using namespace lld;
-///
-/// ErrorOr<int> foo() {
-/// return InvalidArgError("adena");
-/// }
-///
-/// int main() {
-/// auto a = foo();
-/// if (!a && error_code(a) == errc::invalid_argument)
-/// llvm::errs() << a.getError<InvalidArgError>().ArgName << "\n";
-/// }
-/// \endcode
-///
-/// An implicit conversion to bool provides a way to check if there was an
-/// error. The unary * and -> operators provide pointer like access to the
-/// value. Accessing the value when there is an error has undefined behavior.
-///
-/// When T is a reference type the behaivor is slightly different. The reference
-/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and
-/// there is special handling to make operator -> work as if T was not a
-/// reference.
-///
-/// T cannot be a rvalue reference.
-template<class T>
-class ErrorOr {
- static const bool isRef = std::is_reference<T>::value;
- typedef std::reference_wrapper<typename std::remove_reference<T>::type> wrap;
-
-public:
- typedef typename
- std::conditional< isRef
- , wrap
- , T
- >::type storage_type;
-
-private:
- typedef T &reference;
- typedef typename std::remove_reference<T>::type *pointer;
-
-public:
- ErrorOr() : IsValid(false) {}
-
- ErrorOr(llvm::error_code ec) : HasError(true), IsValid(true) {
- Error = new ErrorHolderBase;
- Error->Error = ec;
- Error->HasUserData = false;
- }
-
- template<class UserDataT>
- ErrorOr(UserDataT UD, typename
- std::enable_if<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0)
- : HasError(true), IsValid(true) {
- Error = new ErrorHolder<UserDataT>(std::move(UD));
- Error->Error = ErrorOrUserDataTraits<UserDataT>::error();
- Error->HasUserData = true;
- }
-
- ErrorOr(T t) : HasError(false), IsValid(true) {
- new (get()) storage_type(moveIfMoveConstructible<storage_type>(t));
- }
-
- ErrorOr(const ErrorOr &other) : IsValid(false) {
- // Construct an invalid ErrorOr if other is invalid.
- if (!other.IsValid)
- return;
- if (!other.HasError) {
- // Get the other value.
- new (get()) storage_type(*other.get());
- HasError = false;
- } else {
- // Get other's error.
- Error = other.Error;
- HasError = true;
- Error->aquire();
- }
-
- IsValid = true;
- }
-
- ErrorOr &operator =(const ErrorOr &other) {
- if (this == &other)
- return;
-
- this->~ErrorOr();
- new (this) ErrorOr(other);
-
- return *this;
- }
-
- ErrorOr(ErrorOr &&other) : IsValid(false) {
- // Construct an invalid ErrorOr if other is invalid.
- if (!other.IsValid)
- return;
- if (!other.HasError) {
- // Get the other value.
- IsValid = true;
- new (get()) storage_type(std::move(*other.get()));
- HasError = false;
- // Tell other not to do any destruction.
- other.IsValid = false;
- } else {
- // Get other's error.
- Error = other.Error;
- HasError = true;
- // Tell other not to do any destruction.
- other.IsValid = false;
- }
-
- IsValid = true;
- }
-
- ErrorOr &operator =(ErrorOr &&other) {
- if (this == &other)
- return *this;
-
- this->~ErrorOr();
- new (this) ErrorOr(std::move(other));
-
- return *this;
- }
-
- ~ErrorOr() {
- if (!IsValid)
- return;
- if (HasError)
- Error->release();
- else
- get()->~storage_type();
- }
-
- template<class ET>
- ET getError() const {
- assert(IsValid && "Cannot get the error of a default constructed ErrorOr!");
- assert(HasError && "Cannot get an error if none exists!");
- assert(ErrorOrUserDataTraits<ET>::error() == Error->Error &&
- "Incorrect user error data type for error!");
- if (!Error->HasUserData)
- return ET();
- return reinterpret_cast<const ErrorHolder<ET>*>(Error)->UserData;
- }
-
- typedef void (*unspecified_bool_type)();
- static void unspecified_bool_true() {}
-
- /// \brief Return false if there is an error.
- operator unspecified_bool_type() const {
- assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
- return HasError ? 0 : unspecified_bool_true;
- }
-
- operator llvm::error_code() const {
- assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
- return HasError ? Error->Error : llvm::error_code::success();
- }
-
- pointer operator ->() {
- return toPointer(get());
- }
-
- reference operator *() {
- return *get();
- }
-
-private:
- pointer toPointer(pointer t) {
- return t;
- }
-
- pointer toPointer(wrap *t) {
- return &t->get();
- }
-
-protected:
- storage_type *get() {
- assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
- assert(!HasError && "Cannot get value when an error exists!");
- return reinterpret_cast<storage_type*>(_t.buffer);
- }
-
- const storage_type *get() const {
- assert(IsValid && "Can't do anything on a default constructed ErrorOr!");
- assert(!HasError && "Cannot get value when an error exists!");
- return reinterpret_cast<const storage_type*>(_t.buffer);
- }
-
- union {
- llvm::AlignedCharArrayUnion<storage_type> _t;
- ErrorHolderBase *Error;
- };
- bool HasError : 1;
- bool IsValid : 1;
-};
-
-template<class T, class E>
-typename std::enable_if<llvm::is_error_code_enum<E>::value ||
- llvm::is_error_condition_enum<E>::value, bool>::type
-operator ==(ErrorOr<T> &Err, E Code) {
- return error_code(Err) == Code;
-}
-} // end namespace lld
-
-#endif
Modified: lld/trunk/include/lld/Core/LLVM.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LLVM.h?rev=172993&r1=172992&r2=172993&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/LLVM.h (original)
+++ lld/trunk/include/lld/Core/LLVM.h Sun Jan 20 15:27:05 2013
@@ -33,6 +33,9 @@
template<typename T>
struct SaveAndRestore;
+ template<typename T>
+ class ErrorOr;
+
// Reference counting.
template <typename T> class IntrusiveRefCntPtr;
template <typename T> struct IntrusiveRefCntPtrInfo;
@@ -44,7 +47,6 @@
// TODO: DenseMap, ...
}
-
namespace lld {
// Casting operators.
using llvm::isa;
@@ -63,6 +65,7 @@
using llvm::SmallVector;
using llvm::SmallVectorImpl;
using llvm::SaveAndRestore;
+ using llvm::ErrorOr;
// Reference counting.
using llvm::IntrusiveRefCntPtr;
Modified: lld/trunk/include/lld/Driver/LinkerOptions.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/LinkerOptions.h?rev=172993&r1=172992&r2=172993&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/LinkerOptions.h (original)
+++ lld/trunk/include/lld/Driver/LinkerOptions.h Sun Jan 20 15:27:05 2013
@@ -16,12 +16,12 @@
#ifndef LLD_DRIVER_LINKER_OPTIONS_H
#define LLD_DRIVER_LINKER_OPTIONS_H
-#include "lld/Core/ErrorOr.h"
#include "lld/Core/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
Modified: lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp?rev=172993&r1=172992&r2=172993&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp Sun Jan 20 15:27:05 2013
@@ -15,7 +15,6 @@
#include "lld/ReaderWriter/ReaderELF.h"
#include "lld/ReaderWriter/ReaderArchive.h"
-#include "lld/Core/ErrorOr.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
@@ -26,6 +25,7 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
Modified: lld/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/CMakeLists.txt?rev=172993&r1=172992&r2=172993&view=diff
==============================================================================
--- lld/trunk/unittests/CMakeLists.txt (original)
+++ lld/trunk/unittests/CMakeLists.txt Sun Jan 20 15:27:05 2013
@@ -14,6 +14,5 @@
)
add_lld_unittest(CoreTests
- ErrorOrTest.cpp
RangeTest.cpp
)
Removed: lld/trunk/unittests/ErrorOrTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/ErrorOrTest.cpp?rev=172992&view=auto
==============================================================================
--- lld/trunk/unittests/ErrorOrTest.cpp (original)
+++ lld/trunk/unittests/ErrorOrTest.cpp (removed)
@@ -1,75 +0,0 @@
-//===- unittests/ErrorOrTest.cpp - ErrorOr.h tests ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/ErrorOr.h"
-
-#include "gtest/gtest.h"
-
-#include <memory>
-
-using namespace lld;
-using namespace llvm;
-
-namespace {
-
-ErrorOr<int> t1() {return 1;}
-ErrorOr<int> t2() {return make_error_code(errc::invalid_argument);}
-
-TEST(ErrorOr, SimpleValue) {
- auto a = t1();
- EXPECT_TRUE(a);
- EXPECT_EQ(1, *a);
-
- a = t2();
- EXPECT_FALSE(a);
- EXPECT_EQ(errc::invalid_argument, a);
- EXPECT_DEBUG_DEATH(*a, "Cannot get value when an error exists");
-}
-
-ErrorOr<std::unique_ptr<int>> t3() {
- return std::unique_ptr<int>(new int(3));
-}
-
-TEST(ErrorOr, Types) {
- int x;
- ErrorOr<int&> a(x);
- *a = 42;
- EXPECT_EQ(42, *a);
-
- // Move only types.
- EXPECT_EQ(3, **t3());
-}
-} // end anon namespace
-
-struct InvalidArgError {
- InvalidArgError() {}
- InvalidArgError(std::string S) : ArgName(S) {}
- std::string ArgName;
-};
-
-namespace lld {
-template<>
-struct ErrorOrUserDataTraits<InvalidArgError> : std::true_type {
- static error_code error() {
- return make_error_code(errc::invalid_argument);
- }
-};
-} // end namespace lld
-
-ErrorOr<int> t4() {
- return InvalidArgError("adena");
-}
-
-namespace {
-TEST(ErrorOr, UserErrorData) {
- auto a = t4();
- EXPECT_EQ(errc::invalid_argument, a);
- EXPECT_EQ("adena", t4().getError<InvalidArgError>().ArgName);
-}
-} // end anon namespace
More information about the llvm-commits
mailing list