Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:32

0001 //===- LogicalResult.h - Utilities for handling success/failure -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_SUPPORT_LOGICALRESULT_H
0010 #define LLVM_SUPPORT_LOGICALRESULT_H
0011 
0012 #include <cassert>
0013 #include <optional>
0014 
0015 namespace llvm {
0016 /// This class represents an efficient way to signal success or failure. It
0017 /// should be preferred over the use of `bool` when appropriate, as it avoids
0018 /// all of the ambiguity that arises in interpreting a boolean result. This
0019 /// class is marked as NODISCARD to ensure that the result is processed. Users
0020 /// may explicitly discard a result by using `(void)`, e.g.
0021 /// `(void)functionThatReturnsALogicalResult();`. Given the intended nature of
0022 /// this class, it generally shouldn't be used as the result of functions that
0023 /// very frequently have the result ignored. This class is intended to be used
0024 /// in conjunction with the utility functions below.
0025 struct [[nodiscard]] LogicalResult {
0026 public:
0027   /// If isSuccess is true a `success` result is generated, otherwise a
0028   /// 'failure' result is generated.
0029   static LogicalResult success(bool IsSuccess = true) {
0030     return LogicalResult(IsSuccess);
0031   }
0032 
0033   /// If isFailure is true a `failure` result is generated, otherwise a
0034   /// 'success' result is generated.
0035   static LogicalResult failure(bool IsFailure = true) {
0036     return LogicalResult(!IsFailure);
0037   }
0038 
0039   /// Returns true if the provided LogicalResult corresponds to a success value.
0040   constexpr bool succeeded() const { return IsSuccess; }
0041 
0042   /// Returns true if the provided LogicalResult corresponds to a failure value.
0043   constexpr bool failed() const { return !IsSuccess; }
0044 
0045 private:
0046   LogicalResult(bool IsSuccess) : IsSuccess(IsSuccess) {}
0047 
0048   /// Boolean indicating if this is a success result, if false this is a
0049   /// failure result.
0050   bool IsSuccess;
0051 };
0052 
0053 /// Utility function to generate a LogicalResult. If isSuccess is true a
0054 /// `success` result is generated, otherwise a 'failure' result is generated.
0055 inline LogicalResult success(bool IsSuccess = true) {
0056   return LogicalResult::success(IsSuccess);
0057 }
0058 
0059 /// Utility function to generate a LogicalResult. If isFailure is true a
0060 /// `failure` result is generated, otherwise a 'success' result is generated.
0061 inline LogicalResult failure(bool IsFailure = true) {
0062   return LogicalResult::failure(IsFailure);
0063 }
0064 
0065 /// Utility function that returns true if the provided LogicalResult corresponds
0066 /// to a success value.
0067 inline bool succeeded(LogicalResult Result) { return Result.succeeded(); }
0068 
0069 /// Utility function that returns true if the provided LogicalResult corresponds
0070 /// to a failure value.
0071 inline bool failed(LogicalResult Result) { return Result.failed(); }
0072 
0073 /// This class provides support for representing a failure result, or a valid
0074 /// value of type `T`. This allows for integrating with LogicalResult, while
0075 /// also providing a value on the success path.
0076 template <typename T> class [[nodiscard]] FailureOr : public std::optional<T> {
0077 public:
0078   /// Allow constructing from a LogicalResult. The result *must* be a failure.
0079   /// Success results should use a proper instance of type `T`.
0080   FailureOr(LogicalResult Result) {
0081     assert(failed(Result) &&
0082            "success should be constructed with an instance of 'T'");
0083   }
0084   FailureOr() : FailureOr(failure()) {}
0085   FailureOr(T &&Y) : std::optional<T>(std::forward<T>(Y)) {}
0086   FailureOr(const T &Y) : std::optional<T>(Y) {}
0087   template <typename U,
0088             std::enable_if_t<std::is_constructible<T, U>::value> * = nullptr>
0089   FailureOr(const FailureOr<U> &Other)
0090       : std::optional<T>(failed(Other) ? std::optional<T>()
0091                                        : std::optional<T>(*Other)) {}
0092 
0093   operator LogicalResult() const { return success(has_value()); }
0094 
0095 private:
0096   /// Hide the bool conversion as it easily creates confusion.
0097   using std::optional<T>::operator bool;
0098   using std::optional<T>::has_value;
0099 };
0100 
0101 /// Wrap a value on the success path in a FailureOr of the same value type.
0102 template <typename T,
0103           typename = std::enable_if_t<!std::is_convertible_v<T, bool>>>
0104 inline auto success(T &&Y) {
0105   return FailureOr<std::decay_t<T>>(std::forward<T>(Y));
0106 }
0107 
0108 /// This class represents success/failure for parsing-like operations that find
0109 /// it important to chain together failable operations with `||`.  This is an
0110 /// extended version of `LogicalResult` that allows for explicit conversion to
0111 /// bool.
0112 ///
0113 /// This class should not be used for general error handling cases - we prefer
0114 /// to keep the logic explicit with the `succeeded`/`failed` predicates.
0115 /// However, traditional monadic-style parsing logic can sometimes get
0116 /// swallowed up in boilerplate without this, so we provide this for narrow
0117 /// cases where it is important.
0118 ///
0119 class [[nodiscard]] ParseResult : public LogicalResult {
0120 public:
0121   ParseResult(LogicalResult Result = success()) : LogicalResult(Result) {}
0122 
0123   /// Failure is true in a boolean context.
0124   constexpr explicit operator bool() const { return failed(); }
0125 };
0126 } // namespace llvm
0127 
0128 #endif // LLVM_SUPPORT_LOGICALRESULT_H