Replace LOG(FATAL) and DCHECK with LLVM equivalents.

At a high-level the changes in this CL look like this:
*) LOG(FATAL) => llvm::report_fatal_error + llvm::formatv
*) DCHECK => assert
*) CHECK => assert (this wouldn't preserve behavior in NDEBUG builds so
   this transformation is not applied in all the cases).

PiperOrigin-RevId: 435361199
diff --git a/rs_bindings_from_cc/ast_consumer.cc b/rs_bindings_from_cc/ast_consumer.cc
index aa92100..15ceac5 100644
--- a/rs_bindings_from_cc/ast_consumer.cc
+++ b/rs_bindings_from_cc/ast_consumer.cc
@@ -4,8 +4,8 @@
 
 #include "rs_bindings_from_cc/ast_consumer.h"
 
-#include "base/logging.h"
 #include "rs_bindings_from_cc/importer.h"
+#include "rs_bindings_from_cc/util/check.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/AST/ASTContext.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/Frontend/CompilerInstance.h"
 
@@ -19,7 +19,7 @@
     // There is nothing more for us to do here.
     return;
   }
-  CHECK(instance_.hasSema());
+  CRUBIT_CHECK(instance_.hasSema());
   Importer importer(invocation_, ast_context, instance_.getSema());
   importer.Import(ast_context.getTranslationUnitDecl());
 }
diff --git a/rs_bindings_from_cc/ast_convert.cc b/rs_bindings_from_cc/ast_convert.cc
index e05946d..b247651 100644
--- a/rs_bindings_from_cc/ast_convert.cc
+++ b/rs_bindings_from_cc/ast_convert.cc
@@ -4,10 +4,9 @@
 
 #include "rs_bindings_from_cc/ast_convert.h"
 
-#include <assert.h>
-
 #include "third_party/absl/functional/function_ref.h"
 #include "rs_bindings_from_cc/ir.h"
+#include "rs_bindings_from_cc/util/check.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/AST/Decl.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/AST/DeclCXX.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/Basic/Specifiers.h"
@@ -109,8 +108,9 @@
     case clang::AS_private:
       return kPrivate;
     case clang::AS_none:
-      // We should never be encoding a "none" access specifier in IR.
-      assert(false);
+      CRUBIT_CHECK(
+          false &&
+          "We should never be encoding a 'none' access specifier in IR.");
       // We have to return something. Conservatively return private so we don't
       // inadvertently make a private member variable accessible in Rust.
       return kPrivate;
diff --git a/rs_bindings_from_cc/importer.cc b/rs_bindings_from_cc/importer.cc
index 6b640c0..d2dfcc3 100644
--- a/rs_bindings_from_cc/importer.cc
+++ b/rs_bindings_from_cc/importer.cc
@@ -15,7 +15,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/logging.h"
 #include "third_party/absl/container/flat_hash_map.h"
 #include "third_party/absl/container/flat_hash_set.h"
 #include "third_party/absl/status/status.h"
@@ -28,6 +27,7 @@
 #include "rs_bindings_from_cc/ast_convert.h"
 #include "rs_bindings_from_cc/bazel_types.h"
 #include "rs_bindings_from_cc/ir.h"
+#include "rs_bindings_from_cc/util/check.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"
@@ -48,6 +48,7 @@
 #include "third_party/llvm/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/Support/Casting.h"
 #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"
 
@@ -167,8 +168,8 @@
                      base_path_element.Base->getType()->getAsCXXRecordDecl()))
                  .getQuantity()};
       }
-      DCHECK(!offset.hasValue() || *offset >= 0)
-          << "Concrete base classes should have non-negative offsets.";
+      CRUBIT_CHECK((!offset.hasValue() || *offset >= 0) &&
+                   "Concrete base classes should have non-negative offsets.");
       bases.push_back(
           BaseClass{.base_record_id = GenerateDeclId(base_record_decl),
                     .offset = offset});
