[llvm-commits] [llvm] r172991 - in /llvm/trunk: include/llvm/Support/Compiler.h include/llvm/Support/ErrorOr.h include/llvm/Support/type_traits.h unittests/Support/CMakeLists.txt unittests/Support/ErrorOrTest.cpp
Michael Spencer
bigcheesegs at gmail.com
Tue Jan 22 15:23:24 PST 2013
On Tue, Jan 22, 2013 at 3:17 PM, Galina Kistanova <gkistanova at gmail.com> wrote:
> clang-X86_64-freebsd:
>
> gcc 4.2.1 20070719 [FreeBSD]
> g++ 4.2.1. 20070719 [FreeBSD]
> ld 2.15 [FreeBSD] 2004-05-23
>
> clang-x86_64-darwin11-self-mingw32:
>
> i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build
> 5658) (LLVM build 2336.1.00)
>
> i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build
> i686-apple-darwin11-llvm-g++5658) (LLVM build 2336.1.00)
>
> llvm version 3.0svn, from Apple Clang 3.0 (build 211.9)
>
> Thanks
>
> Galina
Thanks, it should be fixed now.
- Michael Spencer
>
>
>
>
> On Tue, Jan 22, 2013 at 2:21 PM, Michael Spencer <bigcheesegs at gmail.com>
> wrote:
>>
>> On Tue, Jan 22, 2013 at 2:05 PM, Galina Kistanova <gkistanova at gmail.com>
>> wrote:
>> > Builder clang-x86_64-darwin11-self-mingw32 seems have issues with
>> > r172991
>> > also.
>> >
>> > The last successful build:
>> >
>> > http://lab.llvm.org:8011/builders/clang-x86_64-darwin11-self-mingw32/builds/8667
>> > r 172988
>> >
>> > the fist failed:
>> >
>> > http://lab.llvm.org:8011/builders/clang-x86_64-darwin11-self-mingw32/builds/8668
>> > r 172991
>> >
>> > Please let me know if you need more info from me.
>> >
>> > Thanks
>> >
>> > Galina
>> >
>> >
>> >
>> >
>> > On Tue, Jan 22, 2013 at 1:53 PM, Galina Kistanova <gkistanova at gmail.com>
>> > wrote:
>> >>
>> >> Hi Michael,
>> >>
>> >> Seems this revision broke clang-X86_64-freebsd build.
>> >>
>> >> The last successful build was for r 172988:
>> >> http://lab.llvm.org:8011/builders/clang-X86_64-freebsd/builds/6722
>> >>
>> >> The next builded revision was 172992 and it failed:
>> >> http://lab.llvm.org:8011/builders/clang-X86_64-freebsd/builds/6723
>> >>
>> >> Please have a look at this?
>> >> Let me know if you need more information on it.
>> >>
>> >> Thanks
>> >>
>> >> Galina
>>
>> Which compiler is in use on these two bots?
>>
>> - Michael Spencer
>>
>> >>
>> >>
>> >>
>> >>
>> >> On Sun, Jan 20, 2013 at 12:32 PM, Michael J. Spencer
>> >> <bigcheesegs at gmail.com> wrote:
>> >>>
>> >>> Author: mspencer
>> >>> Date: Sun Jan 20 14:32:30 2013
>> >>> New Revision: 172991
>> >>>
>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=172991&view=rev
>> >>> Log:
>> >>> [Support] Port ErrorOr<T> from lld to C++03.
>> >>>
>> >>> Added:
>> >>> llvm/trunk/include/llvm/Support/ErrorOr.h
>> >>> llvm/trunk/unittests/Support/ErrorOrTest.cpp
>> >>> Modified:
>> >>> llvm/trunk/include/llvm/Support/Compiler.h
>> >>> llvm/trunk/include/llvm/Support/type_traits.h
>> >>> llvm/trunk/unittests/Support/CMakeLists.txt
>> >>>
>> >>> Modified: llvm/trunk/include/llvm/Support/Compiler.h
>> >>> URL:
>> >>>
>> >>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Compiler.h?rev=172991&r1=172990&r2=172991&view=diff
>> >>>
>> >>>
>> >>> ==============================================================================
>> >>> --- llvm/trunk/include/llvm/Support/Compiler.h (original)
>> >>> +++ llvm/trunk/include/llvm/Support/Compiler.h Sun Jan 20 14:32:30
>> >>> 2013
>> >>> @@ -42,6 +42,33 @@
>> >>> #define LLVM_HAS_RVALUE_REFERENCE_THIS 0
>> >>> #endif
>> >>>
>> >>> +/// \macro LLVM_HAS_CXX11_TYPETRAITS
>> >>> +/// \brief Does the compiler have the C++11 type traits.
>> >>> +///
>> >>> +/// #include <type_traits>
>> >>> +///
>> >>> +/// * enable_if
>> >>> +/// * {true,false}_type
>> >>> +/// * is_constructible
>> >>> +/// * etc...
>> >>> +#if defined(__GXX_EXPERIMENTAL_CXX0X__) \
>> >>> + || (defined(_MSC_VER) && _MSC_VER >= 1600)
>> >>> +#define LLVM_HAS_CXX11_TYPETRAITS 1
>> >>> +#else
>> >>> +#define LLVM_HAS_CXX11_TYPETRAITS 0
>> >>> +#endif
>> >>> +
>> >>> +/// \macro LLVM_HAS_CXX11_STDLIB
>> >>> +/// \brief Does the compiler have the C++11 standard library.
>> >>> +///
>> >>> +/// Implies LLVM_HAS_RVALUE_REFERENCES, LLVM_HAS_CXX11_TYPETRAITS
>> >>> +#if defined(__GXX_EXPERIMENTAL_CXX0X__) \
>> >>> + || (defined(_MSC_VER) && _MSC_VER >= 1600)
>> >>> +#define LLVM_HAS_CXX11_STDLIB 1
>> >>> +#else
>> >>> +#define LLVM_HAS_CXX11_STDLIB 0
>> >>> +#endif
>> >>> +
>> >>> /// llvm_move - Expands to ::std::move if the compiler supports
>> >>> /// r-value references; otherwise, expands to the argument.
>> >>> #if LLVM_HAS_RVALUE_REFERENCES
>> >>>
>> >>> Added: llvm/trunk/include/llvm/Support/ErrorOr.h
>> >>> URL:
>> >>>
>> >>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ErrorOr.h?rev=172991&view=auto
>> >>>
>> >>>
>> >>> ==============================================================================
>> >>> --- llvm/trunk/include/llvm/Support/ErrorOr.h (added)
>> >>> +++ llvm/trunk/include/llvm/Support/ErrorOr.h Sun Jan 20 14:32:30 2013
>> >>> @@ -0,0 +1,342 @@
>> >>> +//===- llvm/Support/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.
>> >>> +///
>> >>>
>> >>>
>> >>> +//===----------------------------------------------------------------------===//
>> >>> +
>> >>> +#ifndef LLVM_SUPPORT_ERROR_OR_H
>> >>> +#define LLVM_SUPPORT_ERROR_OR_H
>> >>> +
>> >>> +#include "llvm/Support/AlignOf.h"
>> >>> +#include "llvm/Support/system_error.h"
>> >>> +#include "llvm/Support/type_traits.h"
>> >>> +
>> >>> +#include <cassert>
>> >>> +#if LLVM_HAS_CXX11_TYPETRAITS
>> >>> +#include <type_traits>
>> >>> +#endif
>> >>> +
>> >>> +namespace llvm {
>> >>> +struct ErrorHolderBase {
>> >>> + error_code Error;
>> >>> + uint16_t RefCount;
>> >>> + bool HasUserData;
>> >>> +
>> >>> + ErrorHolderBase() : RefCount(1) {}
>> >>> +
>> >>> + void aquire() {
>> >>> + ++RefCount;
>> >>> + }
>> >>> +
>> >>> + void release() {
>> >>> + if (--RefCount == 0)
>> >>> + delete this;
>> >>> + }
>> >>> +
>> >>> +protected:
>> >>> + virtual ~ErrorHolderBase() {}
>> >>> +};
>> >>> +
>> >>> +template<class T>
>> >>> +struct ErrorHolder : ErrorHolderBase {
>> >>> +#if LLVM_HAS_RVALUE_REFERENCES
>> >>> + ErrorHolder(T &&UD) : UserData(llvm_move(UD)) {}
>> >>> +#else
>> >>> + ErrorHolder(T &UD) : UserData(UD) {}
>> >>> +#endif
>> >>> + T UserData;
>> >>> +};
>> >>> +
>> >>> +template<class Tp> struct ErrorOrUserDataTraits : llvm::false_type
>> >>> {};
>> >>> +
>> >>> +#if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES
>> >>> +template<class T, class V>
>> >>> +typename std::enable_if< std::is_constructible<T, V>::value
>> >>> + , typename
>> >>> std::remove_reference<V>::type>::type
>> >>> &&
>> >>> + moveIfMoveConstructible(V &Val) {
>> >>> + return std::move(Val);
>> >>> +}
>> >>> +
>> >>> +template<class T, class V>
>> >>> +typename std::enable_if< !std::is_constructible<T, V>::value
>> >>> + , typename
>> >>> std::remove_reference<V>::type>::type
>> >>> &
>> >>> +moveIfMoveConstructible(V &Val) {
>> >>> + return Val;
>> >>> +}
>> >>> +#else
>> >>> +template<class T, class V>
>> >>> +V &moveIfMoveConstructible(V &Val) {
>> >>> + return Val;
>> >>> +}
>> >>> +#endif
>> >>> +
>> >>> +/// \brief Stores a reference that can be changed.
>> >>> +template <typename T>
>> >>> +class ReferenceStorage {
>> >>> + T *Storage;
>> >>> +
>> >>> +public:
>> >>> + ReferenceStorage(T &Ref) : Storage(&Ref) {}
>> >>> +
>> >>> + operator T &() const { return *Storage; }
>> >>> + T &get() const { return *Storage; }
>> >>> +};
>> >>> +
>> >>> +/// \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 llvm {
>> >>> +/// template<>
>> >>> +/// struct ErrorOrUserDataTraits<InvalidArgError> : std::true_type
>> >>> {
>> >>> +/// static error_code error() {
>> >>> +/// return make_error_code(errc::invalid_argument);
>> >>> +/// }
>> >>> +/// };
>> >>> +/// } // end namespace llvm
>> >>> +///
>> >>> +/// using namespace llvm;
>> >>> +///
>> >>> +/// 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 = is_reference<T>::value;
>> >>> + typedef ReferenceStorage<typename remove_reference<T>::type> wrap;
>> >>> +
>> >>> +public:
>> >>> + typedef typename
>> >>> + conditional< isRef
>> >>> + , wrap
>> >>> + , T
>> >>> + >::type storage_type;
>> >>> +
>> >>> +private:
>> >>> + typedef T &reference;
>> >>> + typedef typename 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
>> >>> + enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type*
>> >>> =
>> >>> 0)
>> >>> + : HasError(true), IsValid(true) {
>> >>> + Error = new ErrorHolder<UserDataT>(llvm_move(UD));
>> >>> + Error->Error = ErrorOrUserDataTraits<UserDataT>::error();
>> >>> + Error->HasUserData = true;
>> >>> + }
>> >>> +
>> >>> + ErrorOr(T Val) : HasError(false), IsValid(true) {
>> >>> + new (get())
>> >>> storage_type(moveIfMoveConstructible<storage_type>(Val));
>> >>> + }
>> >>> +
>> >>> + 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;
>> >>> +
>> >>> + this->~ErrorOr();
>> >>> + new (this) ErrorOr(Other);
>> >>> +
>> >>> + return *this;
>> >>> + }
>> >>> +
>> >>> +#if LLVM_HAS_RVALUE_REFERENCES
>> >>> + 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();
>> >>> + }
>> >>> +#endif
>> >>> +
>> >>> + 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 Val) {
>> >>> + return Val;
>> >>> + }
>> >>> +
>> >>> + pointer toPointer(wrap *Val) {
>> >>> + return &Val->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*>(TStorage.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*>(TStorage.buffer);
>> >>> + }
>> >>> +
>> >>> + union {
>> >>> + AlignedCharArrayUnion<storage_type> TStorage;
>> >>> + ErrorHolderBase *Error;
>> >>> + };
>> >>> + bool HasError : 1;
>> >>> + bool IsValid : 1;
>> >>> +};
>> >>> +
>> >>> +template<class T, class E>
>> >>> +typename enable_if_c<is_error_code_enum<E>::value ||
>> >>> + is_error_condition_enum<E>::value, bool>::type
>> >>> +operator ==(ErrorOr<T> &Err, E Code) {
>> >>> + return error_code(Err) == Code;
>> >>> +}
>> >>> +} // end namespace llvm
>> >>> +
>> >>> +#endif
>> >>>
>> >>> Modified: llvm/trunk/include/llvm/Support/type_traits.h
>> >>> URL:
>> >>>
>> >>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/type_traits.h?rev=172991&r1=172990&r2=172991&view=diff
>> >>>
>> >>>
>> >>> ==============================================================================
>> >>> --- llvm/trunk/include/llvm/Support/type_traits.h (original)
>> >>> +++ llvm/trunk/include/llvm/Support/type_traits.h Sun Jan 20 14:32:30
>> >>> 2013
>> >>> @@ -145,6 +145,10 @@
>> >>> template <typename T> struct is_pointer<T* volatile> : true_type {};
>> >>> template <typename T> struct is_pointer<T* const volatile> :
>> >>> true_type
>> >>> {};
>> >>>
>> >>> +/// \brief Metafunction that determines wheather the given type is a
>> >>> reference.
>> >>> +template <typename T> struct is_reference : false_type {};
>> >>> +template <typename T> struct is_reference<T&> : true_type {};
>> >>> +
>> >>> /// \brief Metafunction that determines whether the given type is
>> >>> either
>> >>> an
>> >>> /// integral type or an enumeration type.
>> >>> ///
>> >>>
>> >>> Modified: llvm/trunk/unittests/Support/CMakeLists.txt
>> >>> URL:
>> >>>
>> >>> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=172991&r1=172990&r2=172991&view=diff
>> >>>
>> >>>
>> >>> ==============================================================================
>> >>> --- llvm/trunk/unittests/Support/CMakeLists.txt (original)
>> >>> +++ llvm/trunk/unittests/Support/CMakeLists.txt Sun Jan 20 14:32:30
>> >>> 2013
>> >>> @@ -13,6 +13,7 @@
>> >>> ConstantRangeTest.cpp
>> >>> DataExtractorTest.cpp
>> >>> EndianTest.cpp
>> >>> + ErrorOrTest.cpp
>> >>> FileOutputBufferTest.cpp
>> >>> IntegersSubsetTest.cpp
>> >>> LeakDetectorTest.cpp
>> >>>
>> >>> Added: llvm/trunk/unittests/Support/ErrorOrTest.cpp
>> >>> URL:
>> >>>
>> >>> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ErrorOrTest.cpp?rev=172991&view=auto
>> >>>
>> >>>
>> >>> ==============================================================================
>> >>> --- llvm/trunk/unittests/Support/ErrorOrTest.cpp (added)
>> >>> +++ llvm/trunk/unittests/Support/ErrorOrTest.cpp Sun Jan 20 14:32:30
>> >>> 2013
>> >>> @@ -0,0 +1,78 @@
>> >>> +//===- 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 "llvm/Support/ErrorOr.h"
>> >>> +
>> >>> +#include "gtest/gtest.h"
>> >>> +
>> >>> +#include <memory>
>> >>> +
>> >>> +using namespace llvm;
>> >>> +
>> >>> +namespace {
>> >>> +
>> >>> +ErrorOr<int> t1() {return 1;}
>> >>> +ErrorOr<int> t2() {return make_error_code(errc::invalid_argument);}
>> >>> +
>> >>> +TEST(ErrorOr, SimpleValue) {
>> >>> + ErrorOr<int> 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");
>> >>> +}
>> >>> +
>> >>> +#if LLVM_HAS_CXX11_STDLIB
>> >>> +ErrorOr<std::unique_ptr<int> > t3() {
>> >>> + return std::unique_ptr<int>(new int(3));
>> >>> +}
>> >>> +#endif
>> >>> +
>> >>> +TEST(ErrorOr, Types) {
>> >>> + int x;
>> >>> + ErrorOr<int&> a(x);
>> >>> + *a = 42;
>> >>> + EXPECT_EQ(42, x);
>> >>> +
>> >>> +#if LLVM_HAS_CXX11_STDLIB
>> >>> + // Move only types.
>> >>> + EXPECT_EQ(3, **t3());
>> >>> +#endif
>> >>> +}
>> >>> +} // end anon namespace
>> >>> +
>> >>> +struct InvalidArgError {
>> >>> + InvalidArgError() {}
>> >>> + InvalidArgError(std::string S) : ArgName(S) {}
>> >>> + std::string ArgName;
>> >>> +};
>> >>> +
>> >>> +namespace llvm {
>> >>> +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) {
>> >>> + ErrorOr<int> a = t4();
>> >>> + EXPECT_EQ(errc::invalid_argument, a);
>> >>> + EXPECT_EQ("adena", t4().getError<InvalidArgError>().ArgName);
>> >>> +}
>> >>> +} // end anon namespace
>> >>>
>> >>>
>> >>> _______________________________________________
>> >>> llvm-commits mailing list
>> >>> llvm-commits at cs.uiuc.edu
>> >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>> >>
>> >>
>> >
>
>
More information about the llvm-commits
mailing list