diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index 6f164805b5c..68ab94609c1 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -115,19 +115,19 @@ public: } template - ErrorOr(const ErrorOr &Other) { + ErrorOr( + const ErrorOr &Other, + typename std::enable_if::value>::type * = + nullptr) { copyConstruct(Other); } - ErrorOr &operator =(const ErrorOr &Other) { - copyAssign(Other); - return *this; - } - template - ErrorOr &operator =(const ErrorOr &Other) { - copyAssign(Other); - return *this; + explicit ErrorOr( + const ErrorOr &Other, + typename std::enable_if< + !std::is_convertible::value>::type * = nullptr) { + copyConstruct(Other); } ErrorOr(ErrorOr &&Other) { @@ -135,17 +135,29 @@ public: } template - ErrorOr(ErrorOr &&Other) { + ErrorOr( + ErrorOr &&Other, + typename std::enable_if::value>::type * = + nullptr) { moveConstruct(std::move(Other)); } - ErrorOr &operator =(ErrorOr &&Other) { - moveAssign(std::move(Other)); + // This might eventually need SFINAE but it's more complex than is_convertible + // & I'm too lazy to write it right now. + template + explicit ErrorOr( + ErrorOr &&Other, + typename std::enable_if::value>::type * = + nullptr) { + moveConstruct(std::move(Other)); + } + + ErrorOr &operator=(const ErrorOr &Other) { + copyAssign(Other); return *this; } - template - ErrorOr &operator =(ErrorOr &&Other) { + ErrorOr &operator=(ErrorOr &&Other) { moveAssign(std::move(Other)); return *this; } diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index d23ee590569..d9fef8be8e1 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -63,7 +63,8 @@ ErrorOr> object::createBinary(MemoryBufferRef Buffer, case sys::fs::file_magic::bitcode: return ObjectFile::createSymbolicFile(Buffer, Type, Context); case sys::fs::file_magic::macho_universal_binary: - return MachOUniversalBinary::create(Buffer); + return ErrorOr>( + MachOUniversalBinary::create(Buffer)); case sys::fs::file_magic::unknown: case sys::fs::file_magic::windows_resource: // Unrecognized object file format. diff --git a/lib/Object/SymbolicFile.cpp b/lib/Object/SymbolicFile.cpp index f8dd4b33a39..17624a307ec 100644 --- a/lib/Object/SymbolicFile.cpp +++ b/lib/Object/SymbolicFile.cpp @@ -33,7 +33,8 @@ ErrorOr> SymbolicFile::createSymbolicFile( switch (Type) { case sys::fs::file_magic::bitcode: if (Context) - return IRObjectFile::createIRObjectFile(Object, *Context); + return ErrorOr>( + IRObjectFile::createIRObjectFile(Object, *Context)); // Fallthrough case sys::fs::file_magic::unknown: case sys::fs::file_magic::archive: diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index d76e7d62421..82bbe090960 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -60,5 +60,36 @@ TEST(ErrorOr, Covariant) { ErrorOr > b1(ErrorOr >(nullptr)); b1 = ErrorOr >(nullptr); + + ErrorOr> b2(ErrorOr(nullptr)); + ErrorOr b3(nullptr); + ErrorOr> b4(b3); } + +// ErrorOr x(nullptr); +// ErrorOr> y = x; // invalid conversion +static_assert( + !std::is_convertible &, + ErrorOr>>::value, + "do not invoke explicit ctors in implicit conversion from lvalue"); + +// ErrorOr> y = ErrorOr(nullptr); // invalid +// // conversion +static_assert( + !std::is_convertible &&, + ErrorOr>>::value, + "do not invoke explicit ctors in implicit conversion from rvalue"); + +// ErrorOr x(nullptr); +// ErrorOr> y; +// y = x; // invalid conversion +static_assert(!std::is_assignable>, + const ErrorOr &>::value, + "do not invoke explicit ctors in assignment"); + +// ErrorOr> x; +// x = ErrorOr(nullptr); // invalid conversion +static_assert(!std::is_assignable>, + ErrorOr &&>::value, + "do not invoke explicit ctors in assignment"); } // end anon namespace