/* RCC-Project Copyright (C) 2026 Richard Qin This file is part of RCC-Project. RCC-Project is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RCC-Project; see the file COPYING. If not see . */ //===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines an API used to indicate fatal error conditions. Non-fatal // errors (most of them) should be handled through LLVMContext. // //===----------------------------------------------------------------------===// #ifndef RCC_SUPPORT_ERRORHANDLING_H #define RCC_SUPPORT_ERRORHANDLING_H #include "CoreLib/Compiler/Compiler.h" namespace rcc { class StringRef; class Twine; /// An error handler callback. using fatal_error_handler_t = void (*) (void *user_data, const char *reason, bool gen_crash_diag); /// install_fatal_error_handler - Installs a new error handler to be used /// whenever a serious (non-recoverable) error is encountered by LLVM. /// /// If no error handler is installed the default is to print the error message /// to stderr, and call exit(1). If an error handler is installed then it is /// the handler's responsibility to log the message, it will no longer be /// printed to stderr. If the error handler returns, then exit(1) will be /// called. /// /// It is dangerous to naively use an error handler which throws an exception. /// Even though some applications desire to gracefully recover from arbitrary /// faults, blindly throwing exceptions through unfamiliar code isn't a way to /// achieve this. /// /// \param user_data - An argument which will be passed to the install error /// handler. RCC_ABI void install_fatal_error_handler (fatal_error_handler_t handler, void *user_data = nullptr); /// Restores default error handling behaviour. RCC_ABI void remove_fatal_error_handler (); /// ScopedFatalErrorHandler - This is a simple helper class which just /// calls install_fatal_error_handler in its constructor and /// remove_fatal_error_handler in its destructor. struct ScopedFatalErrorHandler { explicit ScopedFatalErrorHandler (fatal_error_handler_t handler, void *user_data = nullptr) { install_fatal_error_handler (handler, user_data); } ~ScopedFatalErrorHandler () { remove_fatal_error_handler (); } }; /// @deprecated Use reportFatalInternalError() or reportFatalUsageError() /// instead. [[noreturn]] RCC_ABI void report_fatal_error (const char *reason, bool gen_crash_diag = true); [[noreturn]] RCC_ABI void report_fatal_error (StringRef reason, bool gen_crash_diag = true); [[noreturn]] RCC_ABI void report_fatal_error (const Twine &reason, bool gen_crash_diag = true); /// Report a fatal error that likely indicates a bug in LLVM. It serves a /// similar purpose as an assertion, but is always enabled, regardless of the /// value of NDEBUG. /// /// This will call installed error handlers (or print the message by default) /// and then abort. This will produce a crash trace and *will* ask users to /// report an LLVM bug. [[noreturn]] RCC_ABI void reportFatalInternalError (const char *reason); [[noreturn]] RCC_ABI void reportFatalInternalError (StringRef reason); [[noreturn]] RCC_ABI void reportFatalInternalError (const Twine &reason); /// Report a fatal error that does not indicate a bug in LLVM. /// /// This can be used in contexts where a proper error reporting mechanism /// (such as Error/Expected or DiagnosticInfo) is currently not supported, and /// would be too involved to introduce at the moment. /// /// Examples where this function should be used instead of /// reportFatalInternalError() include invalid inputs or options, but also /// environment error conditions outside LLVM's control. It should also be used /// for known unsupported/unimplemented functionality. /// /// This will call installed error handlers (or print the message by default) /// and then exit with code 1. It will not produce a crash trace and will /// *not* ask users to report an LLVM bug. [[noreturn]] RCC_ABI void reportFatalUsageError (const char *reason); [[noreturn]] RCC_ABI void reportFatalUsageError (StringRef reason); [[noreturn]] RCC_ABI void reportFatalUsageError (const Twine &reason); /// Installs a new bad alloc error handler that should be used whenever a /// bad alloc error, e.g. failing malloc/calloc, is encountered by LLVM. /// /// The user can install a bad alloc handler, in order to define the behavior /// in case of failing allocations, e.g. throwing an exception. Note that this /// handler must not trigger any additional allocations itself. /// /// If no error handler is installed the default is to print the error message /// to stderr, and call exit(1). If an error handler is installed then it is /// the handler's responsibility to log the message, it will no longer be /// printed to stderr. If the error handler returns, then exit(1) will be /// called. /// /// /// \param user_data - An argument which will be passed to the installed error /// handler. RCC_ABI void install_bad_alloc_error_handler (fatal_error_handler_t handler, void *user_data = nullptr); /// Restores default bad alloc error handling behavior. RCC_ABI void remove_bad_alloc_error_handler (); RCC_ABI void install_out_of_memory_new_handler (); /// Reports a bad alloc error, calling any user defined bad alloc /// error handler. In contrast to the generic 'report_fatal_error' /// functions, this function might not terminate, e.g. the user /// defined error handler throws an exception, but it won't return. /// /// Note: When throwing an exception in the bad alloc handler, make sure that /// the following unwind succeeds, e.g. do not trigger additional allocations /// in the unwind chain. /// /// If no error handler is installed (default), throws a bad_alloc exception /// if LLVM is compiled with exception support. Otherwise prints the error /// to standard error and calls abort(). [[noreturn]] RCC_ABI void report_bad_alloc_error (const char *Reason, bool GenCrashDiag = true); /// This function calls abort(), and prints the optional message to stderr. /// Use the llvm_unreachable macro (that adds location info), instead of /// calling this function directly. [[noreturn]] RCC_ABI void rcc_unreachable_internal (const char *msg = nullptr, const char *file = nullptr, unsigned line = 0); } // namespace rcc /// Marks that the current location is not supposed to be reachable. /// In !NDEBUG builds, prints the message and location info to stderr. /// In NDEBUG builds, if the platform does not support a builtin unreachable /// then we call an internal LLVM runtime function. Otherwise the behavior is /// controlled by the CMake flag /// -DLLVM_UNREACHABLE_OPTIMIZE /// * When "ON" (default) llvm_unreachable() becomes an optimizer hint /// that the current location is not supposed to be reachable: the hint /// turns such code path into undefined behavior. On compilers that don't /// support such hints, prints a reduced message instead and aborts the /// program. /// * When "OFF", a builtin_trap is emitted instead of an // optimizer hint or printing a reduced message. /// /// Use this instead of assert(0). It conveys intent more clearly, suppresses /// diagnostics for unreachable code paths, and allows compilers to omit /// unnecessary code. #ifndef NDEBUG #define rcc_unreachable(msg) \ ::rcc::rcc_unreachable_internal (msg, __FILE__, __LINE__) #elif !defined(RCC_BUILTIN_UNREACHABLE) #define rcc_unreachable(msg) ::rcc::rcc_unreachable_internal () #elif RCC_UNREACHABLE_OPTIMIZE #define rcc_unreachable(msg) RCC_BUILTIN_UNREACHABLE #else #define rcc_unreachable(msg) \ do \ { \ RCC_BUILTIN_TRAP; \ RCC_BUILTIN_UNREACHABLE; \ } while (false) #endif #endif