[llvm] r339802 - [Support] Add a basic C API for llvm::Error.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 15 11:42:12 PDT 2018


Author: lhames
Date: Wed Aug 15 11:42:11 2018
New Revision: 339802

URL: http://llvm.org/viewvc/llvm-project?rev=339802&view=rev
Log:
[Support] Add a basic C API for llvm::Error.

Summary:
The C-API supports consuming errors, converting an error to a string error
message, and querying an error's type. Other LLVM C APIs that wish to use
llvm::Error can supply error-type-id checkers and custom
error-to-structured-type converters for any custom errors they provide.

Reviewers: bogner, zturner, labath, dblaikie

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D50716

Added:
    llvm/trunk/include/llvm-c/Error.h
Modified:
    llvm/trunk/include/llvm/Support/Error.h
    llvm/trunk/lib/Support/Error.cpp
    llvm/trunk/unittests/Support/ErrorTest.cpp

Added: llvm/trunk/include/llvm-c/Error.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Error.h?rev=339802&view=auto
==============================================================================
--- llvm/trunk/include/llvm-c/Error.h (added)
+++ llvm/trunk/include/llvm-c/Error.h Wed Aug 15 11:42:11 2018
@@ -0,0 +1,65 @@
+/*===------- llvm-c/Error.h - llvm::Error class C Interface -------*- C -*-===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file defines the C interface to LLVM's Error class.                   *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_ERROR_H
+#define LLVM_C_ERROR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Opaque reference to an error instance. Null serves as the 'success' value.
+ */
+typedef struct LLVMOpaqueError *LLVMErrorRef;
+
+/**
+ * Error type identifier.
+ */
+typedef const void *LLVMErrorTypeId;
+
+/**
+ * Returns the type id for the given error instance, which must be a failure
+ * value (i.e. non-null).
+ */
+LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err);
+
+/**
+ * Dispose of the given error without handling it. This operation consumes the
+ * error, and the given LLVMErrorRef value is not usable once this call returns.
+ * Note: This method *only* needs to be called if the error is not being passed
+ * to some other consuming operation, e.g. LLVMGetErrorMessage.
+ */
+void LLVMConsumeError(LLVMErrorRef Err);
+
+/**
+ * Returns the given string's error message. This operation consumes the error,
+ * and the given LLVMErrorRef value is not usable once this call returns.
+ */
+char *LLVMGetErrorMessage(LLVMErrorRef Err);
+
+/**
+ * Dispose of the given error message.
+ */
+void LLVMDisposeErrorMessage(char *ErrMsg);
+
+/**
+ * Returns the type id for llvm StringError.
+ */
+LLVMErrorTypeId LLVMGetStringErrorTypeId();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Modified: llvm/trunk/include/llvm/Support/Error.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Error.h?rev=339802&r1=339801&r2=339802&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Error.h (original)
+++ llvm/trunk/include/llvm/Support/Error.h Wed Aug 15 11:42:11 2018
@@ -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"
@@ -167,6 +168,9 @@ class LLVM_NODISCARD Error {
   // error.
   template <typename T> friend class Expected;
 
+  // wrap needs to be able to steal the payload.
+  friend LLVMErrorRef wrap(Error);
+
 protected:
   /// Create a success value. Prefer using 'Error::success()' for readability
   Error() {
@@ -1183,6 +1187,17 @@ private:
   std::function<int(const Error &)> GetExitCode;
 };
 
+/// Conversion from Error to LLVMErrorRef for C error bindings.
+inline LLVMErrorRef wrap(Error Err) {
+  return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release());
+}
+
+/// Conversion from LLVMErrorRef to Error for C error bindings.
+inline Error unwrap(LLVMErrorRef ErrRef) {
+  return Error(std::unique_ptr<ErrorInfoBase>(
+      reinterpret_cast<ErrorInfoBase *>(ErrRef)));
+}
+
 } // end namespace llvm
 
 #endif // LLVM_SUPPORT_ERROR_H

Modified: llvm/trunk/lib/Support/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Error.cpp?rev=339802&r1=339801&r2=339802&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Error.cpp (original)
+++ llvm/trunk/lib/Support/Error.cpp Wed Aug 15 11:42:11 2018
@@ -126,6 +126,26 @@ void report_fatal_error(Error Err, bool
   report_fatal_error(ErrMsg);
 }
 
+} // end namespace llvm
+
+LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) {
+  return reinterpret_cast<ErrorInfoBase *>(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<void *>(&StringError::ID);
 }
 
 #ifndef _MSC_VER

Modified: llvm/trunk/unittests/Support/ErrorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ErrorTest.cpp?rev=339802&r1=339801&r2=339802&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/ErrorTest.cpp (original)
+++ llvm/trunk/unittests/Support/ErrorTest.cpp Wed Aug 15 11:42:11 2018
@@ -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,35 @@ TEST(Error, ErrorMatchers) {
       "  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<CustomError>(0))),
+                    Failed<CustomError>())
+      << "Failed to round-trip Error failure value via C API";
+
+  auto Err =
+      wrap(make_error<StringError>("test message", inconvertibleErrorCode()));
+  EXPECT_EQ(LLVMGetErrorTypeId(Err), LLVMGetStringErrorTypeId())
+      << "Failed to match error type ids via C API";
+  char *ErrMsg = LLVMGetErrorMessage(Err);
+  EXPECT_STREQ(ErrMsg, "test message")
+      << "Failed to roundtrip StringError error message via C API";
+  LLVMDisposeErrorMessage(ErrMsg);
+
+  bool GotCSE = false;
+  bool GotCE = false;
+  handleAllErrors(
+    unwrap(wrap(joinErrors(make_error<CustomSubError>(42, 7),
+                           make_error<CustomError>(42)))),
+    [&](CustomSubError &CSE) {
+      GotCSE = true;
+    },
+    [&](CustomError &CE) {
+      GotCE = true;
+    });
+  EXPECT_TRUE(GotCSE) << "Failed to round-trip ErrorList via C API";
+  EXPECT_TRUE(GotCE) << "Failed to round-trip ErrorList via C API";
+}
+
 } // end anon namespace




More information about the llvm-commits mailing list