Index: include/llvm/Support/Error.h =================================================================== --- include/llvm/Support/Error.h +++ include/llvm/Support/Error.h @@ -14,8 +14,9 @@ #ifndef LLVM_SUPPORT_ERROR_H #define LLVM_SUPPORT_ERROR_H -#include "llvm/ADT/SmallVector.h" +#include "llvm-c/Error.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/abi-breaking.h" @@ -1183,6 +1184,21 @@ std::function GetExitCode; }; +/// Conversion from Error to LLVMErrorRef for C error bindings. +inline LLVMErrorRef wrap(Error Err) { + std::unique_ptr EIB; + handleAllErrors(std::move(Err), [&EIB](std::unique_ptr EIB2) { + EIB = std::move(EIB2); + }); + return reinterpret_cast(EIB.release()); +} + +/// Conversion from LLVMErrorRef to Error for C error bindings. +inline Error unwrap(LLVMErrorRef ErrRef) { + return Error(std::unique_ptr( + reinterpret_cast(ErrRef))); +} + } // end namespace llvm #endif // LLVM_SUPPORT_ERROR_H Index: lib/Support/Error.cpp =================================================================== --- lib/Support/Error.cpp +++ lib/Support/Error.cpp @@ -126,6 +126,27 @@ report_fatal_error(ErrMsg); } +} // end namespace llvm + +LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) { + return const_cast( + reinterpret_cast(Err)->dynamicClassID()); +} + +void LLVMConsumeError(LLVMErrorRef Err) { consumeError(unwrap(Err)); } + +char *LLVMGetErrorMessage(LLVMErrorRef Err) { + std::string Tmp = toString(unwrap(Err)); + char *ErrMsg = new char[Tmp.size() + 1]; + memcpy(ErrMsg, Tmp.data(), Tmp.size()); + ErrMsg[Tmp.size()] = '\0'; + return ErrMsg; +} + +void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; } + +LLVMErrorTypeId LLVMGetStringErrorTypeId() { + return reinterpret_cast(&StringError::ID); } #ifndef _MSC_VER Index: unittests/Support/ErrorTest.cpp =================================================================== --- unittests/Support/ErrorTest.cpp +++ unittests/Support/ErrorTest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Error.h" +#include "llvm-c/Error.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Errc.h" @@ -832,4 +833,21 @@ " Actual: failed (CustomError {0})"); } +TEST(Error, C_API) { + EXPECT_THAT_ERROR(unwrap(wrap(Error::success())), Succeeded()) + << "Failed to round-trip Error success value via C API"; + EXPECT_THAT_ERROR(unwrap(wrap(make_error(0))), + Failed()) + << "Failed to round-trip Error failure value via C API"; + + auto Err = + wrap(make_error("test message", inconvertibleErrorCode())); + EXPECT_EQ(LLVMGetErrorTypeId(Err), LLVMGetStringErrorTypeId()) + << "Failed to match error type ids via C API"; + char *ErrMsg = LLVMGetErrorMessage(Err); + EXPECT_EQ(ErrMsg, "test message") + << "Failed to roundtrip StringError error message via C API"; + LLVMDisposeErrorMessage(ErrMsg); +} + } // end anon namespace