blob: b9492ede0cdd246ce9594b40b3afce4b09a28022 [file] [log] [blame]
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_MLIR_EDGE_IREE_BASE_INTERNAL_STATUS_MACROS_H_
#define THIRD_PARTY_MLIR_EDGE_IREE_BASE_INTERNAL_STATUS_MACROS_H_
#include "third_party/absl/types/source_location.h"
#include "third_party/mlir_edge/iree/base/internal/status.h"
#include "third_party/mlir_edge/iree/base/internal/status_builder.h"
#include "third_party/mlir_edge/iree/base/internal/statusor.h"
// Evaluates an expression that produces a `iree::Status`. If the status is not
// ok, returns it from the current function.
#define RETURN_IF_ERROR(expr) \
STATUS_MACROS_IMPL_ELSE_BLOCKER_ \
if (iree::status_macro_internal::StatusAdaptorForMacros \
status_macro_internal_adaptor = {(expr), ABSL_LOC}) { \
} else /* NOLINT */ \
return status_macro_internal_adaptor.Consume()
// Executes an expression `rexpr` that returns a `iree::StatusOr<T>`. On OK,
// moves its value into the variable defined by `lhs`, otherwise returns
// from the current function.
#define ASSIGN_OR_RETURN(...) \
STATUS_MACROS_IMPL_GET_VARIADIC_((__VA_ARGS__, \
STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_3_, \
STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_2_)) \
(__VA_ARGS__)
// =================================================================
// == Implementation details, do not rely on anything below here. ==
// =================================================================
// MSVC incorrectly expands variadic macros, splice together a macro call to
// work around the bug.
#define STATUS_MACROS_IMPL_GET_VARIADIC_HELPER_(_1, _2, _3, NAME, ...) NAME
#define STATUS_MACROS_IMPL_GET_VARIADIC_(args) \
STATUS_MACROS_IMPL_GET_VARIADIC_HELPER_ args
#define STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_2_(lhs, rexpr) \
STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_3_(lhs, rexpr, std::move(_))
#define STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_3_(lhs, rexpr, error_expression) \
STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_( \
STATUS_MACROS_IMPL_CONCAT_(_status_or_value, __LINE__), lhs, rexpr, \
error_expression)
#define STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_(statusor, lhs, rexpr, \
error_expression) \
auto statusor = (rexpr); \
if (ABSL_PREDICT_FALSE(!statusor.ok())) { \
iree::StatusBuilder _(std::move(statusor).status(), ABSL_LOC); \
(void)_; /* error_expression is allowed to not use this variable */ \
return (error_expression); \
} \
lhs = std::move(statusor).ValueOrDie()
// Internal helper for concatenating macro values.
#define STATUS_MACROS_IMPL_CONCAT_INNER_(x, y) x##y
#define STATUS_MACROS_IMPL_CONCAT_(x, y) STATUS_MACROS_IMPL_CONCAT_INNER_(x, y)
// clang-format off
#define STATUS_MACROS_IMPL_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT
// clang-format on
namespace iree {
namespace status_macro_internal {
// Provides a conversion to bool so that it can be used inside an if statement
// that declares a variable.
class StatusAdaptorForMacros {
public:
StatusAdaptorForMacros(const Status& status, absl::SourceLocation loc)
: builder_(status, loc) {}
StatusAdaptorForMacros(Status&& status, absl::SourceLocation loc)
: builder_(std::move(status), loc) {}
StatusAdaptorForMacros(const StatusBuilder& builder, absl::SourceLocation loc)
: builder_(builder) {}
StatusAdaptorForMacros(StatusBuilder&& builder, absl::SourceLocation loc)
: builder_(std::move(builder)) {}
StatusAdaptorForMacros(const StatusAdaptorForMacros&) = delete;
StatusAdaptorForMacros& operator=(const StatusAdaptorForMacros&) = delete;
explicit operator bool() const { return ABSL_PREDICT_TRUE(builder_.ok()); }
StatusBuilder&& Consume() { return std::move(builder_); }
private:
StatusBuilder builder_;
};
} // namespace status_macro_internal
} // namespace iree
#endif // THIRD_PARTY_MLIR_EDGE_IREE_BASE_INTERNAL_STATUS_MACROS_H_