1e7aad357SLang Hames //===----- lib/Support/Error.cpp - Error and associated utilities ---------===//
2e7aad357SLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e7aad357SLang Hames //
7e7aad357SLang Hames //===----------------------------------------------------------------------===//
8e7aad357SLang Hames 
9e7aad357SLang Hames #include "llvm/Support/Error.h"
10c5e0bbd7SLang Hames #include "llvm/ADT/Twine.h"
11e7aad357SLang Hames #include "llvm/Support/ErrorHandling.h"
122ec8b150SVassil Vassilev #include <system_error>
13e7aad357SLang Hames 
14e7aad357SLang Hames using namespace llvm;
15e7aad357SLang Hames 
16e7aad357SLang Hames namespace {
17e7aad357SLang Hames 
18c5e0bbd7SLang Hames   enum class ErrorErrorCode : int {
19c5e0bbd7SLang Hames     MultipleErrors = 1,
20e11f2217SAlexandre Ganea     FileError,
21bd8e9542SLang Hames     InconvertibleError
22e7aad357SLang Hames   };
23e7aad357SLang Hames 
244718f8b5SPeter Collingbourne   // FIXME: This class is only here to support the transition to llvm::Error. It
254718f8b5SPeter Collingbourne   // will be removed once this transition is complete. Clients should prefer to
264718f8b5SPeter Collingbourne   // deal with the Error value directly, rather than converting to error_code.
27e7aad357SLang Hames   class ErrorErrorCategory : public std::error_category {
28e7aad357SLang Hames   public:
name() const29990504e6SReid Kleckner     const char *name() const noexcept override { return "Error"; }
30e7aad357SLang Hames 
message(int condition) const31e7aad357SLang Hames     std::string message(int condition) const override {
32e7aad357SLang Hames       switch (static_cast<ErrorErrorCode>(condition)) {
33e7aad357SLang Hames       case ErrorErrorCode::MultipleErrors:
34e7aad357SLang Hames         return "Multiple errors";
35bd8e9542SLang Hames       case ErrorErrorCode::InconvertibleError:
36bd8e9542SLang Hames         return "Inconvertible error value. An error has occurred that could "
37c5e0bbd7SLang Hames                "not be converted to a known std::error_code. Please file a "
38c5e0bbd7SLang Hames                "bug.";
39e11f2217SAlexandre Ganea       case ErrorErrorCode::FileError:
40e11f2217SAlexandre Ganea           return "A file error occurred.";
41c5e0bbd7SLang Hames       }
42e7aad357SLang Hames       llvm_unreachable("Unhandled error code");
43e7aad357SLang Hames     }
44e7aad357SLang Hames   };
45e7aad357SLang Hames 
46d8c1be66SNAKAMURA Takumi }
47e7aad357SLang Hames 
getErrorErrorCat()48*ede60037SNicolai Hähnle ErrorErrorCategory &getErrorErrorCat() {
49*ede60037SNicolai Hähnle   static ErrorErrorCategory ErrorErrorCat;
50*ede60037SNicolai Hähnle   return ErrorErrorCat;
51*ede60037SNicolai Hähnle }
52c5e0bbd7SLang Hames 
53c5e0bbd7SLang Hames namespace llvm {
54c5e0bbd7SLang Hames 
anchor()55e7aad357SLang Hames void ErrorInfoBase::anchor() {}
56e7aad357SLang Hames char ErrorInfoBase::ID = 0;
57a15b76b3SReid Kleckner char ErrorList::ID = 0;
anchor()5890004149SDavid Bolvansky void ECError::anchor() {}
59a15b76b3SReid Kleckner char ECError::ID = 0;
60c5e0bbd7SLang Hames char StringError::ID = 0;
61e11f2217SAlexandre Ganea char FileError::ID = 0;
62e6d29c99SNAKAMURA Takumi 
logAllUnhandledErrors(Error E,raw_ostream & OS,Twine ErrorBanner)6341a9ee98SZachary Turner void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
642b1c093cSLang Hames   if (!E)
652b1c093cSLang Hames     return;
662b1c093cSLang Hames   OS << ErrorBanner;
672b1c093cSLang Hames   handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
682b1c093cSLang Hames     EI.log(OS);
692b1c093cSLang Hames     OS << "\n";
702b1c093cSLang Hames   });
712b1c093cSLang Hames }
72e7aad357SLang Hames 
73fc209623SLang Hames 
convertToErrorCode() const74e7aad357SLang Hames std::error_code ErrorList::convertToErrorCode() const {
75e7aad357SLang Hames   return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
76*ede60037SNicolai Hähnle                          getErrorErrorCat());
77e7aad357SLang Hames }
78c5e0bbd7SLang Hames 
inconvertibleErrorCode()79bd8e9542SLang Hames std::error_code inconvertibleErrorCode() {
80bd8e9542SLang Hames   return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError),
81*ede60037SNicolai Hähnle                          getErrorErrorCat());
82c5e0bbd7SLang Hames }
83c5e0bbd7SLang Hames 
convertToErrorCode() const84e11f2217SAlexandre Ganea std::error_code FileError::convertToErrorCode() const {
8579c54798SDuncan P. N. Exon Smith   std::error_code NestedEC = Err->convertToErrorCode();
8679c54798SDuncan P. N. Exon Smith   if (NestedEC == inconvertibleErrorCode())
87e11f2217SAlexandre Ganea     return std::error_code(static_cast<int>(ErrorErrorCode::FileError),
88*ede60037SNicolai Hähnle                            getErrorErrorCat());
8979c54798SDuncan P. N. Exon Smith   return NestedEC;
90e11f2217SAlexandre Ganea }
91e11f2217SAlexandre Ganea 
errorCodeToError(std::error_code EC)92c5e0bbd7SLang Hames Error errorCodeToError(std::error_code EC) {
93c5e0bbd7SLang Hames   if (!EC)
94c5e0bbd7SLang Hames     return Error::success();
950eaee545SJonas Devlieghere   return Error(std::make_unique<ECError>(ECError(EC)));
96c5e0bbd7SLang Hames }
97c5e0bbd7SLang Hames 
errorToErrorCode(Error Err)98c5e0bbd7SLang Hames std::error_code errorToErrorCode(Error Err) {
99c5e0bbd7SLang Hames   std::error_code EC;
100c5e0bbd7SLang Hames   handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
101c5e0bbd7SLang Hames     EC = EI.convertToErrorCode();
102c5e0bbd7SLang Hames   });
103bd8e9542SLang Hames   if (EC == inconvertibleErrorCode())
10421661607SSimon Pilgrim     report_fatal_error(Twine(EC.message()));
105c5e0bbd7SLang Hames   return EC;
106c5e0bbd7SLang Hames }
107c5e0bbd7SLang Hames 
10818f21a48SZachary Turner #if LLVM_ENABLE_ABI_BREAKING_CHECKS
fatalUncheckedError() const10918f21a48SZachary Turner void Error::fatalUncheckedError() const {
11018f21a48SZachary Turner   dbgs() << "Program aborted due to an unhandled Error:\n";
11176bcbaafSLang Hames   if (getPtr()) {
11218f21a48SZachary Turner     getPtr()->log(dbgs());
11376bcbaafSLang Hames     dbgs() << "\n";
11476bcbaafSLang Hames   }else
11518f21a48SZachary Turner     dbgs() << "Error value was Success. (Note: Success values must still be "
11618f21a48SZachary Turner               "checked prior to being destroyed).\n";
11718f21a48SZachary Turner   abort();
11818f21a48SZachary Turner }
11918f21a48SZachary Turner #endif
12018f21a48SZachary Turner 
StringError(std::error_code EC,const Twine & S)121e11f2217SAlexandre Ganea StringError::StringError(std::error_code EC, const Twine &S)
122c5e0bbd7SLang Hames     : Msg(S.str()), EC(EC) {}
123c5e0bbd7SLang Hames 
StringError(const Twine & S,std::error_code EC)124e11f2217SAlexandre Ganea StringError::StringError(const Twine &S, std::error_code EC)
125e11f2217SAlexandre Ganea     : Msg(S.str()), EC(EC), PrintMsgOnly(true) {}
126e11f2217SAlexandre Ganea 
log(raw_ostream & OS) const127e11f2217SAlexandre Ganea void StringError::log(raw_ostream &OS) const {
128e11f2217SAlexandre Ganea   if (PrintMsgOnly) {
129e11f2217SAlexandre Ganea     OS << Msg;
130e11f2217SAlexandre Ganea   } else {
131e11f2217SAlexandre Ganea     OS << EC.message();
132e11f2217SAlexandre Ganea     if (!Msg.empty())
133e11f2217SAlexandre Ganea       OS << (" " + Msg);
134e11f2217SAlexandre Ganea   }
135e11f2217SAlexandre Ganea }
136c5e0bbd7SLang Hames 
convertToErrorCode() const137c5e0bbd7SLang Hames std::error_code StringError::convertToErrorCode() const {
138c5e0bbd7SLang Hames   return EC;
139c5e0bbd7SLang Hames }
140c5e0bbd7SLang Hames 
createStringError(std::error_code EC,char const * Msg)141e58e9907SVictor Leschuk Error createStringError(std::error_code EC, char const *Msg) {
142e58e9907SVictor Leschuk   return make_error<StringError>(Msg, EC);
143e58e9907SVictor Leschuk }
144e58e9907SVictor Leschuk 
report_fatal_error(Error Err,bool GenCrashDiag)145fc209623SLang Hames void report_fatal_error(Error Err, bool GenCrashDiag) {
146fc209623SLang Hames   assert(Err && "report_fatal_error called with success value");
147fc209623SLang Hames   std::string ErrMsg;
148fc209623SLang Hames   {
149fc209623SLang Hames     raw_string_ostream ErrStream(ErrMsg);
15045eb84f3SJonas Devlieghere     logAllUnhandledErrors(std::move(Err), ErrStream);
151fc209623SLang Hames   }
15221661607SSimon Pilgrim   report_fatal_error(Twine(ErrMsg));
153fc209623SLang Hames }
154fc209623SLang Hames 
15500fb14daSLang Hames } // end namespace llvm
15600fb14daSLang Hames 
LLVMGetErrorTypeId(LLVMErrorRef Err)15700fb14daSLang Hames LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) {
15800fb14daSLang Hames   return reinterpret_cast<ErrorInfoBase *>(Err)->dynamicClassID();
15900fb14daSLang Hames }
16000fb14daSLang Hames 
LLVMConsumeError(LLVMErrorRef Err)16100fb14daSLang Hames void LLVMConsumeError(LLVMErrorRef Err) { consumeError(unwrap(Err)); }
16200fb14daSLang Hames 
LLVMGetErrorMessage(LLVMErrorRef Err)16300fb14daSLang Hames char *LLVMGetErrorMessage(LLVMErrorRef Err) {
16400fb14daSLang Hames   std::string Tmp = toString(unwrap(Err));
16500fb14daSLang Hames   char *ErrMsg = new char[Tmp.size() + 1];
16600fb14daSLang Hames   memcpy(ErrMsg, Tmp.data(), Tmp.size());
16700fb14daSLang Hames   ErrMsg[Tmp.size()] = '\0';
16800fb14daSLang Hames   return ErrMsg;
16900fb14daSLang Hames }
17000fb14daSLang Hames 
LLVMDisposeErrorMessage(char * ErrMsg)17100fb14daSLang Hames void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; }
17200fb14daSLang Hames 
LLVMGetStringErrorTypeId()17300fb14daSLang Hames LLVMErrorTypeId LLVMGetStringErrorTypeId() {
17400fb14daSLang Hames   return reinterpret_cast<void *>(&StringError::ID);
175c5e0bbd7SLang Hames }
17619402ce7SLang Hames 
LLVMCreateStringError(const char * ErrMsg)17719402ce7SLang Hames LLVMErrorRef LLVMCreateStringError(const char *ErrMsg) {
17819402ce7SLang Hames   return wrap(make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
17919402ce7SLang Hames }
180