@@ -496,9 +497,7 @@
   std::set<std::string> errors;
   auto add_error = [&errors, function_decl](std::string msg) {
     auto result = errors.insert(std::move(msg));
-    CHECK(result.second) << "Duplicated error message for "
-                         << function_decl->getNameAsString() << ": "
-                         << *result.first;
+    CRUBIT_CHECK(result.second && "Duplicated error message");
   };
   if (auto* method_decl =
           clang::dyn_cast<clang::CXXMethodDecl>(function_decl)) {
@@ -527,7 +526,8 @@
   }
 
   if (lifetimes) {
-    CHECK_EQ(lifetimes->param_lifetimes.size(), function_decl->getNumParams());
+    CRUBIT_CHECK(lifetimes->param_lifetimes.size() ==
+                 function_decl->getNumParams());
   }
   for (unsigned i = 0; i < function_decl->getNumParams(); ++i) {
     const clang::ParmVarDecl* param = function_decl->getParamDecl(i);
@@ -560,7 +560,7 @@
     }
 
     std::optional<Identifier> param_name = GetTranslatedIdentifier(param);
-    CHECK(param_name.has_value());  // No known cases where the above can fail.
+    CRUBIT_CHECK(param_name.has_value());  // No known failure cases.
     params.push_back({*param_type, *std::move(param_name)});
   }
 
@@ -596,7 +596,7 @@
   for (devtools_rust::Lifetime lifetime : all_lifetimes) {
     std::optional<llvm::StringRef> name =
         lifetime_symbol_table.LookupLifetime(lifetime);
-    CHECK(name.has_value());
+    CRUBIT_CHECK(name.has_value());
     lifetime_params.push_back(
         {.name = name->str(), .id = LifetimeId(lifetime.Id())});
   }
@@ -655,7 +655,11 @@
 
   std::optional<UnqualifiedIdentifier> translated_name =
       GetTranslatedName(function_decl);
