[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
Galina Kistanova
gkistanova at gmail.com
Tue Jan 22 14:05:28 PST 2013
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
>
>
>
>
> 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
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130122/f23f5d0f/attachment.html>
More information about the llvm-commits
mailing list