commit 0b5a1b30ca87d772d2e1b3d5ec519fdcebedc4d0
Author: Lang Hames <lhames@gmail.com>
Date:   Fri Jan 22 13:30:44 2016 -0800

    [lkh] Initial error checkin.

diff --git include/llvm/Support/TypedError.h include/llvm/Support/TypedError.h
new file mode 100644
index 0000000..05b1563
--- /dev/null
+++ include/llvm/Support/TypedError.h
@@ -0,0 +1,618 @@
+//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- 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 an API used to indicate fatal error conditions.  Non-fatal
+// errors (most of them) should be handled through LLVMContext.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TYPEDERROR_H
+#define LLVM_SUPPORT_TYPEDERROR_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+namespace llvm {
+
+class TypedError;
+class TypedErrorList;
+
+/// Base class for error info classes. Do not extend this directly: Extend
+/// the TypedErrorInfo template subclass instead.
+class TypedErrorInfoBase {
+public:
+  virtual ~TypedErrorInfoBase() {}
+
+  /// Print an error message to an output stream.
+  virtual void log(raw_ostream &OS) const = 0;
+
+  // Check whether this instance's class matches the given class ID.
+  virtual bool isClass(const void *const ClassID) const {
+    return ClassID == &ID;
+  }
+
+  // Check whether this instance is a subclass of the class identified by
+  // ClassID.
+  virtual bool isSameOrSubClass(const void *const ClassID) const {
+    return ClassID == &ID;
+  }
+
+  // Returns the class ID for this type.
+  static const void *classID() { return &ID; }
+
+private:
+  virtual void anchor();
+  static char ID;
+};
+
+/// Lightweight error class with error context and mandatory checking.
+///
+/// Instances of this class wrap a TypedErrorInfoBase pointer. Failure states
+/// are represented by setting the pointer to a TypedErrorInfoBase subclass
+/// instance containing information describing the failure. Success is
+/// represented by a null pointer value.
+///
+/// Instances of TypedError also contains a 'Checked' flag, which must be set
+/// before the destructor is called, otherwise the destructor will trigger a
+/// runtime error. This enforces at runtime the requirement that all TypedError
+/// instances be checked or returned to the caller.
+///
+/// There are two ways to set the checked flag, depending on what state the
+/// TypedError instance is in. For TypedError instances indicating success, it
+/// is sufficient to invoke the boolean conversion operator. E.g.:
+///
+///   TypedError foo(<...>);
+///
+///   if (auto E = foo(<...>))
+///     return E; // <- Return E if it is in the error state.
+///   // We have verified that E was in the success state. It can now be safely
+///   // destroyed.
+///
+/// A success value *can not* be dropped. For example, just calling 'foo(<...>)'
+/// without testing the return value will raise a runtime error, even if foo
+/// returns success.
+///
+/// For TypedError instances representing failure, you must use the either the
+/// catchTypedErrors or catchAllTypedErrors function with a typed handler. E.g.:
+///
+///   class MyErrorInfo : public TypedErrorInfo<MyErrorInfo> {
+///     // Custom error info.
+///   };
+///
+///   Error foo(<...>) { return make_typed_error<MyErrorInfo>(...); }
+///
+///   auto E = foo(<...>); // <- foo returns failure with MyErrorInfo.
+///   auto NewE =
+///     checkTypedErrors(E,
+///       handleTypedError<MyErrorInfo>([](MyErrorInfo &M) {
+///          // Deal with the error, then return 'TypedError()' from the
+///          // handler, indicating success.
+///          return TypedError();
+///       });
+///   // Note - we must check or return NewE in case any of the handlers
+///   // returned a new error.
+///
+/// The catchAllTypedErrors function is identical to catchTypedErrors, except
+/// that it has a void return type, and requires all errors to be handled and
+/// no new errors be returned. It prevents errors (assuming they can all be
+/// handled) from having to be bubbled all the way to the top-level.
+///
+/// *All* TypedError instances must be checked before destruction, even if
+/// they're moved-assigned or constructed from Success values that have already
+/// been checked. This enforces checking through all levels of the call stack.
+class TypedError {
+
+  // ErrorList needs to be able to yank ErrorInfo pointers out of this
+  // class to add to the error list.
+  friend class TypedErrorList;
+
+  // handle_payload needs to be able to reconstruct errors from unhandled
+  // payloads.
+  template <typename HandlerT>
+  friend TypedError handle_payload(std::unique_ptr<TypedErrorInfoBase> Payload,
+                                   HandlerT &Handler);
+
+  // catchTypedErrors needs to be able to set the Checked flag.
+  template <typename... HandlerTs>
+  friend TypedError catchTypedErrors(TypedError E, HandlerTs... Handlers);
+
+public:
+  /// Create a success value. This must still be checked before being
+  /// destructed.
+  TypedError() : Checked(false) {}
+
+  /// Create an error value. Prefer using the 'make_typed_error' function, but
+  /// this constructor can be useful when "re-throwing" errors from handlers.
+  TypedError(std::unique_ptr<TypedErrorInfoBase> Payload)
+      : Payload(std::move(Payload)), Checked(false) {}
+
+  /// Move-construct an error value. The newly constructed error is considered
+  /// unchecked, even if the source error had been checked. The original error
+  /// becomes a checked Success value, regardless of its original state.
+  TypedError(TypedError &&Other)
+      : Payload(std::move(Other.Payload)), Checked(false) {
+    Other.Checked = true;
+  }
+
+  /// Move-assign an error value. The current error must represent success, you
+  /// you cannot overwrite an unhandled error. The current error is then
+  /// considered unchecked. The source error becomes a checked success value,
+  /// regardless of its original state.
+  TypedError &operator=(TypedError &&Other) {
+    // Move assignment shouldn't drop an existing error.
+    if (Payload)
+      fail();
+    Payload = std::move(Other.Payload);
+    Checked = false;
+    Other.Checked = true;
+    return *this;
+  }
+
+  /// Destroy a TypedError. Fails with a call to std::terminate() if the error
+  /// is unchecked.
+  ~TypedError() {
+    if (!Checked)
+      fail();
+  }
+
+  /// Bool conversion. Returns true if this TypedError is in a failure state,
+  /// and false if it is in an accept state. If the error is in a Success state
+  /// it will be considered checked.
+  explicit operator bool() {
+    Checked = (Payload == nullptr);
+    return Payload != nullptr;
+  }
+
+  /// Check whether one typed error is a subclass of another.
+  template <typename ErrT> bool isA() {
+    return Payload->isSameOrSubClass(ErrT::classID());
+  }
+
+private:
+  void fail() { std::terminate(); }
+
+  std::unique_ptr<TypedErrorInfoBase> Payload;
+  bool Checked;
+};
+
+/// Make a TypedError instance representing failure using the given error info
+/// type.
+template <typename ErrT, typename... ArgTs>
+TypedError make_typed_error(ArgTs &&... Args) {
+  return TypedError(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
+}
+
+/// Concatenate errors. The resulting TypedError is unchecked, and contains the
+/// TypedErrorInfo(s), if any, contained in E1, followed by the
+/// TypedErrorInfo(s), if any, contained in E2.
+inline TypedError join_typed_error(TypedError E1, TypedError E2) {
+  if (!E1)
+    return E2;
+  if (!E2)
+    return E1;
+  return make_typed_error<TypedErrorList>(std::move(E1), std::move(E2));
+}
+
+/// Base class for user error types. Users should declare their error types
+/// like:
+///
+/// class MyError : public TypedErrorInfo<MyError> {
+///   ....
+/// };
+///
+/// This class provides an implementation of the TypedErrorInfoBase::kind
+/// method, which is used by the handle<ErrType> functions to find errors that
+/// they apply to.
+template <typename ThisErrT, typename ParentErrT = TypedErrorInfoBase>
+class TypedErrorInfo : public ParentErrT {
+public:
+  bool isClass(const void *const ClassID) const override {
+    return ClassID == &ID;
+  }
+
+  bool isSameOrSubClass(const void *ClassID) const override {
+    return ClassID == &ID || ParentErrT::isSameOrSubClass(ClassID);
+  }
+
+  static const void *classID() { return &ID; }
+
+private:
+  static char ID;
+};
+
+template <typename MyErrT, typename ParentErrT>
+char TypedErrorInfo<MyErrT, ParentErrT>::ID = 0;
+
+/// Special TypedErrorInfo subclass representing a list of TypedErrorInfos.
+/// Instances of this class are constructed by join_error.
+class TypedErrorList final : public TypedErrorInfo<TypedErrorList> {
+
+  // catchTypedErrors needs to be able to iterate the payload list of an
+  // ErrorList.
+  template <typename... HandlerTs>
+  friend TypedError catchTypedErrors(TypedError E, HandlerTs... Handlers);
+
+public:
+  TypedErrorList(TypedError &&E1, TypedError &&E2) {
+    E1.Checked = true;
+    E2.Checked = true;
+    appendPayloads(std::move(E1.Payload));
+    appendPayloads(std::move(E2.Payload));
+  }
+
+  void log(raw_ostream &OS) const override {
+    OS << "Multiple errors:\n";
+    for (auto &ErrPayload : Payloads) {
+      ErrPayload->log(OS);
+      OS << "\n";
+    }
+  }
+
+private:
+  void appendPayloads(std::unique_ptr<TypedErrorInfoBase> Payload) {
+    if (Payload->isClass(TypedErrorList::classID())) {
+      auto &ECompound = static_cast<TypedErrorList &>(*Payload);
+      for (auto &ECompoundImpl : ECompound.Payloads)
+        if (ECompoundImpl)
+          Payloads.push_back(std::move(ECompoundImpl));
+    } else if (Payload)
+      Payloads.push_back(std::move(Payload));
+  }
+
+  std::vector<std::unique_ptr<TypedErrorInfoBase>> Payloads;
+};
+
+/// Helper functor for the 'handle' function.
+template <typename ErrT, typename ErrHandlerT> class TypedErrorHandler {
+public:
+  typedef ErrT ErrorT;
+  TypedErrorHandler(ErrHandlerT ErrHandler)
+      : ErrHandler(std::move(ErrHandler)) {}
+  bool appliesTo(TypedErrorInfoBase &EI) const {
+    return EI.isSameOrSubClass(ErrT::classID());
+  }
+  TypedError operator()(std::unique_ptr<ErrT> Err) {
+    return ErrHandler(std::move(Err));
+  }
+
+private:
+  ErrHandlerT ErrHandler;
+};
+
+/// Returns a handler for all errors of type ErrT.
+/// To be used in checkError blocks:
+///
+/// class MyError : pubilc TypedErrorInfo<MyError> {};
+///
+/// auto E = foo(<...>); // <- foo may return a MyError.
+/// checkAllErrors(std::move(E),
+///   handle<MyError>([](std::unique_ptr<MyError> M) {
+///     ...
+///     return TypedError();
+///   }));
+template <typename ErrT, typename ErrHandlerT>
+TypedErrorHandler<ErrT, ErrHandlerT> handleTypedError(ErrHandlerT ErrHandler) {
+  return TypedErrorHandler<ErrT, ErrHandlerT>(std::move(ErrHandler));
+}
+
+// Pass the payload to the given handler if the error types match, otherwise
+// re-wrap the payload in a TypedError and return it.
+template <typename HandlerT>
+TypedError handle_payload(std::unique_ptr<TypedErrorInfoBase> Payload,
+                          HandlerT &Handler) {
+  if (Handler.appliesTo(*Payload)) {
+    std::unique_ptr<typename HandlerT::ErrorT> DowncastPayload(
+        static_cast<typename HandlerT::ErrorT *>(Payload.release()));
+    return Handler(std::move(DowncastPayload));
+  }
+  return TypedError(std::move(Payload));
+}
+
+// Pass the payload to the given handler if the error types match, otherwise
+// try the next handler.
+template <typename HandlerT, typename... HandlerTs>
+TypedError handle_payload(std::unique_ptr<TypedErrorInfoBase> Payload,
+                          HandlerT &Handler, HandlerTs &... Handlers) {
+  if (Handler.appliesTo(*Payload)) {
+    std::unique_ptr<typename HandlerT::ErrorT> DowncastPayload(
+        static_cast<typename HandlerT::ErrorT *>(Payload.release()));
+    return Handler(std::move(DowncastPayload));
+  }
+  return handle_payload(std::move(Payload), Handlers...);
+}
+
+/// Pass the TypedErrorInfo(s) contained in E to their respective handlers. Any
+/// unhandled errors (or Errors returned by handlers) are re-concatenated and
+/// returned.
+/// Because this function returns an error, its result must also be checked
+/// or returned. If you intend to catch all errors use catchAllTypedErrors
+/// (which returns void, and will std::terminate() on unhandled errors) instead.
+template <typename... HandlerTs>
+TypedError catchTypedErrors(TypedError E, HandlerTs... Handlers) {
+  if (!E)
+    return TypedError();
+
+  E.Checked = true;
+
+  if (E.Payload->isClass(TypedErrorList::classID())) {
+    std::unique_ptr<TypedErrorList> ErrList(
+        static_cast<TypedErrorList *>(E.Payload.release()));
+    std::vector<std::unique_ptr<TypedErrorInfoBase>> Payloads =
+        std::move(ErrList->Payloads);
+    ErrList->Payloads = std::vector<std::unique_ptr<TypedErrorInfoBase>>();
+
+    for (auto &Payload : Payloads)
+      if (auto E = handle_payload(std::move(Payload), Handlers...)) {
+        E.Checked = true;
+        ErrList->Payloads.push_back(std::move(E.Payload));
+      }
+
+    if (ErrList->Payloads.empty())
+      return TypedError();
+
+    return TypedError(std::move(ErrList));
+  }
+
+  return handle_payload(std::move(E.Payload), Handlers...);
+}
+
+/// Behaves the same as catchTypedErrors, except that it requires that all
+/// errors be handled by the given handlers. If any unhandled error remains
+/// after the handlers have run, std::terminate() will be called.
+template <typename... HandlerTs>
+void catchAllTypedErrors(TypedError E, HandlerTs... Handlers) {
+  if (auto F = catchTypedErrors(std::move(E), std::move(Handlers)...))
+    std::terminate();
+}
+
+/// Check that E is a non-error, then drop it.
+inline void catchAllTypedErrors(TypedError E) {
+  if (E)
+    std::terminate();
+}
+
+/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
+/// will be printed before the first one is logged. A newline will be printed
+/// after each error.
+///
+/// This is useful in the base level of your program to allow clean termination
+/// (allowing clean deallocation of resources, etc.), while reporting error
+/// information to the user.
+template <typename... HandlerTs>
+void logAllUnhandledTypedErrors(TypedError E, raw_ostream &OS,
+                                std::string ErrorBanner) {
+
+  // Helper class to log uncaught errors.
+  class LogUncaughtErrorsTo {
+  public:
+    typedef TypedErrorInfoBase ErrorT;
+    LogUncaughtErrorsTo(raw_ostream &OS) : OS(OS) {}
+    bool appliesTo(TypedErrorInfoBase &EI) const { return true; }
+    TypedError operator()(std::unique_ptr<TypedErrorInfoBase> EI) {
+      EI->log(OS);
+      return TypedError();
+    }
+
+  private:
+    raw_ostream &OS;
+  };
+
+  if (!E)
+    return;
+
+  OS << ErrorBanner;
+  catchAllTypedErrors(std::move(E), LogUncaughtErrorsTo(OS));
+}
+
+/// Consume a TypedError without doing anything. This method should be used
+/// only where an error can be considered a reasonable and expected return
+/// value.
+///
+/// Uses of this method are potentially indicative of design problems: If it's
+/// legitimate to do nothing while processing an "error", the error-producer
+/// might be more clearly refactored to return an Optional<T>.
+inline void consumeTypedError(TypedError Err) {
+  catchAllTypedErrors(
+      std::move(Err),
+      handleTypedError<TypedErrorInfoBase>([](
+          std::unique_ptr<TypedErrorInfoBase> TEI) { return TypedError(); }));
+}
+
+/// Tagged union holding either a T or a TypedError.
+///
+/// This class parallels ErrorOr, but replaces error_code with TypedError. Since
+/// TypedError cannot be copied, this clas replaces getError() with takeError().
+/// It also adds an bool errorIsA<ErrT>() method for testing the error class
+/// type.
+template <class T> class TypedErrorOr {
+  template <class OtherT> friend class TypedErrorOr;
+  static const bool isRef = std::is_reference<T>::value;
+  typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap;
+
+public:
+  typedef typename std::conditional<isRef, wrap, T>::type storage_type;
+
+private:
+  typedef typename std::remove_reference<T>::type &reference;
+  typedef const typename std::remove_reference<T>::type &const_reference;
+  typedef typename std::remove_reference<T>::type *pointer;
+  typedef const typename std::remove_reference<T>::type *const_pointer;
+
+public:
+  TypedErrorOr(TypedError Err) : HasError(true) {
+    new (getErrorStorage()) TypedError(std::move(Err));
+  }
+
+  template <typename OtherT>
+  TypedErrorOr(
+      OtherT &&Val,
+      typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+          nullptr)
+      : HasError(false) {
+    new (getStorage()) storage_type(std::move(Val));
+  }
+
+  TypedErrorOr(TypedErrorOr &&Other) { moveConstruct(std::move(Other)); }
+
+  template <class OtherT>
+  TypedErrorOr(
+      TypedErrorOr<OtherT> &&Other,
+      typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+          nullptr) {
+    moveConstruct(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 <class OtherT>
+  explicit TypedErrorOr(
+      TypedErrorOr<OtherT> &&Other,
+      typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
+          nullptr) {
+    moveConstruct(std::move(Other));
+  }
+
+  TypedErrorOr &operator=(TypedErrorOr &&Other) {
+    moveAssign(std::move(Other));
+    return *this;
+  }
+
+  ~TypedErrorOr() {
+    if (!HasError)
+      getStorage()->~storage_type();
+  }
+
+  /// \brief Return false if there is an error.
+  explicit operator bool() const { return !HasError; }
+
+  reference get() { return *getStorage(); }
+  const_reference get() const {
+    return const_cast<TypedErrorOr<T> *>(this)->get();
+  }
+
+  template <typename ErrT> bool errorIsA() const {
+    return HasError && getErrorStorage()->template isA<ErrT>();
+  }
+
+  TypedError takeError() {
+    return HasError ? std::move(*getErrorStorage()) : TypedError();
+  }
+
+  pointer operator->() { return toPointer(getStorage()); }
+
+  const_pointer operator->() const { return toPointer(getStorage()); }
+
+  reference operator*() { return *getStorage(); }
+
+  const_reference operator*() const { return *getStorage(); }
+
+private:
+  template <class T1>
+  static bool compareThisIfSameType(const T1 &a, const T1 &b) {
+    return &a == &b;
+  }
+
+  template <class T1, class T2>
+  static bool compareThisIfSameType(const T1 &a, const T2 &b) {
+    return false;
+  }
+
+  template <class OtherT> void moveConstruct(TypedErrorOr<OtherT> &&Other) {
+    if (!Other.HasError) {
+      // Get the other value.
+      HasError = false;
+      new (getStorage()) storage_type(std::move(*Other.getStorage()));
+    } else {
+      // Get other's error.
+      HasError = true;
+      new (getErrorStorage()) TypedError(Other.takeError());
+    }
+  }
+
+  template <class OtherT> void moveAssign(TypedErrorOr<OtherT> &&Other) {
+    if (compareThisIfSameType(*this, Other))
+      return;
+
+    this->~TypedErrorOr();
+    new (this) TypedErrorOr(std::move(Other));
+  }
+
+  pointer toPointer(pointer Val) { return Val; }
+
+  const_pointer toPointer(const_pointer Val) const { return Val; }
+
+  pointer toPointer(wrap *Val) { return &Val->get(); }
+
+  const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
+
+  storage_type *getStorage() {
+    assert(!HasError && "Cannot get value when an error exists!");
+    return reinterpret_cast<storage_type *>(TStorage.buffer);
+  }
+
+  const storage_type *getStorage() const {
+    assert(!HasError && "Cannot get value when an error exists!");
+    return reinterpret_cast<const storage_type *>(TStorage.buffer);
+  }
+
+  TypedError *getErrorStorage() {
+    assert(HasError && "Cannot get error when a value exists!");
+    return reinterpret_cast<TypedError *>(ErrorStorage.buffer);
+  }
+
+  union {
+    AlignedCharArrayUnion<storage_type> TStorage;
+    AlignedCharArrayUnion<TypedError> ErrorStorage;
+  };
+  bool HasError : 1;
+};
+
+template <class T, class E>
+typename std::enable_if<std::is_error_code_enum<E>::value ||
+                            std::is_error_condition_enum<E>::value,
+                        bool>::type
+operator==(const TypedErrorOr<T> &Err, E Code) {
+  return Err.getError() == Code;
+}
+
+/// This class wraps a std::error_code in a TypedError.
+///
+/// This is useful if you're writing an interface that returns a TypedError
+/// (or TypedErrorOr) and you want to call code that still returns
+/// std::error_codes.
+class ECError : public TypedErrorInfo<ECError> {
+public:
+  ECError() = default;
+  ECError(std::error_code EC) : EC(EC) {}
+  std::error_code getErrorCode() const { return EC; }
+  void log(raw_ostream &OS) const override { OS << EC.message() << "\n"; }
+
+protected:
+  std::error_code EC;
+};
+
+/// Helper for converting an ECError to a std::error_code.
+///
+/// This method requires that Err be an ECError, otherwise it will trigger a
+/// call to std::terminate(). If you need to
+inline std::error_code typedErrorToErrorCode(TypedError Err) {
+  std::error_code EC;
+  catchAllTypedErrors(std::move(Err), handleTypedError<ECError>(
+                                          [&](std::unique_ptr<ECError> ECE) {
+                                            EC = ECE->getErrorCode();
+                                            return TypedError();
+                                          }));
+  return EC;
+}
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_TYPEDERROR_H
diff --git lib/Support/ErrorHandling.cpp lib/Support/ErrorHandling.cpp
index 2808bd3..ffdc2df 100644
--- lib/Support/ErrorHandling.cpp
+++ lib/Support/ErrorHandling.cpp
@@ -24,6 +24,7 @@
 #include "llvm/Support/MutexGuard.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/Threading.h"
+#include "llvm/Support/TypedError.h"
 #include "llvm/Support/WindowsError.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
@@ -138,6 +139,8 @@ void LLVMResetFatalErrorHandler() {
   remove_fatal_error_handler();
 }
 
+void TypedErrorInfoBase::anchor() {}
+
 #ifdef LLVM_ON_WIN32
 
 #include <winerror.h>