-  CHECK(return_type.ok());  // Silence ClangTidy, checked above.
+
+  // Silence ClangTidy, checked above: calling `add_error` if
+  // `!return_type.ok()` and returning early if `!errors.empty()`.
+  CRUBIT_CHECK(return_type.ok());
+
   if (translated_name.has_value()) {
     return LookupResult(Func{
         .name = *translated_name,
@@ -870,10 +874,7 @@
 
   std::optional<Identifier> identifier =
       GetTranslatedIdentifier(typedef_name_decl);
-  if (!identifier.has_value()) {
-    // This should never happen.
-    LOG(FATAL) << "Couldn't get identifier for TypedefNameDecl";
-  }
+  CRUBIT_CHECK(identifier.has_value());  // This should never happen.
   std::optional<devtools_rust::TypeLifetimes> no_lifetimes;
   absl::StatusOr<MappedType> underlying_type =
       ConvertQualType(typedef_name_decl->getUnderlyingType(), no_lifetimes);
@@ -959,7 +960,7 @@
     clang::QualType pointee_type = type->getPointeeType();
     std::optional<LifetimeId> lifetime;
     if (lifetimes.has_value()) {
-      CHECK(!lifetimes->empty());
+      CRUBIT_CHECK(!lifetimes->empty());
       lifetime = LifetimeId(lifetimes->back().Id());
       lifetimes->pop_back();
     }
@@ -992,7 +993,7 @@
                                    std::move(mapped_return_type),
                                    std::move(mapped_param_types));
       } else {
-        DCHECK(type->isLValueReferenceType());
+        CRUBIT_CHECK(type->isLValueReferenceType());
         return MappedType::FuncRef(cc_call_conv, rs_abi, lifetime,
                                    std::move(mapped_return_type),
                                    std::move(mapped_param_types));
@@ -1005,7 +1006,7 @@
       return MappedType::PointerTo(std::move(mapped_pointee_type), lifetime,
                                    nullable);
     } else {
-      DCHECK(type->isLValueReferenceType());
+      CRUBIT_CHECK(type->isLValueReferenceType());
       return MappedType::LValueReferenceTo(std::move(mapped_pointee_type),
                                            lifetime);
     }
@@ -1170,10 +1171,12 @@
     case clang::DeclarationName::CXXOperatorName:
       switch (named_decl->getDeclName().getCXXOverloadedOperator()) {
         case clang::OO_None:
-          LOG(FATAL) << "No OO_None expected under CXXOperatorName branch";
+          CRUBIT_CHECK(false &&
+                       "No OO_None expected under CXXOperatorName branch");
           return std::nullopt;
         case clang::NUM_OVERLOADED_OPERATORS:
-          LOG(FATAL) << "No NUM_OVERLOADED_OPERATORS expected at runtime";
+          CRUBIT_CHECK(false &&
+                       "No NUM_OVERLOADED_OPERATORS expected at runtime");
           return std::nullopt;
           // clang-format off
         #define OVERLOADED_OPERATOR(name, spelling, ...)  \
@@ -1184,7 +1187,8 @@
         #undef OVERLOADED_OPERATOR
           // clang-format on
       }
-      LOG(FATAL) << "The `switch` above should handle all cases and `return`";
+      CRUBIT_CHECK(false && "The `switch` above should handle all cases");
+      return std::nullopt;
     default:
       // To be implemented later: CXXConversionFunctionName.
       // There are also e.g. literal operators, deduction guides, etc., but
diff --git a/rs_bindings_from_cc/importer.h b/rs_bindings_from_cc/importer.h
index 59c037d..4642c17 100644
--- a/rs_bindings_from_cc/importer.h
+++ b/rs_bindings_from_cc/importer.h
@@ -13,7 +13,6 @@
 #include <variant>
 #include <vector>
 
-#include "base/logging.h"
 #include "third_party/absl/container/flat_hash_map.h"
 #include "third_party/absl/container/flat_hash_set.h"
 #include "third_party/absl/status/statusor.h"
@@ -21,6 +20,7 @@
 #include "lifetime_annotations/lifetime_annotations.h"
 #include "rs_bindings_from_cc/bazel_types.h"
 #include "rs_bindings_from_cc/ir.h"
+#include "rs_bindings_from_cc/util/check.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/AST/ASTContext.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/AST/Decl.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/AST/Mangle.h"
@@ -48,8 +48,10 @@
           lifetime_context_(
               std::make_shared<devtools_rust::LifetimeAnnotationContext>()),
           header_targets_(header_targets) {
-      CHECK(!entry_headers_.empty());
-      CHECK(!header_targets_.empty());
+      // Caller should verify that the inputs are non-empty.
+      CRUBIT_CHECK(!entry_headers_.empty());
+      CRUBIT_CHECK(!header_targets_.empty());
+
       ir_.used_headers.insert(ir_.used_headers.end(), entry_headers_.begin(),
                               entry_headers.end());
       ir_.current_target = target_;
@@ -85,7 +87,7 @@
       : invocation_(invocation),
         ctx_(ctx),
         sema_(sema),
-        mangler_(ABSL_DIE_IF_NULL(ctx_.createMangleContext())) {}
+        mangler_(CRUBIT_DIE_IF_NULL(ctx_.createMangleContext())) {}
 
   // Import all visible declarations from a translation unit.
   void Import(clang::TranslationUnitDecl* decl);
diff --git a/rs_bindings_from_cc/ir.cc b/rs_bindings_from_cc/ir.cc
index 10099d4..6261631 100644
--- a/rs_bindings_from_cc/ir.cc
+++ b/rs_bindings_from_cc/ir.cc
@@ -13,9 +13,9 @@
 #include <variant>
 #include <vector>
 
-#include "base/integral_types.h"
 #include "third_party/absl/strings/string_view.h"
 #include "rs_bindings_from_cc/bazel_types.h"
+#include "rs_bindings_from_cc/util/check.h"
 #include "rs_bindings_from_cc/util/strong_int.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/Support/JSON.h"
 
@@ -117,12 +117,13 @@
   MappedType result = FuncRef(cc_call_conv, rs_abi, lifetime,
                               std::move(return_type), std::move(param_types));
 
-  DCHECK_EQ(result.cc_type.name, internal::kCcLValueRef);
+  CRUBIT_CHECK(result.cc_type.name == internal::kCcLValueRef);
   result.cc_type.name = std::string(internal::kCcPtr);
 
   RsType rs_func_ptr_type = std::move(result.rs_type);
-  DCHECK_EQ(rs_func_ptr_type.name.substr(0, internal::kRustFuncPtr.length()),
-            internal::kRustFuncPtr);
+  CRUBIT_CHECK(
+      rs_func_ptr_type.name.substr(0, internal::kRustFuncPtr.length()) ==
+      internal::kRustFuncPtr);
   result.rs_type =
       RsType{.name = "Option", .type_args = {std::move(rs_func_ptr_type)}};
 
diff --git a/rs_bindings_from_cc/ir.h b/rs_bindings_from_cc/ir.h
index 1dadd71..f43fab7 100644
--- a/rs_bindings_from_cc/ir.h
+++ b/rs_bindings_from_cc/ir.h
@@ -21,10 +21,9 @@
 #include <variant>
 #include <vector>
 
-#include "base/integral_types.h"
-#include "base/logging.h"
 #include "third_party/absl/strings/string_view.h"
 #include "rs_bindings_from_cc/bazel_types.h"
+#include "rs_bindings_from_cc/util/check.h"
 #include "rs_bindings_from_cc/util/strong_int.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/ADT/APSInt.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/ADT/Optional.h"
@@ -247,7 +246,7 @@
  public:
   explicit Identifier(std::string identifier)
       : identifier_(std::move(identifier)) {
-    CHECK(!identifier_.empty()) << "Identifier name cannot be empty.";
+    CRUBIT_CHECK(!identifier_.empty());
   }
 
   absl::string_view Ident() const { return identifier_; }
@@ -268,8 +267,7 @@
 class IntegerConstant {
  public:
   explicit IntegerConstant(const llvm::APSInt& value) {
-    CHECK(value.getSignificantBits() <= 64)
-        << "enumerator value unexpectedly had more than 64 bits";
+    CRUBIT_CHECK(value.getSignificantBits() <= 64);
     is_negative_ = value < 0;
     wrapped_value_ = static_cast<uint64_t>(value.getExtValue());
   }
@@ -289,7 +287,7 @@
 class Operator {
  public:
   explicit Operator(std::string name) : name_(std::move(name)) {
-    CHECK(!name_.empty()) << "Operator name cannot be empty.";
+    CRUBIT_CHECK(!name_.empty());
   }
 
   absl::string_view Name() const { return name_; }
diff --git a/rs_bindings_from_cc/ir_from_cc.cc b/rs_bindings_from_cc/ir_from_cc.cc
index cc62eea..db8556c 100644
--- a/rs_bindings_from_cc/ir_from_cc.cc
+++ b/rs_bindings_from_cc/ir_from_cc.cc
@@ -19,6 +19,7 @@
 #include "rs_bindings_from_cc/frontend_action.h"
 #include "rs_bindings_from_cc/importer.h"
 #include "rs_bindings_from_cc/ir.h"
+#include "rs_bindings_from_cc/util/check.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/Basic/FileManager.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/Basic/FileSystemOptions.h"
 #include "third_party/llvm/llvm-project/clang/include/clang/Frontend/FrontendAction.h"
@@ -38,6 +39,10 @@
         virtual_headers_contents,
     absl::flat_hash_map<const HeaderName, const BlazeLabel> headers_to_targets,
     absl::Span<const absl::string_view> args) {
+  // Caller should verify that the inputs are not empty.
+  CRUBIT_CHECK(!extra_source_code.empty() || !public_headers.empty());
+  CRUBIT_CHECK(!extra_source_code.empty() || !headers_to_targets.empty());
+
   std::vector<HeaderName> entrypoint_headers(public_headers.begin(),
                                              public_headers.end());
   clang::tooling::FileContentMappings file_contents;
diff --git a/rs_bindings_from_cc/json_from_cc.cc b/rs_bindings_from_cc/json_from_cc.cc
index b1df4a4..ccd4391 100644
--- a/rs_bindings_from_cc/json_from_cc.cc
+++ b/rs_bindings_from_cc/json_from_cc.cc
@@ -4,7 +4,6 @@
 
 #include <string>
 
-#include "base/logging.h"
 #include "third_party/absl/status/statusor.h"
 #include "rs_bindings_from_cc/bazel_types.h"
 #include "rs_bindings_from_cc/ffi_types.h"
@@ -38,7 +37,10 @@
   // this from tests, which are ok to just fail. Clang has already printed error
   // messages. If we start using this for production, then we should bridge the
   // error code into Rust.
-  CHECK(ir.ok()) << "- IrFromCc reported an error: " << ir.status().message();
+  if (!ir.ok()) {
+    llvm::report_fatal_error(llvm::formatv("IrFromCc reported an error: {0}",
+                                           ir.status().message()));
+  }
   std::string json = llvm::formatv("{0}", ir->ToJson());
   return AllocFfiU8SliceBox(MakeFfiU8Slice(json));
 }
diff --git a/rs_bindings_from_cc/rs_bindings_from_cc.cc b/rs_bindings_from_cc/rs_bindings_from_cc.cc
index 1060f6c..4a2a0e2 100644
--- a/rs_bindings_from_cc/rs_bindings_from_cc.cc
+++ b/rs_bindings_from_cc/rs_bindings_from_cc.cc
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/init_google.h"
-#include "base/logging.h"
 #include "third_party/absl/container/flat_hash_map.h"
 #include "third_party/absl/status/status.h"
 #include "third_party/absl/status/statusor.h"
diff --git a/rs_bindings_from_cc/util/check.h b/rs_bindings_from_cc/util/check.h
new file mode 100644
index 0000000..581738b
--- /dev/null
+++ b/rs_bindings_from_cc/util/check.h
@@ -0,0 +1,36 @@
+// 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
+
+#ifndef CRUBIT_RS_BINDINGS_FROM_CC_UTIL_CHECK_H_
+#define CRUBIT_RS_BINDINGS_FROM_CC_UTIL_CHECK_H_
+
+#include "third_party/absl/base/attributes.h"
+#include "third_party/absl/base/optimization.h"
+#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/ErrorHandling.h"
+#include "third_party/llvm/llvm-project/llvm/include/llvm/Support/FormatVariadic.h"
+
+#define CRUBIT_CHECK(condition)                                           \
+  do {                                                                    \
+    if (ABSL_PREDICT_FALSE(!(condition))) {                               \
+      ::llvm::report_fatal_error(                                         \
+          ::llvm::formatv("CRUBIT_CHECK failure: {0}:{1}: {2}", __FILE__, \
+                          __LINE__, #condition));                         \
+    }                                                                     \
+  } while (false)
+
+namespace rs_bindings_from_cc {
+template <typename T>
+ABSL_MUST_USE_RESULT T DieIfNull(const char* file, int line,
+                                 const char* exprtext, T&& t) {
+  if (ABSL_PREDICT_FALSE(t == nullptr)) {
+    ::llvm::report_fatal_error(llvm::formatv(
+        "CRUBIT_DIE_IF_NULL failure: {0}:{1}: {2}", file, line, exprtext));
+  }
+  return std::forward<T>(t);
+}
+}  // namespace rs_bindings_from_cc
+#define CRUBIT_DIE_IF_NULL(value) \
+  ::rs_bindings_from_cc::DieIfNull(__FILE__, __LINE__, #value, (value))
+
+#endif  // CRUBIT_RS_BINDINGS_FROM_CC_UTIL_CHECK_H_