Fork status_macros.h into crubit/rs_bindings_from_cc/util/
PiperOrigin-RevId: 435377692
diff --git a/rs_bindings_from_cc/cmdline.cc b/rs_bindings_from_cc/cmdline.cc
index 26d75cb..de37b2d 100644
--- a/rs_bindings_from_cc/cmdline.cc
+++ b/rs_bindings_from_cc/cmdline.cc
@@ -13,8 +13,8 @@
#include "third_party/absl/flags/flag.h"
#include "third_party/absl/strings/str_cat.h"
#include "third_party/absl/strings/substitute.h"
+#include "rs_bindings_from_cc/util/status_macros.h"
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/JSON.h"
-#include "util/task/status_macros.h"
ABSL_FLAG(bool, do_nothing, false,
"if set to true the tool will produce empty files "
@@ -126,11 +126,11 @@
}
}
- ASSIGN_OR_RETURN(cmdline.current_target_,
- cmdline.FindHeader(cmdline.public_headers_[0]));
+ CRUBIT_ASSIGN_OR_RETURN(cmdline.current_target_,
+ cmdline.FindHeader(cmdline.public_headers_[0]));
for (const HeaderName& public_header : cmdline.public_headers_) {
- ASSIGN_OR_RETURN(BlazeLabel header_target,
- cmdline.FindHeader(public_header));
+ CRUBIT_ASSIGN_OR_RETURN(BlazeLabel header_target,
+ cmdline.FindHeader(public_header));
if (cmdline.current_target_ != header_target) {
return absl::InvalidArgumentError(absl::Substitute(
diff --git a/rs_bindings_from_cc/cmdline_test.cc b/rs_bindings_from_cc/cmdline_test.cc
index 8dd5fdc..99feb54 100644
--- a/rs_bindings_from_cc/cmdline_test.cc
+++ b/rs_bindings_from_cc/cmdline_test.cc
@@ -10,7 +10,6 @@
#include "testing/base/public/gmock.h"
#include "testing/base/public/gunit.h"
#include "rs_bindings_from_cc/bazel_types.h"
-#include "util/task/status_macros.h"
namespace rs_bindings_from_cc {
namespace {
diff --git a/rs_bindings_from_cc/importer.cc b/rs_bindings_from_cc/importer.cc
index d2dfcc3..bba0508 100644
--- a/rs_bindings_from_cc/importer.cc
+++ b/rs_bindings_from_cc/importer.cc
@@ -28,6 +28,7 @@
#include "rs_bindings_from_cc/bazel_types.h"
#include "rs_bindings_from_cc/ir.h"
#include "rs_bindings_from_cc/util/check.h"
+#include "rs_bindings_from_cc/util/status_macros.h"
#include "third_party/llvm/llvm-project/clang/include/clang/AST/ASTContext.h"
#include "third_party/llvm/llvm-project/clang/include/clang/AST/Attrs.inc"
#include "third_party/llvm/llvm-project/clang/include/clang/AST/CXXInheritance.h"
@@ -50,7 +51,6 @@
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/ErrorHandling.h"
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/FormatVariadic.h"
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/Regex.h"
-#include "util/task/status_macros.h"
namespace rs_bindings_from_cc {
namespace {
@@ -155,7 +155,7 @@
continue;
}
const clang::CXXRecordDecl* base_record_decl =
- ABSL_DIE_IF_NULL(base_specifier.getType()->getAsCXXRecordDecl());
+ CRUBIT_DIE_IF_NULL(base_specifier.getType()->getAsCXXRecordDecl());
llvm::Optional<int64_t> offset = {0};
for (const clang::CXXBasePathElement& base_path_element : path) {
if (base_path_element.Base->isVirtual()) {
@@ -164,7 +164,7 @@
}
*offset +=
{ctx.getASTRecordLayout(base_path_element.Class)
- .getBaseClassOffset(ABSL_DIE_IF_NULL(
+ .getBaseClassOffset(CRUBIT_DIE_IF_NULL(
base_path_element.Base->getType()->getAsCXXRecordDecl()))
.getQuantity()};
}
@@ -976,15 +976,17 @@
clang::StringRef cc_call_conv =
clang::FunctionType::getNameForCallConv(func_type->getCallConv());
- ASSIGN_OR_RETURN(absl::string_view rs_abi,
- ConvertCcCallConvIntoRsAbi(func_type->getCallConv()));
- ASSIGN_OR_RETURN(MappedType mapped_return_type,
- ConvertQualType(func_type->getReturnType(), lifetimes));
+ CRUBIT_ASSIGN_OR_RETURN(
+ absl::string_view rs_abi,
+ ConvertCcCallConvIntoRsAbi(func_type->getCallConv()));
+ CRUBIT_ASSIGN_OR_RETURN(
+ MappedType mapped_return_type,
+ ConvertQualType(func_type->getReturnType(), lifetimes));
std::vector<MappedType> mapped_param_types;
for (const clang::QualType& param_type : func_type->getParamTypes()) {
- ASSIGN_OR_RETURN(MappedType mapped_param_type,
- ConvertQualType(param_type, lifetimes));
+ CRUBIT_ASSIGN_OR_RETURN(MappedType mapped_param_type,
+ ConvertQualType(param_type, lifetimes));
mapped_param_types.push_back(std::move(mapped_param_type));
}
@@ -1000,8 +1002,8 @@
}
}
- ASSIGN_OR_RETURN(MappedType mapped_pointee_type,
- ConvertQualType(pointee_type, lifetimes));
+ CRUBIT_ASSIGN_OR_RETURN(MappedType mapped_pointee_type,
+ ConvertQualType(pointee_type, lifetimes));
if (type->isPointerType()) {
return MappedType::PointerTo(std::move(mapped_pointee_type), lifetime,
nullable);
diff --git a/rs_bindings_from_cc/importer_test.cc b/rs_bindings_from_cc/importer_test.cc
index 04fbdf4..9fba4d9 100644
--- a/rs_bindings_from_cc/importer_test.cc
+++ b/rs_bindings_from_cc/importer_test.cc
@@ -18,7 +18,6 @@
#include "rs_bindings_from_cc/ir.h"
#include "rs_bindings_from_cc/ir_from_cc.h"
#include "third_party/llvm/llvm-project/clang/include/clang/AST/ASTContext.h"
-#include "util/task/status_macros.h"
namespace rs_bindings_from_cc {
namespace {
diff --git a/rs_bindings_from_cc/rs_bindings_from_cc.cc b/rs_bindings_from_cc/rs_bindings_from_cc.cc
index 4a2a0e2..10e538f 100644
--- a/rs_bindings_from_cc/rs_bindings_from_cc.cc
+++ b/rs_bindings_from_cc/rs_bindings_from_cc.cc
@@ -20,10 +20,10 @@
#include "rs_bindings_from_cc/ir.h"
#include "rs_bindings_from_cc/ir_from_cc.h"
#include "rs_bindings_from_cc/src_code_gen.h"
+#include "rs_bindings_from_cc/util/status_macros.h"
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/FormatVariadic.h"
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/JSON.h"
#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/raw_ostream.h"
-#include "util/task/status_macros.h"
namespace {
@@ -45,19 +45,19 @@
absl::Status Main(int argc, char* argv[]) {
using rs_bindings_from_cc::Cmdline;
using rs_bindings_from_cc::IR;
- ASSIGN_OR_RETURN(Cmdline cmdline, Cmdline::Create());
+ CRUBIT_ASSIGN_OR_RETURN(Cmdline cmdline, Cmdline::Create());
if (cmdline.do_nothing()) {
- RETURN_IF_ERROR(SetFileContents(
+ CRUBIT_RETURN_IF_ERROR(SetFileContents(
cmdline.rs_out(),
"// intentionally left empty because --do_nothing was passed."));
- RETURN_IF_ERROR(SetFileContents(
+ CRUBIT_RETURN_IF_ERROR(SetFileContents(
cmdline.cc_out(),
"// intentionally left empty because --do_nothing was passed."));
return absl::OkStatus();
}
- ASSIGN_OR_RETURN(
+ CRUBIT_ASSIGN_OR_RETURN(
IR ir,
rs_bindings_from_cc::IrFromCc(
/* extra_source_code= */ "", cmdline.current_target(),
@@ -66,14 +66,15 @@
std::vector<absl::string_view>(argv, argv + argc)));
if (!cmdline.ir_out().empty()) {
- RETURN_IF_ERROR(SetFileContents(
+ CRUBIT_RETURN_IF_ERROR(SetFileContents(
cmdline.ir_out(), std::string(llvm::formatv("{0:2}", ir.ToJson()))));
}
rs_bindings_from_cc::Bindings bindings =
rs_bindings_from_cc::GenerateBindings(ir);
- RETURN_IF_ERROR(SetFileContents(cmdline.rs_out(), bindings.rs_api));
- RETURN_IF_ERROR(SetFileContents(cmdline.cc_out(), bindings.rs_api_impl));
+ CRUBIT_RETURN_IF_ERROR(SetFileContents(cmdline.rs_out(), bindings.rs_api));
+ CRUBIT_RETURN_IF_ERROR(
+ SetFileContents(cmdline.cc_out(), bindings.rs_api_impl));
return absl::OkStatus();
}
diff --git a/rs_bindings_from_cc/util/status_macros.h b/rs_bindings_from_cc/util/status_macros.h
new file mode 100644
index 0000000..44a9fb8
--- /dev/null
+++ b/rs_bindings_from_cc/util/status_macros.h
@@ -0,0 +1,169 @@
+// Part of the Crubit project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Helper macros and methods to return and propagate errors with `absl::Status`.
+
+#ifndef CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STATUS_MACROS_H_
+#define CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STATUS_MACROS_H_
+
+#include <utility>
+
+#include "third_party/absl/base/optimization.h"
+#include "third_party/absl/status/status.h"
+#include "third_party/absl/status/statusor.h"
+#include "third_party/absl/types/source_location.h"
+
+// Evaluates an expression that produces a `absl::Status`. If the status is not
+// ok, returns it from the current function.
+//
+// For example:
+// absl::Status MultiStepFunction() {
+// CRUBIT_RETURN_IF_ERROR(Function(args...));
+// CRUBIT_RETURN_IF_ERROR(foo.Method(args...));
+// return absl::OkStatus();
+// }
+#define CRUBIT_RETURN_IF_ERROR(expr) \
+ CRUBIT_STATUS_MACROS_IMPL_ELSE_BLOCKER_ \
+ if (::absl::Status status = (expr); status.ok()) { \
+ } else /* NOLINT */ \
+ return status
+
+// Executes an expression `rexpr` that returns an `absl::StatusOr<T>`. On OK,
+// moves its value into the variable defined by `lhs`, otherwise returns
+// from the current function.
+//
+// Interface:
+//
+// CRUBIT_ASSIGN_OR_RETURN(lhs, rexpr)
+//
+// WARNING: if lhs is parenthesized, the parentheses are removed. See examples
+// for more details.
+//
+// WARNING: expands into multiple statements; it cannot be used in a single
+// statement (e.g. as the body of an if statement without {})!
+//
+// Example: Declaring and initializing a new variable (ValueType can be anything
+// that can be initialized with assignment, including references):
+// CRUBIT_ASSIGN_OR_RETURN(ValueType value, MaybeGetValue(arg));
+//
+// Example: Assigning to an existing variable:
+// ValueType value;
+// CRUBIT_ASSIGN_OR_RETURN(value, MaybeGetValue(arg));
+//
+// Example: Assigning to an expression with side effects:
+// MyProto data;
+// CRUBIT_ASSIGN_OR_RETURN(*data.mutable_str(), MaybeGetValue(arg));
+// // No field "str" is added on error.
+//
+// Example: Initializing a `std::unique_ptr`.
+// CRUBIT_ASSIGN_OR_RETURN(std::unique_ptr<T> ptr, MaybeGetPtr(arg));
+//
+// Example: Initializing a map. Because of C++ preprocessor limitations,
+// the type used in CRUBIT_ASSIGN_OR_RETURN cannot contain commas, so wrap the
+// lhs in parentheses:
+// CRUBIT_ASSIGN_OR_RETURN((absl::flat_hash_map<Foo, Bar> my_map), GetMap());
+// Or use `auto` if the type is obvious enough:
+// CRUBIT_ASSIGN_OR_RETURN(auto my_map, GetMap());
+//
+// Example: Assigning to structured bindings (<internal link>/169). The same situation
+// with comma as in map, so wrap the statement in parentheses.
+// CRUBIT_ASSIGN_OR_RETURN((auto [first, second]), GetPair());
+#define CRUBIT_ASSIGN_OR_RETURN(lhs, rexpr) \
+ CRUBIT_STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_( \
+ CRUBIT_STATUS_MACROS_IMPL_CONCAT_(_status_or_value, __LINE__), lhs, \
+ rexpr, \
+ return absl::Status(std::move(CRUBIT_STATUS_MACROS_IMPL_CONCAT_( \
+ _status_or_value, __LINE__)) \
+ .status(), \
+ ABSL_LOC))
+
+// =================================================================
+// == Implementation details, do not rely on anything below here. ==
+// =================================================================
+
+// Some builds do not support C++14 fully yet, using C++11 constexpr technique.
+constexpr bool HasPotentialConditionalOperator(const char* lhs, int index) {
+ return (index == -1 ? false
+ : (lhs[index] == '?' ? true
+ : HasPotentialConditionalOperator(
+ lhs, index - 1)));
+}
+
+#define CRUBIT_STATUS_MACROS_IMPL_ASSIGN_OR_RETURN_(statusor, lhs, rexpr, \
+ error_expression) \
+ auto statusor = (rexpr); \
+ if (ABSL_PREDICT_FALSE(!statusor.ok())) { \
+ error_expression; \
+ } \
+ { \
+ static_assert( \
+ #lhs[0] != '(' || #lhs[sizeof(#lhs) - 2] != ')' || \
+ !HasPotentialConditionalOperator(#lhs, sizeof(#lhs) - 2), \
+ "Identified potential conditional operator, consider not " \
+ "using CRUBIT_ASSIGN_OR_RETURN"); \
+ } \
+ CRUBIT_STATUS_MACROS_IMPL_UNPARENTHESIZE_IF_PARENTHESIZED(lhs) = \
+ std::move(statusor).ValueOrDie()
+
+// Internal helpers for macro expansion.
+#define CRUBIT_STATUS_MACROS_IMPL_EAT(...)
+#define CRUBIT_STATUS_MACROS_IMPL_REM(...) __VA_ARGS__
+#define CRUBIT_STATUS_MACROS_IMPL_EMPTY()
+
+// Internal helpers for emptyness arguments check.
+#define CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_INNER(...) \
+ CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_INNER_HELPER((__VA_ARGS__, 0, 1))
+// MSVC expands variadic macros incorrectly, so we need this extra indirection
+// to work around that (b/110959038).
+#define CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_INNER_HELPER(args) \
+ CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_INNER_I args
+#define CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_INNER_I(e0, e1, is_empty, ...) \
+ is_empty
+
+#define CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY(...) \
+ CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_I(__VA_ARGS__)
+#define CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_I(...) \
+ CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY_INNER(_, ##__VA_ARGS__)
+
+// Internal helpers for if statement.
+#define CRUBIT_STATUS_MACROS_IMPL_IF_1(_Then, _Else) _Then
+#define CRUBIT_STATUS_MACROS_IMPL_IF_0(_Then, _Else) _Else
+#define CRUBIT_STATUS_MACROS_IMPL_IF(_Cond, _Then, _Else) \
+ CRUBIT_STATUS_MACROS_IMPL_CONCAT_(CRUBIT_STATUS_MACROS_IMPL_IF_, _Cond) \
+ (_Then, _Else)
+
+// Expands to 1 if the input is parenthesized. Otherwise expands to 0.
+#define CRUBIT_STATUS_MACROS_IMPL_IS_PARENTHESIZED(...) \
+ CRUBIT_STATUS_MACROS_IMPL_IS_EMPTY(CRUBIT_STATUS_MACROS_IMPL_EAT __VA_ARGS__)
+
+// If the input is parenthesized, removes the parentheses. Otherwise expands to
+// the input unchanged.
+#define CRUBIT_STATUS_MACROS_IMPL_UNPARENTHESIZE_IF_PARENTHESIZED(...) \
+ CRUBIT_STATUS_MACROS_IMPL_IF( \
+ CRUBIT_STATUS_MACROS_IMPL_IS_PARENTHESIZED(__VA_ARGS__), \
+ CRUBIT_STATUS_MACROS_IMPL_REM, CRUBIT_STATUS_MACROS_IMPL_EMPTY()) \
+ __VA_ARGS__
+
+// Internal helper for concatenating macro values.
+#define CRUBIT_STATUS_MACROS_IMPL_CONCAT_INNER_(x, y) x##y
+#define CRUBIT_STATUS_MACROS_IMPL_CONCAT_(x, y) \
+ CRUBIT_STATUS_MACROS_IMPL_CONCAT_INNER_(x, y)
+
+// The GNU compiler emits a warning for code like:
+//
+// if (foo)
+// if (bar) { } else baz;
+//
+// because it thinks you might want the else to bind to the first if. This
+// leads to problems with code like:
+//
+// if (do_expr) CRUBIT_RETURN_IF_ERROR(expr) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#define CRUBIT_STATUS_MACROS_IMPL_ELSE_BLOCKER_ \
+ switch (0) \
+ case 0: \
+ default: // NOLINT
+
+#endif // CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STATUS_MACROS_H_