Move MSVC workarounds for future<Error>/future<Expected<T>> out of ORC and into
a header in support. MSVC's std::future implementation requires types to be default constructible, but Error and Expected are not. This issue came up once before in ORC's RPCUtils.h header and was worked around there but came up again in r342939, so I am moving the workaround to Support to make it available to other clients. llvm-svn: 343011
This commit is contained in:
parent
3da977be13
commit
721da4bd87
|
|
@ -207,73 +207,6 @@ private:
|
|||
|
||||
namespace detail {
|
||||
|
||||
// FIXME: Remove MSVCPError/MSVCPExpected once MSVC's future implementation
|
||||
// supports classes without default constructors.
|
||||
#ifdef _MSC_VER
|
||||
|
||||
namespace msvc_hacks {
|
||||
|
||||
// Work around MSVC's future implementation's use of default constructors:
|
||||
// A default constructed value in the promise will be overwritten when the
|
||||
// real error is set - so the default constructed Error has to be checked
|
||||
// already.
|
||||
class MSVCPError : public Error {
|
||||
public:
|
||||
MSVCPError() { (void)!!*this; }
|
||||
|
||||
MSVCPError(MSVCPError &&Other) : Error(std::move(Other)) {}
|
||||
|
||||
MSVCPError &operator=(MSVCPError Other) {
|
||||
Error::operator=(std::move(Other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
MSVCPError(Error Err) : Error(std::move(Err)) {}
|
||||
};
|
||||
|
||||
// Work around MSVC's future implementation, similar to MSVCPError.
|
||||
template <typename T> class MSVCPExpected : public Expected<T> {
|
||||
public:
|
||||
MSVCPExpected()
|
||||
: Expected<T>(make_error<StringError>("", inconvertibleErrorCode())) {
|
||||
consumeError(this->takeError());
|
||||
}
|
||||
|
||||
MSVCPExpected(MSVCPExpected &&Other) : Expected<T>(std::move(Other)) {}
|
||||
|
||||
MSVCPExpected &operator=(MSVCPExpected &&Other) {
|
||||
Expected<T>::operator=(std::move(Other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
MSVCPExpected(Error Err) : Expected<T>(std::move(Err)) {}
|
||||
|
||||
template <typename OtherT>
|
||||
MSVCPExpected(
|
||||
OtherT &&Val,
|
||||
typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
|
||||
nullptr)
|
||||
: Expected<T>(std::move(Val)) {}
|
||||
|
||||
template <class OtherT>
|
||||
MSVCPExpected(
|
||||
Expected<OtherT> &&Other,
|
||||
typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
|
||||
nullptr)
|
||||
: Expected<T>(std::move(Other)) {}
|
||||
|
||||
template <class OtherT>
|
||||
explicit MSVCPExpected(
|
||||
Expected<OtherT> &&Other,
|
||||
typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
|
||||
nullptr)
|
||||
: Expected<T>(std::move(Other)) {}
|
||||
};
|
||||
|
||||
} // end namespace msvc_hacks
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
/// Provides a typedef for a tuple containing the decayed argument types.
|
||||
template <typename T> class FunctionArgsTuple;
|
||||
|
||||
|
|
@ -293,10 +226,10 @@ public:
|
|||
|
||||
#ifdef _MSC_VER
|
||||
// The ErrorReturnType wrapped in a std::promise.
|
||||
using ReturnPromiseType = std::promise<msvc_hacks::MSVCPExpected<RetT>>;
|
||||
using ReturnPromiseType = std::promise<MSVCPExpected<RetT>>;
|
||||
|
||||
// The ErrorReturnType wrapped in a std::future.
|
||||
using ReturnFutureType = std::future<msvc_hacks::MSVCPExpected<RetT>>;
|
||||
using ReturnFutureType = std::future<MSVCPExpected<RetT>>;
|
||||
#else
|
||||
// The ErrorReturnType wrapped in a std::promise.
|
||||
using ReturnPromiseType = std::promise<ErrorReturnType>;
|
||||
|
|
@ -325,10 +258,10 @@ public:
|
|||
|
||||
#ifdef _MSC_VER
|
||||
// The ErrorReturnType wrapped in a std::promise.
|
||||
using ReturnPromiseType = std::promise<msvc_hacks::MSVCPError>;
|
||||
using ReturnPromiseType = std::promise<MSVCPError>;
|
||||
|
||||
// The ErrorReturnType wrapped in a std::future.
|
||||
using ReturnFutureType = std::future<msvc_hacks::MSVCPError>;
|
||||
using ReturnFutureType = std::future<MSVCPError>;
|
||||
#else
|
||||
// The ErrorReturnType wrapped in a std::promise.
|
||||
using ReturnPromiseType = std::promise<ErrorReturnType>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
//===--- MSVCErrorWorkarounds.h - Enable future<Error> in MSVC --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// MSVC's promise/future implementation requires types to be default
|
||||
// constructible, so this header provides analogues of Error an Expected
|
||||
// that are default constructed in a safely destructible state.
|
||||
//
|
||||
// FIXME: Kill off this header and migrate all users to Error/Expected once we
|
||||
// move to MSVC versions that support non-default-constructible types.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_MSVCERRORWORKAROUNDS_H
|
||||
#define LLVM_SUPPORT_MSVCERRORWORKAROUNDS_H
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
// A default-constructible llvm::Error that is suitable for use with MSVC's
|
||||
// std::future implementation which requires default constructible types.
|
||||
class MSVCPError : public Error {
|
||||
public:
|
||||
MSVCPError() { (void)!!*this; }
|
||||
|
||||
MSVCPError(MSVCPError &&Other) : Error(std::move(Other)) {}
|
||||
|
||||
MSVCPError &operator=(MSVCPError Other) {
|
||||
Error::operator=(std::move(Other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
MSVCPError(Error Err) : Error(std::move(Err)) {}
|
||||
};
|
||||
|
||||
// A default-constructible llvm::Expected that is suitable for use with MSVC's
|
||||
// std::future implementation, which requires default constructible types.
|
||||
template <typename T> class MSVCPExpected : public Expected<T> {
|
||||
public:
|
||||
MSVCPExpected()
|
||||
: Expected<T>(make_error<StringError>("", inconvertibleErrorCode())) {
|
||||
consumeError(this->takeError());
|
||||
}
|
||||
|
||||
MSVCPExpected(MSVCPExpected &&Other) : Expected<T>(std::move(Other)) {}
|
||||
|
||||
MSVCPExpected &operator=(MSVCPExpected &&Other) {
|
||||
Expected<T>::operator=(std::move(Other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
MSVCPExpected(Error Err) : Expected<T>(std::move(Err)) {}
|
||||
|
||||
template <typename OtherT>
|
||||
MSVCPExpected(
|
||||
OtherT &&Val,
|
||||
typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
|
||||
nullptr)
|
||||
: Expected<T>(std::move(Val)) {}
|
||||
|
||||
template <class OtherT>
|
||||
MSVCPExpected(
|
||||
Expected<OtherT> &&Other,
|
||||
typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
|
||||
nullptr)
|
||||
: Expected<T>(std::move(Other)) {}
|
||||
|
||||
template <class OtherT>
|
||||
explicit MSVCPExpected(
|
||||
Expected<OtherT> &&Other,
|
||||
typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
|
||||
nullptr)
|
||||
: Expected<T>(std::move(Other)) {}
|
||||
};
|
||||
|
||||
} // end namespace orc
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_SUPPORT_MSVCERRORWORKAROUNDS_H
|
||||
Loading…
Reference in New Issue