Error.h revision 303231
1303231Sdim//===----- llvm/Support/Error.h - Recoverable error handling ----*- C++ -*-===// 2303231Sdim// 3303231Sdim// The LLVM Compiler Infrastructure 4303231Sdim// 5303231Sdim// This file is distributed under the University of Illinois Open Source 6303231Sdim// License. See LICENSE.TXT for details. 7303231Sdim// 8303231Sdim//===----------------------------------------------------------------------===// 9303231Sdim// 10303231Sdim// This file defines an API used to report recoverable errors. 11303231Sdim// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14303231Sdim#ifndef LLVM_SUPPORT_ERROR_H 15303231Sdim#define LLVM_SUPPORT_ERROR_H 16303231Sdim 17303231Sdim#include "llvm/ADT/PointerIntPair.h" 18303231Sdim#include "llvm/ADT/STLExtras.h" 19303231Sdim#include "llvm/ADT/StringExtras.h" 20303231Sdim#include "llvm/ADT/Twine.h" 21303231Sdim#include "llvm/Support/Debug.h" 22303231Sdim#include "llvm/Support/ErrorOr.h" 23303231Sdim#include "llvm/Support/raw_ostream.h" 24303231Sdim#include <vector> 25303231Sdim 26303231Sdimnamespace llvm { 27303231Sdim 28303231Sdimclass Error; 29303231Sdimclass ErrorList; 30303231Sdim 31303231Sdim/// Base class for error info classes. Do not extend this directly: Extend 32303231Sdim/// the ErrorInfo template subclass instead. 33303231Sdimclass ErrorInfoBase { 34303231Sdimpublic: 35303231Sdim virtual ~ErrorInfoBase() {} 36303231Sdim 37303231Sdim /// Print an error message to an output stream. 38303231Sdim virtual void log(raw_ostream &OS) const = 0; 39303231Sdim 40303231Sdim /// Return the error message as a string. 41303231Sdim virtual std::string message() const { 42303231Sdim std::string Msg; 43303231Sdim raw_string_ostream OS(Msg); 44303231Sdim log(OS); 45303231Sdim return OS.str(); 46303231Sdim } 47303231Sdim 48303231Sdim /// Convert this error to a std::error_code. 49303231Sdim /// 50303231Sdim /// This is a temporary crutch to enable interaction with code still 51303231Sdim /// using std::error_code. It will be removed in the future. 52303231Sdim virtual std::error_code convertToErrorCode() const = 0; 53303231Sdim 54303231Sdim // Check whether this instance is a subclass of the class identified by 55303231Sdim // ClassID. 56303231Sdim virtual bool isA(const void *const ClassID) const { 57303231Sdim return ClassID == classID(); 58303231Sdim } 59303231Sdim 60303231Sdim // Check whether this instance is a subclass of ErrorInfoT. 61303231Sdim template <typename ErrorInfoT> bool isA() const { 62303231Sdim return isA(ErrorInfoT::classID()); 63303231Sdim } 64303231Sdim 65303231Sdim // Returns the class ID for this type. 66303231Sdim static const void *classID() { return &ID; } 67303231Sdim 68303231Sdimprivate: 69303231Sdim virtual void anchor(); 70303231Sdim static char ID; 71303231Sdim}; 72303231Sdim 73303231Sdim/// Lightweight error class with error context and mandatory checking. 74303231Sdim/// 75303231Sdim/// Instances of this class wrap a ErrorInfoBase pointer. Failure states 76303231Sdim/// are represented by setting the pointer to a ErrorInfoBase subclass 77303231Sdim/// instance containing information describing the failure. Success is 78303231Sdim/// represented by a null pointer value. 79303231Sdim/// 80303231Sdim/// Instances of Error also contains a 'Checked' flag, which must be set 81303231Sdim/// before the destructor is called, otherwise the destructor will trigger a 82303231Sdim/// runtime error. This enforces at runtime the requirement that all Error 83303231Sdim/// instances be checked or returned to the caller. 84303231Sdim/// 85303231Sdim/// There are two ways to set the checked flag, depending on what state the 86303231Sdim/// Error instance is in. For Error instances indicating success, it 87303231Sdim/// is sufficient to invoke the boolean conversion operator. E.g.: 88303231Sdim/// 89303231Sdim/// Error foo(<...>); 90303231Sdim/// 91303231Sdim/// if (auto E = foo(<...>)) 92303231Sdim/// return E; // <- Return E if it is in the error state. 93303231Sdim/// // We have verified that E was in the success state. It can now be safely 94303231Sdim/// // destroyed. 95303231Sdim/// 96303231Sdim/// A success value *can not* be dropped. For example, just calling 'foo(<...>)' 97303231Sdim/// without testing the return value will raise a runtime error, even if foo 98303231Sdim/// returns success. 99303231Sdim/// 100303231Sdim/// For Error instances representing failure, you must use either the 101303231Sdim/// handleErrors or handleAllErrors function with a typed handler. E.g.: 102303231Sdim/// 103303231Sdim/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { 104303231Sdim/// // Custom error info. 105303231Sdim/// }; 106303231Sdim/// 107303231Sdim/// Error foo(<...>) { return make_error<MyErrorInfo>(...); } 108303231Sdim/// 109303231Sdim/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. 110303231Sdim/// auto NewE = 111303231Sdim/// handleErrors(E, 112303231Sdim/// [](const MyErrorInfo &M) { 113303231Sdim/// // Deal with the error. 114303231Sdim/// }, 115303231Sdim/// [](std::unique_ptr<OtherError> M) -> Error { 116303231Sdim/// if (canHandle(*M)) { 117303231Sdim/// // handle error. 118303231Sdim/// return Error::success(); 119303231Sdim/// } 120303231Sdim/// // Couldn't handle this error instance. Pass it up the stack. 121303231Sdim/// return Error(std::move(M)); 122303231Sdim/// ); 123303231Sdim/// // Note - we must check or return NewE in case any of the handlers 124303231Sdim/// // returned a new error. 125303231Sdim/// 126303231Sdim/// The handleAllErrors function is identical to handleErrors, except 127303231Sdim/// that it has a void return type, and requires all errors to be handled and 128303231Sdim/// no new errors be returned. It prevents errors (assuming they can all be 129303231Sdim/// handled) from having to be bubbled all the way to the top-level. 130303231Sdim/// 131303231Sdim/// *All* Error instances must be checked before destruction, even if 132303231Sdim/// they're moved-assigned or constructed from Success values that have already 133303231Sdim/// been checked. This enforces checking through all levels of the call stack. 134303231Sdimclass Error { 135303231Sdim 136303231Sdim // ErrorList needs to be able to yank ErrorInfoBase pointers out of this 137303231Sdim // class to add to the error list. 138303231Sdim friend class ErrorList; 139303231Sdim 140303231Sdim // handleErrors needs to be able to set the Checked flag. 141303231Sdim template <typename... HandlerTs> 142303231Sdim friend Error handleErrors(Error E, HandlerTs &&... Handlers); 143303231Sdim 144303231Sdim // Expected<T> needs to be able to steal the payload when constructed from an 145303231Sdim // error. 146303231Sdim template <typename T> class Expected; 147303231Sdim 148303231Sdimpublic: 149303231Sdim /// Create a success value. Prefer using 'Error::success()' for readability 150303231Sdim /// where possible. 151303231Sdim Error() { 152303231Sdim setPtr(nullptr); 153303231Sdim setChecked(false); 154303231Sdim } 155303231Sdim 156303231Sdim /// Create a success value. This is equivalent to calling the default 157303231Sdim /// constructor, but should be preferred for readability where possible. 158303231Sdim static Error success() { return Error(); } 159303231Sdim 160303231Sdim // Errors are not copy-constructable. 161303231Sdim Error(const Error &Other) = delete; 162303231Sdim 163303231Sdim /// Move-construct an error value. The newly constructed error is considered 164303231Sdim /// unchecked, even if the source error had been checked. The original error 165303231Sdim /// becomes a checked Success value, regardless of its original state. 166303231Sdim Error(Error &&Other) { 167303231Sdim setChecked(true); 168303231Sdim *this = std::move(Other); 169303231Sdim } 170303231Sdim 171303231Sdim /// Create an error value. Prefer using the 'make_error' function, but 172303231Sdim /// this constructor can be useful when "re-throwing" errors from handlers. 173303231Sdim Error(std::unique_ptr<ErrorInfoBase> Payload) { 174303231Sdim setPtr(Payload.release()); 175303231Sdim setChecked(false); 176303231Sdim } 177303231Sdim 178303231Sdim // Errors are not copy-assignable. 179303231Sdim Error &operator=(const Error &Other) = delete; 180303231Sdim 181303231Sdim /// Move-assign an error value. The current error must represent success, you 182303231Sdim /// you cannot overwrite an unhandled error. The current error is then 183303231Sdim /// considered unchecked. The source error becomes a checked success value, 184303231Sdim /// regardless of its original state. 185303231Sdim Error &operator=(Error &&Other) { 186303231Sdim // Don't allow overwriting of unchecked values. 187303231Sdim assertIsChecked(); 188303231Sdim setPtr(Other.getPtr()); 189303231Sdim 190303231Sdim // This Error is unchecked, even if the source error was checked. 191303231Sdim setChecked(false); 192303231Sdim 193303231Sdim // Null out Other's payload and set its checked bit. 194303231Sdim Other.setPtr(nullptr); 195303231Sdim Other.setChecked(true); 196303231Sdim 197303231Sdim return *this; 198303231Sdim } 199303231Sdim 200303231Sdim /// Destroy a Error. Fails with a call to abort() if the error is 201303231Sdim /// unchecked. 202303231Sdim ~Error() { 203303231Sdim assertIsChecked(); 204303231Sdim delete getPtr(); 205303231Sdim } 206303231Sdim 207303231Sdim /// Bool conversion. Returns true if this Error is in a failure state, 208303231Sdim /// and false if it is in an accept state. If the error is in a Success state 209303231Sdim /// it will be considered checked. 210303231Sdim explicit operator bool() { 211303231Sdim setChecked(getPtr() == nullptr); 212303231Sdim return getPtr() != nullptr; 213303231Sdim } 214303231Sdim 215303231Sdim /// Check whether one error is a subclass of another. 216303231Sdim template <typename ErrT> bool isA() const { 217303231Sdim return getPtr() && getPtr()->isA(ErrT::classID()); 218303231Sdim } 219303231Sdim 220303231Sdimprivate: 221303231Sdim void assertIsChecked() { 222303231Sdim#ifndef NDEBUG 223303231Sdim if (!getChecked() || getPtr()) { 224303231Sdim dbgs() << "Program aborted due to an unhandled Error:\n"; 225303231Sdim if (getPtr()) 226303231Sdim getPtr()->log(dbgs()); 227303231Sdim else 228303231Sdim dbgs() 229303231Sdim << "Error value was Success. (Note: Success values must still be " 230303231Sdim "checked prior to being destroyed).\n"; 231303231Sdim abort(); 232303231Sdim } 233303231Sdim#endif 234303231Sdim } 235303231Sdim 236303231Sdim ErrorInfoBase *getPtr() const { 237303231Sdim#ifndef NDEBUG 238303231Sdim return PayloadAndCheckedBit.getPointer(); 239303231Sdim#else 240303231Sdim return Payload; 241303231Sdim#endif 242303231Sdim } 243303231Sdim 244303231Sdim void setPtr(ErrorInfoBase *EI) { 245303231Sdim#ifndef NDEBUG 246303231Sdim PayloadAndCheckedBit.setPointer(EI); 247303231Sdim#else 248303231Sdim Payload = EI; 249303231Sdim#endif 250303231Sdim } 251303231Sdim 252303231Sdim bool getChecked() const { 253303231Sdim#ifndef NDEBUG 254303231Sdim return PayloadAndCheckedBit.getInt(); 255303231Sdim#else 256303231Sdim return true; 257303231Sdim#endif 258303231Sdim } 259303231Sdim 260303231Sdim void setChecked(bool V) { 261303231Sdim#ifndef NDEBUG 262303231Sdim PayloadAndCheckedBit.setInt(V); 263303231Sdim#endif 264303231Sdim } 265303231Sdim 266303231Sdim std::unique_ptr<ErrorInfoBase> takePayload() { 267303231Sdim std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); 268303231Sdim setPtr(nullptr); 269303231Sdim setChecked(true); 270303231Sdim return Tmp; 271303231Sdim } 272303231Sdim 273303231Sdim#ifndef NDEBUG 274303231Sdim PointerIntPair<ErrorInfoBase *, 1> PayloadAndCheckedBit; 275303231Sdim#else 276303231Sdim ErrorInfoBase *Payload; 277303231Sdim#endif 278303231Sdim}; 279303231Sdim 280303231Sdim/// Make a Error instance representing failure using the given error info 281303231Sdim/// type. 282303231Sdimtemplate <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { 283303231Sdim return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); 284303231Sdim} 285303231Sdim 286303231Sdim/// Base class for user error types. Users should declare their error types 287303231Sdim/// like: 288303231Sdim/// 289303231Sdim/// class MyError : public ErrorInfo<MyError> { 290303231Sdim/// .... 291303231Sdim/// }; 292303231Sdim/// 293303231Sdim/// This class provides an implementation of the ErrorInfoBase::kind 294303231Sdim/// method, which is used by the Error RTTI system. 295303231Sdimtemplate <typename ThisErrT, typename ParentErrT = ErrorInfoBase> 296303231Sdimclass ErrorInfo : public ParentErrT { 297303231Sdimpublic: 298303231Sdim bool isA(const void *const ClassID) const override { 299303231Sdim return ClassID == classID() || ParentErrT::isA(ClassID); 300303231Sdim } 301303231Sdim 302303231Sdim static const void *classID() { return &ThisErrT::ID; } 303303231Sdim}; 304303231Sdim 305303231Sdim/// Special ErrorInfo subclass representing a list of ErrorInfos. 306303231Sdim/// Instances of this class are constructed by joinError. 307303231Sdimclass ErrorList final : public ErrorInfo<ErrorList> { 308303231Sdim 309303231Sdim // handleErrors needs to be able to iterate the payload list of an 310303231Sdim // ErrorList. 311303231Sdim template <typename... HandlerTs> 312303231Sdim friend Error handleErrors(Error E, HandlerTs &&... Handlers); 313303231Sdim 314303231Sdim // joinErrors is implemented in terms of join. 315303231Sdim friend Error joinErrors(Error, Error); 316303231Sdim 317303231Sdimpublic: 318303231Sdim void log(raw_ostream &OS) const override { 319303231Sdim OS << "Multiple errors:\n"; 320303231Sdim for (auto &ErrPayload : Payloads) { 321303231Sdim ErrPayload->log(OS); 322303231Sdim OS << "\n"; 323303231Sdim } 324303231Sdim } 325303231Sdim 326303231Sdim std::error_code convertToErrorCode() const override; 327303231Sdim 328303231Sdim // Used by ErrorInfo::classID. 329303231Sdim static char ID; 330303231Sdim 331303231Sdimprivate: 332303231Sdim ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, 333303231Sdim std::unique_ptr<ErrorInfoBase> Payload2) { 334303231Sdim assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && 335303231Sdim "ErrorList constructor payloads should be singleton errors"); 336303231Sdim Payloads.push_back(std::move(Payload1)); 337303231Sdim Payloads.push_back(std::move(Payload2)); 338303231Sdim } 339303231Sdim 340303231Sdim static Error join(Error E1, Error E2) { 341303231Sdim if (!E1) 342303231Sdim return E2; 343303231Sdim if (!E2) 344303231Sdim return E1; 345303231Sdim if (E1.isA<ErrorList>()) { 346303231Sdim auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); 347303231Sdim if (E2.isA<ErrorList>()) { 348303231Sdim auto E2Payload = E2.takePayload(); 349303231Sdim auto &E2List = static_cast<ErrorList &>(*E2Payload); 350303231Sdim for (auto &Payload : E2List.Payloads) 351303231Sdim E1List.Payloads.push_back(std::move(Payload)); 352303231Sdim } else 353303231Sdim E1List.Payloads.push_back(E2.takePayload()); 354303231Sdim 355303231Sdim return E1; 356303231Sdim } 357303231Sdim if (E2.isA<ErrorList>()) { 358303231Sdim auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); 359303231Sdim E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); 360303231Sdim return E2; 361303231Sdim } 362303231Sdim return Error(std::unique_ptr<ErrorList>( 363303231Sdim new ErrorList(E1.takePayload(), E2.takePayload()))); 364303231Sdim } 365303231Sdim 366303231Sdim std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; 367303231Sdim}; 368303231Sdim 369303231Sdim/// Concatenate errors. The resulting Error is unchecked, and contains the 370303231Sdim/// ErrorInfo(s), if any, contained in E1, followed by the 371303231Sdim/// ErrorInfo(s), if any, contained in E2. 372303231Sdiminline Error joinErrors(Error E1, Error E2) { 373303231Sdim return ErrorList::join(std::move(E1), std::move(E2)); 374303231Sdim} 375303231Sdim 376303231Sdim/// Helper for testing applicability of, and applying, handlers for 377303231Sdim/// ErrorInfo types. 378303231Sdimtemplate <typename HandlerT> 379303231Sdimclass ErrorHandlerTraits 380303231Sdim : public ErrorHandlerTraits<decltype( 381303231Sdim &std::remove_reference<HandlerT>::type::operator())> {}; 382303231Sdim 383303231Sdim// Specialization functions of the form 'Error (const ErrT&)'. 384303231Sdimtemplate <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { 385303231Sdimpublic: 386303231Sdim static bool appliesTo(const ErrorInfoBase &E) { 387303231Sdim return E.template isA<ErrT>(); 388303231Sdim } 389303231Sdim 390303231Sdim template <typename HandlerT> 391303231Sdim static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { 392303231Sdim assert(appliesTo(*E) && "Applying incorrect handler"); 393303231Sdim return H(static_cast<ErrT &>(*E)); 394303231Sdim } 395303231Sdim}; 396303231Sdim 397303231Sdim// Specialization functions of the form 'void (const ErrT&)'. 398303231Sdimtemplate <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { 399303231Sdimpublic: 400303231Sdim static bool appliesTo(const ErrorInfoBase &E) { 401303231Sdim return E.template isA<ErrT>(); 402303231Sdim } 403303231Sdim 404303231Sdim template <typename HandlerT> 405303231Sdim static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { 406303231Sdim assert(appliesTo(*E) && "Applying incorrect handler"); 407303231Sdim H(static_cast<ErrT &>(*E)); 408303231Sdim return Error::success(); 409303231Sdim } 410303231Sdim}; 411303231Sdim 412303231Sdim/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. 413303231Sdimtemplate <typename ErrT> 414303231Sdimclass ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { 415303231Sdimpublic: 416303231Sdim static bool appliesTo(const ErrorInfoBase &E) { 417303231Sdim return E.template isA<ErrT>(); 418303231Sdim } 419303231Sdim 420303231Sdim template <typename HandlerT> 421303231Sdim static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { 422303231Sdim assert(appliesTo(*E) && "Applying incorrect handler"); 423303231Sdim std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); 424303231Sdim return H(std::move(SubE)); 425303231Sdim } 426303231Sdim}; 427303231Sdim 428303231Sdim/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. 429303231Sdimtemplate <typename ErrT> 430303231Sdimclass ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { 431303231Sdimpublic: 432303231Sdim static bool appliesTo(const ErrorInfoBase &E) { 433303231Sdim return E.template isA<ErrT>(); 434303231Sdim } 435303231Sdim 436303231Sdim template <typename HandlerT> 437303231Sdim static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { 438303231Sdim assert(appliesTo(*E) && "Applying incorrect handler"); 439303231Sdim std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); 440303231Sdim H(std::move(SubE)); 441303231Sdim return Error::success(); 442303231Sdim } 443303231Sdim}; 444303231Sdim 445303231Sdim// Specialization for member functions of the form 'RetT (const ErrT&)'. 446303231Sdimtemplate <typename C, typename RetT, typename ErrT> 447303231Sdimclass ErrorHandlerTraits<RetT (C::*)(ErrT &)> 448303231Sdim : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; 449303231Sdim 450303231Sdim// Specialization for member functions of the form 'RetT (const ErrT&) const'. 451303231Sdimtemplate <typename C, typename RetT, typename ErrT> 452303231Sdimclass ErrorHandlerTraits<RetT (C::*)(ErrT &) const> 453303231Sdim : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; 454303231Sdim 455303231Sdim// Specialization for member functions of the form 'RetT (const ErrT&)'. 456303231Sdimtemplate <typename C, typename RetT, typename ErrT> 457303231Sdimclass ErrorHandlerTraits<RetT (C::*)(const ErrT &)> 458303231Sdim : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; 459303231Sdim 460303231Sdim// Specialization for member functions of the form 'RetT (const ErrT&) const'. 461303231Sdimtemplate <typename C, typename RetT, typename ErrT> 462303231Sdimclass ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> 463303231Sdim : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; 464303231Sdim 465303231Sdim/// Specialization for member functions of the form 466303231Sdim/// 'RetT (std::unique_ptr<ErrT>) const'. 467303231Sdimtemplate <typename C, typename RetT, typename ErrT> 468303231Sdimclass ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> 469303231Sdim : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; 470303231Sdim 471303231Sdim/// Specialization for member functions of the form 472303231Sdim/// 'RetT (std::unique_ptr<ErrT>) const'. 473303231Sdimtemplate <typename C, typename RetT, typename ErrT> 474303231Sdimclass ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> 475303231Sdim : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; 476303231Sdim 477303231Sdiminline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { 478303231Sdim return Error(std::move(Payload)); 479303231Sdim} 480303231Sdim 481303231Sdimtemplate <typename HandlerT, typename... HandlerTs> 482303231SdimError handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, 483303231Sdim HandlerT &&Handler, HandlerTs &&... Handlers) { 484303231Sdim if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) 485303231Sdim return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), 486303231Sdim std::move(Payload)); 487303231Sdim return handleErrorImpl(std::move(Payload), 488303231Sdim std::forward<HandlerTs>(Handlers)...); 489303231Sdim} 490303231Sdim 491303231Sdim/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any 492303231Sdim/// unhandled errors (or Errors returned by handlers) are re-concatenated and 493303231Sdim/// returned. 494303231Sdim/// Because this function returns an error, its result must also be checked 495303231Sdim/// or returned. If you intend to handle all errors use handleAllErrors 496303231Sdim/// (which returns void, and will abort() on unhandled errors) instead. 497303231Sdimtemplate <typename... HandlerTs> 498303231SdimError handleErrors(Error E, HandlerTs &&... Hs) { 499303231Sdim if (!E) 500303231Sdim return Error::success(); 501303231Sdim 502303231Sdim std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); 503303231Sdim 504303231Sdim if (Payload->isA<ErrorList>()) { 505303231Sdim ErrorList &List = static_cast<ErrorList &>(*Payload); 506303231Sdim Error R; 507303231Sdim for (auto &P : List.Payloads) 508303231Sdim R = ErrorList::join( 509303231Sdim std::move(R), 510303231Sdim handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); 511303231Sdim return R; 512303231Sdim } 513303231Sdim 514303231Sdim return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); 515303231Sdim} 516303231Sdim 517303231Sdim/// Behaves the same as handleErrors, except that it requires that all 518303231Sdim/// errors be handled by the given handlers. If any unhandled error remains 519303231Sdim/// after the handlers have run, abort() will be called. 520303231Sdimtemplate <typename... HandlerTs> 521303231Sdimvoid handleAllErrors(Error E, HandlerTs &&... Handlers) { 522303231Sdim auto F = handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...); 523303231Sdim // Cast 'F' to bool to set the 'Checked' flag if it's a success value: 524303231Sdim (void)!F; 525303231Sdim} 526303231Sdim 527303231Sdim/// Check that E is a non-error, then drop it. 528303231Sdiminline void handleAllErrors(Error E) { 529303231Sdim // Cast 'E' to a bool to set the 'Checked' flag if it's a success value: 530303231Sdim (void)!E; 531303231Sdim} 532303231Sdim 533303231Sdim/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner 534303231Sdim/// will be printed before the first one is logged. A newline will be printed 535303231Sdim/// after each error. 536303231Sdim/// 537303231Sdim/// This is useful in the base level of your program to allow clean termination 538303231Sdim/// (allowing clean deallocation of resources, etc.), while reporting error 539303231Sdim/// information to the user. 540303231Sdimvoid logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); 541303231Sdim 542303231Sdim/// Write all error messages (if any) in E to a string. The newline character 543303231Sdim/// is used to separate error messages. 544303231Sdiminline std::string toString(Error E) { 545303231Sdim SmallVector<std::string, 2> Errors; 546303231Sdim handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { 547303231Sdim Errors.push_back(EI.message()); 548303231Sdim }); 549303231Sdim return join(Errors.begin(), Errors.end(), "\n"); 550303231Sdim} 551303231Sdim 552303231Sdim/// Consume a Error without doing anything. This method should be used 553303231Sdim/// only where an error can be considered a reasonable and expected return 554303231Sdim/// value. 555303231Sdim/// 556303231Sdim/// Uses of this method are potentially indicative of design problems: If it's 557303231Sdim/// legitimate to do nothing while processing an "error", the error-producer 558303231Sdim/// might be more clearly refactored to return an Optional<T>. 559303231Sdiminline void consumeError(Error Err) { 560303231Sdim handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); 561303231Sdim} 562303231Sdim 563303231Sdim/// Helper for Errors used as out-parameters. 564303231Sdim/// 565303231Sdim/// This helper is for use with the Error-as-out-parameter idiom, where an error 566303231Sdim/// is passed to a function or method by reference, rather than being returned. 567303231Sdim/// In such cases it is helpful to set the checked bit on entry to the function 568303231Sdim/// so that the error can be written to (unchecked Errors abort on assignment) 569303231Sdim/// and clear the checked bit on exit so that clients cannot accidentally forget 570303231Sdim/// to check the result. This helper performs these actions automatically using 571303231Sdim/// RAII: 572303231Sdim/// 573303231Sdim/// Result foo(Error &Err) { 574303231Sdim/// ErrorAsOutParameter ErrAsOutParam(Err); // 'Checked' flag set 575303231Sdim/// // <body of foo> 576303231Sdim/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. 577303231Sdim/// } 578303231Sdimclass ErrorAsOutParameter { 579303231Sdimpublic: 580303231Sdim ErrorAsOutParameter(Error &Err) : Err(Err) { 581303231Sdim // Raise the checked bit if Err is success. 582303231Sdim (void)!!Err; 583303231Sdim } 584303231Sdim ~ErrorAsOutParameter() { 585303231Sdim // Clear the checked bit. 586303231Sdim if (!Err) 587303231Sdim Err = Error::success(); 588303231Sdim } 589303231Sdim 590303231Sdimprivate: 591303231Sdim Error &Err; 592303231Sdim}; 593303231Sdim 594303231Sdim/// Tagged union holding either a T or a Error. 595303231Sdim/// 596303231Sdim/// This class parallels ErrorOr, but replaces error_code with Error. Since 597303231Sdim/// Error cannot be copied, this class replaces getError() with 598303231Sdim/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the 599303231Sdim/// error class type. 600303231Sdimtemplate <class T> class Expected { 601303231Sdim template <class OtherT> friend class Expected; 602303231Sdim static const bool isRef = std::is_reference<T>::value; 603303231Sdim typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap; 604303231Sdim 605303231Sdim typedef std::unique_ptr<ErrorInfoBase> error_type; 606303231Sdim 607303231Sdimpublic: 608303231Sdim typedef typename std::conditional<isRef, wrap, T>::type storage_type; 609303231Sdim typedef T value_type; 610303231Sdim 611303231Sdimprivate: 612303231Sdim typedef typename std::remove_reference<T>::type &reference; 613303231Sdim typedef const typename std::remove_reference<T>::type &const_reference; 614303231Sdim typedef typename std::remove_reference<T>::type *pointer; 615303231Sdim typedef const typename std::remove_reference<T>::type *const_pointer; 616303231Sdim 617303231Sdimpublic: 618303231Sdim /// Create an Expected<T> error value from the given Error. 619303231Sdim Expected(Error Err) 620303231Sdim : HasError(true) 621303231Sdim#ifndef NDEBUG 622303231Sdim , 623303231Sdim Checked(false) 624303231Sdim#endif 625303231Sdim { 626303231Sdim assert(Err && "Cannot create Expected<T> from Error success value."); 627303231Sdim new (getErrorStorage()) Error(std::move(Err)); 628303231Sdim } 629303231Sdim 630303231Sdim /// Create an Expected<T> success value from the given OtherT value, which 631303231Sdim /// must be convertible to T. 632303231Sdim template <typename OtherT> 633303231Sdim Expected(OtherT &&Val, 634303231Sdim typename std::enable_if<std::is_convertible<OtherT, T>::value>::type 635303231Sdim * = nullptr) 636303231Sdim : HasError(false) 637303231Sdim#ifndef NDEBUG 638303231Sdim , 639303231Sdim Checked(false) 640303231Sdim#endif 641303231Sdim { 642303231Sdim new (getStorage()) storage_type(std::forward<OtherT>(Val)); 643303231Sdim } 644303231Sdim 645303231Sdim /// Move construct an Expected<T> value. 646303231Sdim Expected(Expected &&Other) { moveConstruct(std::move(Other)); } 647303231Sdim 648303231Sdim /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT 649303231Sdim /// must be convertible to T. 650303231Sdim template <class OtherT> 651303231Sdim Expected(Expected<OtherT> &&Other, 652303231Sdim typename std::enable_if<std::is_convertible<OtherT, T>::value>::type 653303231Sdim * = nullptr) { 654303231Sdim moveConstruct(std::move(Other)); 655303231Sdim } 656303231Sdim 657303231Sdim /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT 658303231Sdim /// isn't convertible to T. 659303231Sdim template <class OtherT> 660303231Sdim explicit Expected( 661303231Sdim Expected<OtherT> &&Other, 662303231Sdim typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = 663303231Sdim nullptr) { 664303231Sdim moveConstruct(std::move(Other)); 665303231Sdim } 666303231Sdim 667303231Sdim /// Move-assign from another Expected<T>. 668303231Sdim Expected &operator=(Expected &&Other) { 669303231Sdim moveAssign(std::move(Other)); 670303231Sdim return *this; 671303231Sdim } 672303231Sdim 673303231Sdim /// Destroy an Expected<T>. 674303231Sdim ~Expected() { 675303231Sdim assertIsChecked(); 676303231Sdim if (!HasError) 677303231Sdim getStorage()->~storage_type(); 678303231Sdim else 679303231Sdim getErrorStorage()->~error_type(); 680303231Sdim } 681303231Sdim 682303231Sdim /// \brief Return false if there is an error. 683303231Sdim explicit operator bool() { 684303231Sdim#ifndef NDEBUG 685303231Sdim Checked = !HasError; 686303231Sdim#endif 687303231Sdim return !HasError; 688303231Sdim } 689303231Sdim 690303231Sdim /// \brief Returns a reference to the stored T value. 691303231Sdim reference get() { 692303231Sdim assertIsChecked(); 693303231Sdim return *getStorage(); 694303231Sdim } 695303231Sdim 696303231Sdim /// \brief Returns a const reference to the stored T value. 697303231Sdim const_reference get() const { 698303231Sdim assertIsChecked(); 699303231Sdim return const_cast<Expected<T> *>(this)->get(); 700303231Sdim } 701303231Sdim 702303231Sdim /// \brief Check that this Expected<T> is an error of type ErrT. 703303231Sdim template <typename ErrT> bool errorIsA() const { 704303231Sdim return HasError && getErrorStorage()->template isA<ErrT>(); 705303231Sdim } 706303231Sdim 707303231Sdim /// \brief Take ownership of the stored error. 708303231Sdim /// After calling this the Expected<T> is in an indeterminate state that can 709303231Sdim /// only be safely destructed. No further calls (beside the destructor) should 710303231Sdim /// be made on the Expected<T> vaule. 711303231Sdim Error takeError() { 712303231Sdim#ifndef NDEBUG 713303231Sdim Checked = true; 714303231Sdim#endif 715303231Sdim return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); 716303231Sdim } 717303231Sdim 718303231Sdim /// \brief Returns a pointer to the stored T value. 719303231Sdim pointer operator->() { 720303231Sdim assertIsChecked(); 721303231Sdim return toPointer(getStorage()); 722303231Sdim } 723303231Sdim 724303231Sdim /// \brief Returns a const pointer to the stored T value. 725303231Sdim const_pointer operator->() const { 726303231Sdim assertIsChecked(); 727303231Sdim return toPointer(getStorage()); 728303231Sdim } 729303231Sdim 730303231Sdim /// \brief Returns a reference to the stored T value. 731303231Sdim reference operator*() { 732303231Sdim assertIsChecked(); 733303231Sdim return *getStorage(); 734303231Sdim } 735303231Sdim 736303231Sdim /// \brief Returns a const reference to the stored T value. 737303231Sdim const_reference operator*() const { 738303231Sdim assertIsChecked(); 739303231Sdim return *getStorage(); 740303231Sdim } 741303231Sdim 742303231Sdimprivate: 743303231Sdim template <class T1> 744303231Sdim static bool compareThisIfSameType(const T1 &a, const T1 &b) { 745303231Sdim return &a == &b; 746303231Sdim } 747303231Sdim 748303231Sdim template <class T1, class T2> 749303231Sdim static bool compareThisIfSameType(const T1 &a, const T2 &b) { 750303231Sdim return false; 751303231Sdim } 752303231Sdim 753303231Sdim template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { 754303231Sdim HasError = Other.HasError; 755303231Sdim 756303231Sdim#ifndef NDEBUG 757303231Sdim Checked = false; 758303231Sdim Other.Checked = true; 759303231Sdim#endif 760303231Sdim 761303231Sdim if (!HasError) 762303231Sdim new (getStorage()) storage_type(std::move(*Other.getStorage())); 763303231Sdim else 764303231Sdim new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); 765303231Sdim } 766303231Sdim 767303231Sdim template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { 768303231Sdim assertIsChecked(); 769303231Sdim 770303231Sdim if (compareThisIfSameType(*this, Other)) 771303231Sdim return; 772303231Sdim 773303231Sdim this->~Expected(); 774303231Sdim new (this) Expected(std::move(Other)); 775303231Sdim } 776303231Sdim 777303231Sdim pointer toPointer(pointer Val) { return Val; } 778303231Sdim 779303231Sdim const_pointer toPointer(const_pointer Val) const { return Val; } 780303231Sdim 781303231Sdim pointer toPointer(wrap *Val) { return &Val->get(); } 782303231Sdim 783303231Sdim const_pointer toPointer(const wrap *Val) const { return &Val->get(); } 784303231Sdim 785303231Sdim storage_type *getStorage() { 786303231Sdim assert(!HasError && "Cannot get value when an error exists!"); 787303231Sdim return reinterpret_cast<storage_type *>(TStorage.buffer); 788303231Sdim } 789303231Sdim 790303231Sdim const storage_type *getStorage() const { 791303231Sdim assert(!HasError && "Cannot get value when an error exists!"); 792303231Sdim return reinterpret_cast<const storage_type *>(TStorage.buffer); 793303231Sdim } 794303231Sdim 795303231Sdim error_type *getErrorStorage() { 796303231Sdim assert(HasError && "Cannot get error when a value exists!"); 797303231Sdim return reinterpret_cast<error_type *>(ErrorStorage.buffer); 798303231Sdim } 799303231Sdim 800303231Sdim void assertIsChecked() { 801303231Sdim#ifndef NDEBUG 802303231Sdim if (!Checked) { 803303231Sdim dbgs() << "Expected<T> must be checked before access or destruction.\n"; 804303231Sdim if (HasError) { 805303231Sdim dbgs() << "Unchecked Expected<T> contained error:\n"; 806303231Sdim (*getErrorStorage())->log(dbgs()); 807303231Sdim } else 808303231Sdim dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " 809303231Sdim "values in success mode must still be checked prior to being " 810303231Sdim "destroyed).\n"; 811303231Sdim abort(); 812303231Sdim } 813303231Sdim#endif 814303231Sdim } 815303231Sdim 816303231Sdim union { 817303231Sdim AlignedCharArrayUnion<storage_type> TStorage; 818303231Sdim AlignedCharArrayUnion<error_type> ErrorStorage; 819303231Sdim }; 820303231Sdim bool HasError : 1; 821303231Sdim#ifndef NDEBUG 822303231Sdim bool Checked : 1; 823303231Sdim#endif 824303231Sdim}; 825303231Sdim 826303231Sdim/// This class wraps a std::error_code in a Error. 827303231Sdim/// 828303231Sdim/// This is useful if you're writing an interface that returns a Error 829303231Sdim/// (or Expected) and you want to call code that still returns 830303231Sdim/// std::error_codes. 831303231Sdimclass ECError : public ErrorInfo<ECError> { 832303231Sdim friend Error errorCodeToError(std::error_code); 833303231Sdimpublic: 834303231Sdim void setErrorCode(std::error_code EC) { this->EC = EC; } 835303231Sdim std::error_code convertToErrorCode() const override { return EC; } 836303231Sdim void log(raw_ostream &OS) const override { OS << EC.message(); } 837303231Sdim 838303231Sdim // Used by ErrorInfo::classID. 839303231Sdim static char ID; 840303231Sdim 841303231Sdimprotected: 842303231Sdim ECError() = default; 843303231Sdim ECError(std::error_code EC) : EC(EC) {} 844303231Sdim std::error_code EC; 845303231Sdim}; 846303231Sdim 847303231Sdim/// The value returned by this function can be returned from convertToErrorCode 848303231Sdim/// for Error values where no sensible translation to std::error_code exists. 849303231Sdim/// It should only be used in this situation, and should never be used where a 850303231Sdim/// sensible conversion to std::error_code is available, as attempts to convert 851303231Sdim/// to/from this error will result in a fatal error. (i.e. it is a programmatic 852303231Sdim///error to try to convert such a value). 853303231Sdimstd::error_code inconvertibleErrorCode(); 854303231Sdim 855303231Sdim/// Helper for converting an std::error_code to a Error. 856303231SdimError errorCodeToError(std::error_code EC); 857303231Sdim 858303231Sdim/// Helper for converting an ECError to a std::error_code. 859303231Sdim/// 860303231Sdim/// This method requires that Err be Error() or an ECError, otherwise it 861303231Sdim/// will trigger a call to abort(). 862303231Sdimstd::error_code errorToErrorCode(Error Err); 863303231Sdim 864303231Sdim/// Convert an ErrorOr<T> to an Expected<T>. 865303231Sdimtemplate <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { 866303231Sdim if (auto EC = EO.getError()) 867303231Sdim return errorCodeToError(EC); 868303231Sdim return std::move(*EO); 869303231Sdim} 870303231Sdim 871303231Sdim/// Convert an Expected<T> to an ErrorOr<T>. 872303231Sdimtemplate <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { 873303231Sdim if (auto Err = E.takeError()) 874303231Sdim return errorToErrorCode(std::move(Err)); 875303231Sdim return std::move(*E); 876303231Sdim} 877303231Sdim 878303231Sdim/// This class wraps a string in an Error. 879303231Sdim/// 880303231Sdim/// StringError is useful in cases where the client is not expected to be able 881303231Sdim/// to consume the specific error message programmatically (for example, if the 882303231Sdim/// error message is to be presented to the user). 883303231Sdimclass StringError : public ErrorInfo<StringError> { 884303231Sdimpublic: 885303231Sdim static char ID; 886303231Sdim StringError(const Twine &S, std::error_code EC); 887303231Sdim void log(raw_ostream &OS) const override; 888303231Sdim std::error_code convertToErrorCode() const override; 889303231Sdimprivate: 890303231Sdim std::string Msg; 891303231Sdim std::error_code EC; 892303231Sdim}; 893303231Sdim 894303231Sdim/// Helper for check-and-exit error handling. 895303231Sdim/// 896303231Sdim/// For tool use only. NOT FOR USE IN LIBRARY CODE. 897303231Sdim/// 898303231Sdimclass ExitOnError { 899303231Sdimpublic: 900303231Sdim /// Create an error on exit helper. 901303231Sdim ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) 902303231Sdim : Banner(std::move(Banner)), 903303231Sdim GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} 904303231Sdim 905303231Sdim /// Set the banner string for any errors caught by operator(). 906303231Sdim void setBanner(std::string Banner) { this->Banner = std::move(Banner); } 907303231Sdim 908303231Sdim /// Set the exit-code mapper function. 909303231Sdim void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { 910303231Sdim this->GetExitCode = std::move(GetExitCode); 911303231Sdim } 912303231Sdim 913303231Sdim /// Check Err. If it's in a failure state log the error(s) and exit. 914303231Sdim void operator()(Error Err) const { checkError(std::move(Err)); } 915303231Sdim 916303231Sdim /// Check E. If it's in a success state then return the contained value. If 917303231Sdim /// it's in a failure state log the error(s) and exit. 918303231Sdim template <typename T> T operator()(Expected<T> &&E) const { 919303231Sdim checkError(E.takeError()); 920303231Sdim return std::move(*E); 921303231Sdim } 922303231Sdim 923303231Sdim /// Check E. If it's in a success state then return the contained reference. If 924303231Sdim /// it's in a failure state log the error(s) and exit. 925303231Sdim template <typename T> T& operator()(Expected<T&> &&E) const { 926303231Sdim checkError(E.takeError()); 927303231Sdim return *E; 928303231Sdim } 929303231Sdim 930303231Sdimprivate: 931303231Sdim void checkError(Error Err) const { 932303231Sdim if (Err) { 933303231Sdim int ExitCode = GetExitCode(Err); 934303231Sdim logAllUnhandledErrors(std::move(Err), errs(), Banner); 935303231Sdim exit(ExitCode); 936303231Sdim } 937303231Sdim } 938303231Sdim 939303231Sdim std::string Banner; 940303231Sdim std::function<int(const Error &)> GetExitCode; 941303231Sdim}; 942303231Sdim 943303231Sdim/// Report a serious error, calling any installed error handler. See 944303231Sdim/// ErrorHandling.h. 945303231SdimLLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, 946303231Sdim bool gen_crash_diag = true); 947303231Sdim 948303231Sdim} // namespace llvm 949303231Sdim 950303231Sdim#endif // LLVM_SUPPORT_ERROR_H 951