[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 14:21:08 PST 2013
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