[clang] [llvm] [FlowSensitive] [StatusOr] [1/N] Add minimal model (PR #162932)

Florian Mayer via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 10 16:33:48 PDT 2025


https://github.com/fmayer updated https://github.com/llvm/llvm-project/pull/162932

>From 92d4136ee576acf006df02d0f28d23e5870db646 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Fri, 10 Oct 2025 15:15:03 -0700
Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.4
---
 .../Models/UncheckedStatusOrAccessModel.h     |  114 +
 .../FlowSensitive/Models/CMakeLists.txt       |    1 +
 .../Models/UncheckedStatusOrAccessModel.cpp   |  284 +
 .../Analysis/FlowSensitive/CMakeLists.txt     |    2 +
 .../UncheckedStatusOrAccessModelTest.cpp      |   34 +
 ...ncheckedStatusOrAccessModelTestFixture.cpp | 5231 +++++++++++++++++
 .../UncheckedStatusOrAccessModelTestFixture.h |  159 +
 .../Analysis/FlowSensitive/Models/BUILD.gn    |    1 +
 .../unittests/Analysis/FlowSensitive/BUILD.gn |    2 +
 9 files changed, 5828 insertions(+)
 create mode 100644 clang/include/clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h
 create mode 100644 clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
 create mode 100644 clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTest.cpp
 create mode 100644 clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 create mode 100644 clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h

diff --git a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h
new file mode 100644
index 0000000000000..ed82907f4867d
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h
@@ -0,0 +1,114 @@
+//===- UncheckedStatusOrAccessModel.h -------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDSTATUSORACCESSMODEL_H
+#define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDSTATUSORACCESSMODEL_H
+
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/Value.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang::dataflow::statusor_model {
+
+// The helper functions exported here are for use of downstream vendor
+// extensions of this model.
+
+// Match declation of `absl::StatusOr<T>` and bind `T` to "T".
+clang::ast_matchers::DeclarationMatcher statusOrClass();
+// Match declation of `absl::Status`.
+clang::ast_matchers::DeclarationMatcher statusClass();
+// Match declaration of `absl::internal_statusor::OperatorBase`.
+clang::ast_matchers::DeclarationMatcher statusOrOperatorBaseClass();
+clang::ast_matchers::TypeMatcher possiblyAliasedStatusType();
+clang::ast_matchers::TypeMatcher possiblyAliasedStatusOrType();
+clang::ast_matchers::TypeMatcher statusOrType();
+
+// Get RecordStorageLocation for the `Status` contained in the `StatusOr`
+RecordStorageLocation &locForStatus(RecordStorageLocation &StatusOrLoc);
+// Get the StorageLocation OK boolean in the `Status`
+StorageLocation &locForOk(RecordStorageLocation &StatusLoc);
+// Get the OK boolean in the `Status`, and initialize it if necessary.
+BoolValue &valForOk(RecordStorageLocation &StatusLoc, Environment &Env);
+// Get synthetic fields for the types modelled by
+// `UncheckedStatusOrAccessModel`.
+llvm::StringMap<QualType> getSyntheticFields(QualType Ty, QualType StatusType,
+                                             const CXXRecordDecl &RD);
+
+// Initialize the synthetic fields of the `StatusOr`.
+// N.B. if it is already initialized, the value gets reset.
+BoolValue &initializeStatusOr(RecordStorageLocation &StatusOrLoc,
+                              Environment &Env);
+// Initialize the synthetic fields of the `Status`.
+// N.B. if it is already initialized, the value gets reset.
+BoolValue &initializeStatus(RecordStorageLocation &StatusLoc, Environment &Env);
+
+bool isRecordTypeWithName(QualType Type, llvm::StringRef TypeName);
+// Return true if `Type` is instantiation of `absl::StatusOr<T>`
+bool isStatusOrType(QualType Type);
+// Return true if `Type` is `absl::Status`
+bool isStatusType(QualType Type);
+
+// Get `QualType` for `absl::Status`, or default-constructed
+// QualType if it does not exist.
+QualType findStatusType(const ASTContext &Ctx);
+
+struct UncheckedStatusOrAccessModelOptions {};
+
+// Dataflow analysis that discovers unsafe uses of StatusOr values.
+class UncheckedStatusOrAccessModel
+    : public DataflowAnalysis<UncheckedStatusOrAccessModel, NoopLattice> {
+public:
+  explicit UncheckedStatusOrAccessModel(ASTContext &Ctx, Environment &Env);
+
+  static Lattice initialElement() { return {}; }
+
+  void transfer(const CFGElement &Elt, Lattice &L, Environment &Env);
+
+private:
+  CFGMatchSwitch<TransferState<Lattice>> TransferMatchSwitch;
+};
+
+using LatticeTransferState =
+    TransferState<UncheckedStatusOrAccessModel::Lattice>;
+
+// Extend the Builder with the transfer functions for
+// `UncheckedStatusOrAccessModel`. This is useful to write downstream models
+// that extend the model.
+CFGMatchSwitch<LatticeTransferState>
+buildTransferMatchSwitch(ASTContext &Ctx,
+                         CFGMatchSwitchBuilder<LatticeTransferState> Builder);
+
+class UncheckedStatusOrAccessDiagnoser {
+public:
+  explicit UncheckedStatusOrAccessDiagnoser(
+      UncheckedStatusOrAccessModelOptions Options = {});
+
+  llvm::SmallVector<SourceLocation> operator()(
+      const CFGElement &Elt, ASTContext &Ctx,
+      const TransferStateForDiagnostics<UncheckedStatusOrAccessModel::Lattice>
+          &State);
+
+private:
+  CFGMatchSwitch<const Environment, llvm::SmallVector<SourceLocation>>
+      DiagnoseMatchSwitch;
+};
+
+} // namespace clang::dataflow::statusor_model
+
+#endif // CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDSTATUSORACCESSMODEL_H
diff --git a/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt b/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
index 89bbe8791eb2c..d1236f5714881 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
+++ b/clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_clang_library(clangAnalysisFlowSensitiveModels
   ChromiumCheckModel.cpp
   UncheckedOptionalAccessModel.cpp
+  UncheckedStatusOrAccessModel.cpp
 
   LINK_LIBS
   clangAnalysis
diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
new file mode 100644
index 0000000000000..eab1db8330d5e
--- /dev/null
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
@@ -0,0 +1,284 @@
+//===- UncheckedStatusOrAccessModel.cpp -----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h"
+
+#include <cassert>
+#include <utility>
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeBase.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/Value.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang::dataflow::statusor_model {
+namespace {
+
+using ::clang::ast_matchers::MatchFinder;
+using ::clang::ast_matchers::StatementMatcher;
+
+} // namespace
+
+static void transferStatusOrOkCall(const CXXMemberCallExpr *Expr,
+                                   const MatchFinder::MatchResult &,
+                                   LatticeTransferState &State) {
+  RecordStorageLocation *StatusOrLoc =
+      getImplicitObjectLocation(*Expr, State.Env);
+  if (StatusOrLoc == nullptr)
+    return;
+
+  auto &OkVal = valForOk(locForStatus(*StatusOrLoc), State.Env);
+  State.Env.setValue(*Expr, OkVal);
+}
+
+static bool isStatusOrOperatorBaseType(QualType type) {
+  return isRecordTypeWithName(type, "absl::internal_statusor::OperatorBase");
+}
+
+static bool isSafeUnwrap(RecordStorageLocation *StatusOrLoc,
+                         const Environment &Env) {
+  if (!StatusOrLoc)
+    return false;
+  auto &StatusLoc = locForStatus(*StatusOrLoc);
+  auto *OkVal = Env.get<BoolValue>(locForOk(StatusLoc));
+  return OkVal != nullptr && Env.proves(OkVal->formula());
+}
+
+static ClassTemplateSpecializationDecl *
+getStatusOrBaseClass(const QualType &Ty) {
+  auto *RD = Ty->getAsCXXRecordDecl();
+  if (RD == nullptr)
+    return nullptr;
+  if (isStatusOrType(Ty) ||
+      // In case we are analyzing code under OperatorBase itself that uses
+      // operator* (e.g. to implement operator->).
+      isStatusOrOperatorBaseType(Ty))
+    return cast<ClassTemplateSpecializationDecl>(RD);
+  if (!RD->hasDefinition())
+    return nullptr;
+  for (const auto &Base : RD->bases())
+    if (auto *QT = getStatusOrBaseClass(Base.getType()))
+      return QT;
+  return nullptr;
+}
+
+static QualType getStatusOrValueType(ClassTemplateSpecializationDecl *TRD) {
+  return TRD->getTemplateArgs().get(0).getAsType();
+}
+
+static auto isStatusOrMemberCallWithName(llvm::StringRef member_name) {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return cxxMemberCallExpr(
+      on(expr(unless(cxxThisExpr()))),
+      callee(cxxMethodDecl(
+          hasName(member_name),
+          ofClass(anyOf(statusOrClass(), statusOrOperatorBaseClass())))));
+}
+
+static auto isStatusOrOperatorCallWithName(llvm::StringRef operator_name) {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return cxxOperatorCallExpr(
+      hasOverloadedOperatorName(operator_name),
+      callee(cxxMethodDecl(
+          ofClass(anyOf(statusOrClass(), statusOrOperatorBaseClass())))));
+}
+
+static auto valueCall() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return anyOf(isStatusOrMemberCallWithName("value"),
+               isStatusOrMemberCallWithName("ValueOrDie"));
+}
+
+static auto valueOperatorCall() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return expr(anyOf(isStatusOrOperatorCallWithName("*"),
+                    isStatusOrOperatorCallWithName("->")));
+}
+
+static auto
+buildDiagnoseMatchSwitch(const UncheckedStatusOrAccessModelOptions &Options) {
+  return CFGMatchSwitchBuilder<const Environment,
+                               llvm::SmallVector<SourceLocation>>()
+      // StatusOr::value, StatusOr::ValueOrDie
+      .CaseOfCFGStmt<CXXMemberCallExpr>(
+          valueCall(),
+          [](const CXXMemberCallExpr *E,
+             const ast_matchers::MatchFinder::MatchResult &,
+             const Environment &Env) {
+            if (!isSafeUnwrap(getImplicitObjectLocation(*E, Env), Env))
+              return llvm::SmallVector<SourceLocation>({E->getExprLoc()});
+            return llvm::SmallVector<SourceLocation>();
+          })
+
+      // StatusOr::operator*, StatusOr::operator->
+      .CaseOfCFGStmt<CXXOperatorCallExpr>(
+          valueOperatorCall(),
+          [](const CXXOperatorCallExpr *E,
+             const ast_matchers::MatchFinder::MatchResult &,
+             const Environment &Env) {
+            RecordStorageLocation *StatusOrLoc =
+                Env.get<RecordStorageLocation>(*E->getArg(0));
+            if (!isSafeUnwrap(StatusOrLoc, Env))
+              return llvm::SmallVector<SourceLocation>({E->getOperatorLoc()});
+            return llvm::SmallVector<SourceLocation>();
+          })
+      .Build();
+}
+
+UncheckedStatusOrAccessDiagnoser::UncheckedStatusOrAccessDiagnoser(
+    UncheckedStatusOrAccessModelOptions Options)
+    : DiagnoseMatchSwitch(buildDiagnoseMatchSwitch(Options)) {}
+
+llvm::SmallVector<SourceLocation> UncheckedStatusOrAccessDiagnoser::operator()(
+    const CFGElement &Elt, ASTContext &Ctx,
+    const TransferStateForDiagnostics<UncheckedStatusOrAccessModel::Lattice>
+        &State) {
+  return DiagnoseMatchSwitch(Elt, Ctx, State.Env);
+}
+
+BoolValue &initializeStatus(RecordStorageLocation &StatusLoc,
+                            Environment &Env) {
+  auto &OkVal = Env.makeAtomicBoolValue();
+  Env.setValue(locForOk(StatusLoc), OkVal);
+  return OkVal;
+}
+
+BoolValue &initializeStatusOr(RecordStorageLocation &StatusOrLoc,
+                              Environment &Env) {
+  return initializeStatus(locForStatus(StatusOrLoc), Env);
+}
+
+clang::ast_matchers::DeclarationMatcher statusOrClass() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return classTemplateSpecializationDecl(
+      hasName("absl::StatusOr"),
+      hasTemplateArgument(0, refersToType(type().bind("T"))));
+}
+
+clang::ast_matchers::DeclarationMatcher statusClass() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return cxxRecordDecl(hasName("absl::Status"));
+}
+
+clang::ast_matchers::DeclarationMatcher statusOrOperatorBaseClass() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return classTemplateSpecializationDecl(
+      hasName("absl::internal_statusor::OperatorBase"));
+}
+
+clang::ast_matchers::TypeMatcher possiblyAliasedStatusOrType() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(statusOrClass())));
+}
+
+clang::ast_matchers::TypeMatcher possiblyAliasedStatusType() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return hasUnqualifiedDesugaredType(recordType(hasDeclaration(statusClass())));
+}
+
+clang::ast_matchers::TypeMatcher statusOrType() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return hasCanonicalType(qualType(hasDeclaration(statusOrClass())));
+}
+
+bool isRecordTypeWithName(QualType Type, llvm::StringRef TypeName) {
+  return Type->isRecordType() &&
+         Type->getAsCXXRecordDecl()->getQualifiedNameAsString() == TypeName;
+}
+
+bool isStatusOrType(QualType Type) {
+  return isRecordTypeWithName(Type, "absl::StatusOr");
+}
+
+bool isStatusType(QualType Type) {
+  return isRecordTypeWithName(Type, "absl::Status");
+}
+
+llvm::StringMap<QualType> getSyntheticFields(QualType Ty, QualType StatusType,
+                                             const CXXRecordDecl &RD) {
+  if (auto *TRD = getStatusOrBaseClass(Ty))
+    return {{"status", StatusType}, {"value", getStatusOrValueType(TRD)}};
+  if (isStatusType(Ty) || (RD.hasDefinition() &&
+                           RD.isDerivedFrom(StatusType->getAsCXXRecordDecl())))
+    return {{"ok", RD.getASTContext().BoolTy}};
+  return {};
+}
+
+RecordStorageLocation &locForStatus(RecordStorageLocation &StatusOrLoc) {
+  return cast<RecordStorageLocation>(StatusOrLoc.getSyntheticField("status"));
+}
+
+StorageLocation &locForOk(RecordStorageLocation &StatusLoc) {
+  return StatusLoc.getSyntheticField("ok");
+}
+
+BoolValue &valForOk(RecordStorageLocation &StatusLoc, Environment &Env) {
+  if (auto *Val = Env.get<BoolValue>(locForOk(StatusLoc)))
+    return *Val;
+  return initializeStatus(StatusLoc, Env);
+}
+
+CFGMatchSwitch<LatticeTransferState>
+buildTransferMatchSwitch(ASTContext &Ctx,
+                         CFGMatchSwitchBuilder<LatticeTransferState> Builder) {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return std::move(Builder)
+      .CaseOfCFGStmt<CXXMemberCallExpr>(isStatusOrMemberCallWithName("ok"),
+                                        transferStatusOrOkCall)
+      .Build();
+}
+
+QualType findStatusType(const ASTContext &Ctx) {
+  for (Type *Ty : Ctx.getTypes())
+    if (isStatusType(QualType(Ty, 0)))
+      return QualType(Ty, 0);
+
+  return QualType();
+}
+
+UncheckedStatusOrAccessModel::UncheckedStatusOrAccessModel(ASTContext &Ctx,
+                                                           Environment &Env)
+    : DataflowAnalysis<UncheckedStatusOrAccessModel,
+                       UncheckedStatusOrAccessModel::Lattice>(Ctx),
+      TransferMatchSwitch(buildTransferMatchSwitch(Ctx, {})) {
+  QualType StatusType = findStatusType(Ctx);
+  Env.getDataflowAnalysisContext().setSyntheticFieldCallback(
+      [StatusType](QualType Ty) -> llvm::StringMap<QualType> {
+        CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+        if (RD == nullptr)
+          return {};
+
+        if (auto Fields = getSyntheticFields(Ty, StatusType, *RD);
+            !Fields.empty())
+          return Fields;
+        return {};
+      });
+}
+
+void UncheckedStatusOrAccessModel::transfer(const CFGElement &Elt, Lattice &L,
+                                            Environment &Env) {
+  LatticeTransferState State(L, Env);
+  TransferMatchSwitch(Elt, getASTContext(), State);
+}
+
+} // namespace clang::dataflow::statusor_model
diff --git a/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt b/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
index 3bd4a6e21bee7..0fd136fa77ca9 100644
--- a/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
+++ b/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
@@ -24,6 +24,8 @@ add_clang_unittest(ClangAnalysisFlowSensitiveTests
   TransferTest.cpp
   TypeErasedDataflowAnalysisTest.cpp
   UncheckedOptionalAccessModelTest.cpp
+  UncheckedStatusOrAccessModelTest.cpp
+  UncheckedStatusOrAccessModelTestFixture.cpp
   ValueTest.cpp
   WatchedLiteralsSolverTest.cpp
   CLANG_LIBS
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTest.cpp
new file mode 100644
index 0000000000000..07d3f2412e842
--- /dev/null
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTest.cpp
@@ -0,0 +1,34 @@
+//===- UncheckedStatusOrAccessModelTest.cpp -------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <utility>
+
+#include "UncheckedStatusOrAccessModelTestFixture.h"
+#include "clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h"
+#include "gtest/gtest.h"
+
+namespace clang::dataflow::statusor_model {
+namespace {
+
+INSTANTIATE_TEST_SUITE_P(
+    UncheckedStatusOrAccessModelTest, UncheckedStatusOrAccessModelTest,
+    testing::Values(
+        std::make_pair(new UncheckedStatusOrAccessModelTestExecutor<
+                           UncheckedStatusOrAccessModel>(),
+                       UncheckedStatusOrAccessModelTestAliasKind::kUnaliased),
+        std::make_pair(
+            new UncheckedStatusOrAccessModelTestExecutor<
+                UncheckedStatusOrAccessModel>(),
+            UncheckedStatusOrAccessModelTestAliasKind::kPartiallyAliased),
+        std::make_pair(
+            new UncheckedStatusOrAccessModelTestExecutor<
+                UncheckedStatusOrAccessModel>(),
+            UncheckedStatusOrAccessModelTestAliasKind::kFullyAliased)));
+} // namespace
+
+} // namespace clang::dataflow::statusor_model
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
new file mode 100644
index 0000000000000..af30e98c51c56
--- /dev/null
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -0,0 +1,5231 @@
+//===- UncheckedStatusOrAccessModelTestFixture.cpp ------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "UncheckedStatusOrAccessModelTestFixture.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+namespace clang::dataflow::statusor_model {
+namespace {
+
+static constexpr const char *kAbslDefsHeader = R"cc(
+  // Contains minimal mock declarations of common entities from //base, //util
+  // and //testing.
+
+#pragma clang system_header
+
+#ifndef BASE_DEFS_H_
+#define BASE_DEFS_H_
+
+#include "absl_type_traits.h"
+#include "std_type_traits.h"
+#include "stdlib_defs.h"
+#include "string_defs.h"
+
+  namespace absl {
+  struct in_place_t {};
+
+  constexpr in_place_t in_place;
+
+  struct nullopt_t {
+    constexpr explicit nullopt_t() {}
+  };
+
+  constexpr nullopt_t nullopt;
+  }  // namespace absl
+
+  namespace std {
+
+  struct in_place_t {};
+
+  constexpr in_place_t in_place;
+
+  struct nullopt_t {
+    constexpr explicit nullopt_t() {}
+  };
+
+  constexpr nullopt_t nullopt;
+
+  template <class _Tp>
+  struct __optional_destruct_base {
+    constexpr void reset() noexcept;
+  };
+
+  template <class _Tp>
+  struct __optional_storage_base : __optional_destruct_base<_Tp> {
+    constexpr bool has_value() const noexcept;
+  };
+
+  template <typename _Tp>
+  class optional : private __optional_storage_base<_Tp> {
+    using __base = __optional_storage_base<_Tp>;
+
+   public:
+    using value_type = _Tp;
+
+   private:
+    struct _CheckOptionalArgsConstructor {
+      template <class _Up>
+      static constexpr bool __enable_implicit() {
+        return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
+      }
+
+      template <class _Up>
+      static constexpr bool __enable_explicit() {
+        return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
+      }
+    };
+    template <class _Up>
+    using _CheckOptionalArgsCtor =
+        _If<_IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
+                _IsNotSame<__uncvref_t<_Up>, optional>::value,
+            _CheckOptionalArgsConstructor, __check_tuple_constructor_fail>;
+    template <class _QualUp>
+    struct _CheckOptionalLikeConstructor {
+      template <class _Up, class _Opt = optional<_Up>>
+      using __check_constructible_from_opt =
+          _Or<is_constructible<_Tp, _Opt&>, is_constructible<_Tp, _Opt const&>,
+              is_constructible<_Tp, _Opt&&>,
+              is_constructible<_Tp, _Opt const&&>, is_convertible<_Opt&, _Tp>,
+              is_convertible<_Opt const&, _Tp>, is_convertible<_Opt&&, _Tp>,
+              is_convertible<_Opt const&&, _Tp>>;
+      template <class _Up, class _QUp = _QualUp>
+      static constexpr bool __enable_implicit() {
+        return is_convertible<_QUp, _Tp>::value &&
+               !__check_constructible_from_opt<_Up>::value;
+      }
+      template <class _Up, class _QUp = _QualUp>
+      static constexpr bool __enable_explicit() {
+        return !is_convertible<_QUp, _Tp>::value &&
+               !__check_constructible_from_opt<_Up>::value;
+      }
+    };
+
+    template <class _Up, class _QualUp>
+    using _CheckOptionalLikeCtor =
+        _If<_And<_IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>>::value,
+            _CheckOptionalLikeConstructor<_QualUp>,
+            __check_tuple_constructor_fail>;
+    template <class _Up, class _QualUp>
+    using _CheckOptionalLikeAssign =
+        _If<_And<_IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>,
+                 is_assignable<_Tp&, _QualUp>>::value,
+            _CheckOptionalLikeConstructor<_QualUp>,
+            __check_tuple_constructor_fail>;
+
+   public:
+    constexpr optional() noexcept {}
+    constexpr optional(const optional&) = default;
+    constexpr optional(optional&&) = default;
+    constexpr optional(nullopt_t) noexcept {}
+
+    template <class _InPlaceT, class... _Args,
+              class = std::enable_if_t<
+                  _And<_IsSame<_InPlaceT, in_place_t>,
+                       is_constructible<value_type, _Args...>>::value>>
+    constexpr explicit optional(_InPlaceT, _Args&&... __args);
+
+    template <class _Up, class... _Args,
+              class = std::enable_if_t<is_constructible_v<
+                  value_type, initializer_list<_Up>&, _Args...>>>
+    constexpr explicit optional(in_place_t, initializer_list<_Up> __il,
+                                _Args&&... __args);
+
+    template <class _Up = value_type,
+              std::enable_if_t<_CheckOptionalArgsCtor<
+                                   _Up>::template __enable_implicit<_Up>(),
+                               int> = 0>
+    constexpr optional(_Up&& __v);
+
+    template <class _Up, std::enable_if_t<_CheckOptionalArgsCtor<_Up>::
+                                              template __enable_explicit<_Up>(),
+                                          int> = 0>
+    constexpr explicit optional(_Up&& __v);
+
+    template <class _Up,
+              std::enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::
+                                   template __enable_implicit<_Up>(),
+                               int> = 0>
+    constexpr optional(const optional<_Up>& __v);
+
+    template <class _Up,
+              std::enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::
+                                   template __enable_explicit<_Up>(),
+                               int> = 0>
+    constexpr explicit optional(const optional<_Up>& __v);
+
+    template <class _Up, std::enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
+                                              template __enable_implicit<_Up>(),
+                                          int> = 0>
+    constexpr optional(optional<_Up>&& __v);
+
+    template <class _Up, std::enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
+                                              template __enable_explicit<_Up>(),
+                                          int> = 0>
+    constexpr explicit optional(optional<_Up>&& __v);
+
+    constexpr optional& operator=(nullopt_t) noexcept;
+
+    optional& operator=(const optional&);
+
+    optional& operator=(optional&&);
+
+    template <class _Up = value_type,
+              class = std::enable_if_t<
+                  _And<_IsNotSame<__uncvref_t<_Up>, optional>,
+                       _Or<_IsNotSame<__uncvref_t<_Up>, value_type>,
+                           _Not<is_scalar<value_type>>>,
+                       is_constructible<value_type, _Up>,
+                       is_assignable<value_type&, _Up>>::value>>
+    constexpr optional& operator=(_Up&& __v);
+
+    template <class _Up,
+              std::enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::
+                                   template __enable_assign<_Up>(),
+                               int> = 0>
+    constexpr optional& operator=(const optional<_Up>& __v);
+
+    template <class _Up, std::enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::
+                                              template __enable_assign<_Up>(),
+                                          int> = 0>
+    constexpr optional& operator=(optional<_Up>&& __v);
+
+    const _Tp& operator*() const&;
+    _Tp& operator*() &;
+    const _Tp&& operator*() const&&;
+    _Tp&& operator*() &&;
+
+    const _Tp* operator->() const;
+    _Tp* operator->();
+
+    const _Tp& value() const&;
+    _Tp& value() &;
+    const _Tp&& value() const&&;
+    _Tp&& value() &&;
+
+    template <typename U>
+    constexpr _Tp value_or(U&& v) const&;
+    template <typename U>
+    _Tp value_or(U&& v) &&;
+
+    constexpr explicit operator bool() const noexcept;
+
+    using __base::has_value;
+
+    template <typename... Args>
+    _Tp& emplace(Args&&... args);
+
+    template <typename U, typename... Args>
+    _Tp& emplace(std::initializer_list<U> ilist, Args&&... args);
+
+    using __base::reset;
+
+    constexpr void swap(optional& __opt) noexcept;
+  };
+
+  template <class _Tp, class _Up>
+  constexpr std::enable_if_t<
+      is_convertible_v<decltype(declval<const _Tp&>() == declval<const _Up&>()),
+                       bool>,
+      bool>
+  operator==(const optional<_Tp>& __x, const optional<_Up>& __y);
+
+  template <class _Tp, class _Up>
+  constexpr std::enable_if_t<
+      is_convertible_v<decltype(declval<const _Tp&>() != declval<const _Up&>()),
+                       bool>,
+      bool>
+  operator!=(const optional<_Tp>& __x, const optional<_Up>& __y);
+
+  template <class _Tp>
+  constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept;
+
+  template <class _Tp>
+  constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept;
+
+  template <class _Tp>
+  constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept;
+
+  template <class _Tp>
+  constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept;
+
+  template <class _Tp, class _Up>
+  constexpr std::enable_if_t<
+      is_convertible_v<decltype(declval<const _Tp&>() == declval<const _Up&>()),
+                       bool>,
+      bool>
+  operator==(const optional<_Tp>& __x, const _Up& __v);
+
+  template <class _Tp, class _Up>
+  constexpr std::enable_if_t<
+      is_convertible_v<decltype(declval<const _Tp&>() == declval<const _Up&>()),
+                       bool>,
+      bool>
+  operator==(const _Tp& __v, const optional<_Up>& __x);
+
+  template <class _Tp, class _Up>
+  constexpr std::enable_if_t<
+      is_convertible_v<decltype(declval<const _Tp&>() != declval<const _Up&>()),
+                       bool>,
+      bool>
+  operator!=(const optional<_Tp>& __x, const _Up& __v);
+
+  template <class _Tp, class _Up>
+  constexpr std::enable_if_t<
+      is_convertible_v<decltype(declval<const _Tp&>() != declval<const _Up&>()),
+                       bool>,
+      bool>
+  operator!=(const _Tp& __v, const optional<_Up>& __x);
+
+  template <typename T>
+  constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
+    return optional<typename std::decay<T>::type>(std::forward<T>(v));
+  }
+
+  template <typename T, typename... Args>
+  constexpr optional<T> make_optional(Args&&... args) {
+    return optional<T>(in_place_t(), std::forward<Args>(args)...);
+  }
+
+  template <typename T, typename U, typename... Args>
+  constexpr optional<T> make_optional(std::initializer_list<U> il,
+                                      Args&&... args) {
+    return optional<T>(in_place_t(), il, std::forward<Args>(args)...);
+  }
+
+  }  // namespace std
+
+  namespace absl {
+
+#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))
+#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))
+
+  struct VLogSite final {
+    explicit constexpr VLogSite(const char* f);
+    bool IsEnabled(int level);
+  };
+
+  namespace log_internal {
+  class LogMessage {
+   public:
+    LogMessage();
+    LogMessage& stream();
+    LogMessage& InternalStream();
+    LogMessage& WithVerbosity(int verboselevel);
+    template <typename T>
+    LogMessage& operator<<(const T&);
+  };
+  class LogMessageFatal : public LogMessage {
+   public:
+    LogMessageFatal();
+    ~LogMessageFatal() __attribute__((noreturn));
+  };
+  class LogMessageQuietlyFatal : public LogMessage {
+   public:
+    LogMessageQuietlyFatal();
+    ~LogMessageQuietlyFatal() __attribute__((noreturn));
+  };
+  class Voidify final {
+   public:
+    // This has to be an operator with a precedence lower than << but higher
+    // than
+    // ?:
+    template <typename T>
+    void operator&&(const T&) const&& {}
+  };
+  }  // namespace log_internal
+  }  // namespace absl
+
+#ifndef NULL
+#define NULL __null
+#endif
+  extern "C" void abort() {}
+#define ABSL_LOG_INTERNAL_LOG_INFO ::absl::log_internal::LogMessage()
+#define ABSL_LOG_INTERNAL_LOG_WARNING ::absl::log_internal::LogMessage()
+#define ABSL_LOG_INTERNAL_LOG_ERROR ::absl::log_internal::LogMessage()
+#define ABSL_LOG_INTERNAL_LOG_FATAL ::absl::log_internal::LogMessageFatal()
+#define ABSL_LOG_INTERNAL_LOG_QFATAL \
+    ::absl::log_internal::LogMessageQuietlyFatal()
+#define LOG(severity) ABSL_LOG_INTERNAL_LOG_##severity.InternalStream()
+
+#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(lit) lit
+
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOG_INTERNAL_LOG_FATAL
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message) ABSL_LOG_INTERNAL_LOG_QFATAL
+
+#define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \
+    switch (0)                                             \
+    case 0:                                                \
+    default:                                               \
+      !(condition) ? (void)0 : ::absl::log_internal::Voidify() &&
+
+#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
+    ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+
+#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
+    ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+
+#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
+    ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+
+#define ABSL_CHECK_IMPL(condition, condition_text)                    \
+    ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS,                        \
+                                      ABSL_PREDICT_FALSE(!(condition))) \
+    ABSL_LOG_INTERNAL_CHECK(condition_text).InternalStream()
+
+#define ABSL_QCHECK_IMPL(condition, condition_text)                    \
+    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS,                        \
+                                       ABSL_PREDICT_FALSE(!(condition))) \
+    ABSL_LOG_INTERNAL_QCHECK(condition_text).InternalStream()
+
+#define CHECK(condition) ABSL_CHECK_IMPL((condition), #condition)
+#define DCHECK(condition) CHECK(condition)
+#define QCHECK(condition) ABSL_QCHECK_IMPL((condition), #condition)
+
+#define ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(x)
+
+#define VLOG_IS_ON(verbose_level)                               \
+    (ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(verbose_level)[]() \
+         ->::absl::VLogSite *                                     \
+     {                                                            \
+       static ::absl::VLogSite site(__FILE__);                    \
+       return &site;                                              \
+     }()                                                          \
+         ->IsEnabled(verbose_level))
+
+#define ABSL_LOG_IF_IMPL(severity, condition)                 \
+    ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
+        ABSL_LOG_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_VLOG_IMPL(verbose_level)                                        \
+    switch (const int absl_logging_internal_verbose_level = (verbose_level))   \
+    default:                                                                   \
+      ABSL_LOG_IF_IMPL(_INFO, VLOG_IS_ON(absl_logging_internal_verbose_level)) \
+          .WithVerbosity(absl_logging_internal_verbose_level)
+
+#define VLOG(severity) ABSL_VLOG_IMPL(severity)
+
+  namespace absl {
+
+  template <typename T>
+  class StatusOr;
+  class Status;
+
+  namespace status_internal {
+  std::string* MakeCheckFailString(const absl::Status* status,
+                                   const char* prefix);
+  }  // namespace status_internal
+
+  namespace log_internal {
+  template <class T>
+  const T& GetReferenceableValue(const T& t);
+  inline char GetReferenceableValue(char t) { return t; }
+  inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
+  inline signed char GetReferenceableValue(signed char t) { return t; }
+  inline short GetReferenceableValue(short t) { return t; }        // NOLINT
+  inline unsigned short GetReferenceableValue(unsigned short t) {  // NOLINT
+    return t;
+  }
+  inline int GetReferenceableValue(int t) { return t; }  // NOLINT
+  inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
+  inline long GetReferenceableValue(long t) { return t; }        // NOLINT
+  inline unsigned long GetReferenceableValue(unsigned long t) {  // NOLINT
+    return t;
+  }
+  inline long long GetReferenceableValue(long long t) { return t; }  // NOLINT
+  inline unsigned long long GetReferenceableValue(                   // NOLINT
+      unsigned long long t) {                                        // NOLINT
+    return t;
+  }
+  inline const absl::Status* AsStatus(const absl::Status& s) { return &s; }
+  template <typename T>
+  const absl::Status* AsStatus(const absl::StatusOr<T>& s) {
+    return &s.status();
+  }
+  }  // namespace log_internal
+  }  // namespace absl
+  // TODO(tkd): this still doesn't allow operator<<, unlike the real CHECK_
+  // macros.
+#define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val2)        \
+    while (char* _result = ::absl::log_internal::name##Impl(      \
+               ::absl::log_internal::GetReferenceableValue(val1), \
+               ::absl::log_internal::GetReferenceableValue(val2), \
+               #val1 " " #op " " #val2))                          \
+    (void)0
+#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val2)       \
+    while (char* _result = ::absl::log_internal::name##Impl(      \
+               ::absl::log_internal::GetReferenceableValue(val1), \
+               ::absl::log_internal::GetReferenceableValue(val2), \
+               #val1 " " #op " " #val2))                          \
+    (void)0
+  namespace absl {
+  namespace log_internal {
+  template <class T1, class T2>
+  char* Check_NEImpl(const T1& v1, const T2& v2, const char* names);
+  template <class T1, class T2>
+  char* Check_EQImpl(const T1& v1, const T2& v2, const char* names);
+  template <class T1, class T2>
+  char* Check_LTImpl(const T1& v1, const T2& v2, const char* names);
+
+#define CHECK_EQ(a, b) ABSL_LOG_INTERNAL_CHECK_OP(Check_EQ, ==, a, b)
+#define CHECK_NE(a, b) ABSL_LOG_INTERNAL_CHECK_OP(Check_NE, !=, a, b)
+#define CHECK_LT(a, b) ABSL_LOG_INTERNAL_CHECK_OP(Check_EQ, <, a, b)
+
+#define QCHECK_EQ(a, b) ABSL_LOG_INTERNAL_QCHECK_OP(Check_EQ, ==, a, b)
+#define QCHECK_NE(a, b) ABSL_LOG_INTERNAL_QCHECK_OP(Check_NE, !=, a, b)
+  }  // namespace log_internal
+  }  // namespace absl
+
+#define CHECK_NOTNULL(x) CHECK((x) != nullptr)
+
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) \
+    ::absl::log_internal::LogMessageFatal()
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
+    ::absl::log_internal::LogMessageQuietlyFatal()
+#define ABSL_LOG_INTERNAL_CHECK_OK(val)                                      \
+    for (::std::pair<const ::absl::Status*, ::std::string*>                    \
+             absl_log_internal_check_ok_goo;                                   \
+         absl_log_internal_check_ok_goo.first =                                \
+             ::absl::log_internal::AsStatus(val),                              \
+         absl_log_internal_check_ok_goo.second =                               \
+             ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok())     \
+                 ? nullptr                                                     \
+                 : ::absl::status_internal::MakeCheckFailString(               \
+                       absl_log_internal_check_ok_goo.first,                   \
+                       ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val " is OK")), \
+         !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)      \
+    ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_ok_goo.second)            \
+        .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OK(val)                                     \
+    for (::std::pair<const ::absl::Status*, ::std::string*>                    \
+             absl_log_internal_check_ok_goo;                                   \
+         absl_log_internal_check_ok_goo.first =                                \
+             ::absl::log_internal::AsStatus(val),                              \
+         absl_log_internal_check_ok_goo.second =                               \
+             ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok())     \
+                 ? nullptr                                                     \
+                 : ::absl::status_internal::MakeCheckFailString(               \
+                       absl_log_internal_check_ok_goo.first,                   \
+                       ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val " is OK")), \
+         !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)      \
+    ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_check_ok_goo.second)           \
+        .InternalStream()
+
+#define CHECK_OK(val) ABSL_LOG_INTERNAL_CHECK_OK(val)
+#define DCHECK_OK(val) ABSL_LOG_INTERNAL_CHECK_OK(val)
+#define QCHECK_OK(val) ABSL_LOG_INTERNAL_QCHECK_OK(val)
+
+  namespace testing {
+  struct AssertionResult {
+    template <typename T>
+    explicit AssertionResult(const T& res, bool enable_if = true) {}
+    ~AssertionResult();
+    operator bool() const;
+    template <typename T>
+    AssertionResult& operator<<(const T& value);
+    const char* failure_message() const;
+  };
+
+  class TestPartResult {
+   public:
+    enum Type { kSuccess, kNonFatalFailure, kFatalFailure, kSkip };
+  };
+
+  class Test {
+   public:
+    virtual ~Test() = default;
+
+   protected:
+    virtual void SetUp() {}
+  };
+
+  class Message {
+   public:
+    template <typename T>
+    Message& operator<<(const T& val);
+  };
+
+  namespace internal {
+  class AssertHelper {
+   public:
+    AssertHelper(TestPartResult::Type type, const char* file, int line,
+                 const char* message);
+    void operator=(const Message& message) const;
+  };
+
+  class EqHelper {
+   public:
+    template <typename T1, typename T2>
+    static AssertionResult Compare(const char* lhx, const char* rhx,
+                                   const T1& lhs, const T2& rhs);
+  };
+
+#define GTEST_IMPL_CMP_HELPER_(op_name)                                    \
+    template <typename T1, typename T2>                                      \
+    AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                       const T1& val1, const T2& val2);
+
+  GTEST_IMPL_CMP_HELPER_(NE)
+  GTEST_IMPL_CMP_HELPER_(LE)
+  GTEST_IMPL_CMP_HELPER_(LT)
+  GTEST_IMPL_CMP_HELPER_(GE)
+  GTEST_IMPL_CMP_HELPER_(GT)
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+  std::string GetBoolAssertionFailureMessage(
+      const AssertionResult& assertion_result, const char* expression_text,
+      const char* actual_predicate_value, const char* expected_predicate_value);
+
+  template <typename M>
+  class PredicateFormatterFromMatcher {
+   public:
+    template <typename T>
+    AssertionResult operator()(const char* value_text, const T& x) const;
+  };
+
+  template <typename M>
+  inline PredicateFormatterFromMatcher<M> MakePredicateFormatterFromMatcher(
+      M matcher) {
+    return PredicateFormatterFromMatcher<M>();
+  }
+  }  // namespace internal
+
+  namespace status {
+  namespace internal_status {
+  class IsOkMatcher {};
+
+  class StatusIsMatcher {};
+
+  class CanonicalStatusIsMatcher {};
+
+  template <typename M>
+  class IsOkAndHoldsMatcher {};
+
+  }  // namespace internal_status
+
+  internal_status::IsOkMatcher IsOk();
+
+  template <typename StatusCodeMatcher>
+  internal_status::StatusIsMatcher StatusIs(StatusCodeMatcher&& code_matcher);
+
+  template <typename StatusCodeMatcher>
+  internal_status::CanonicalStatusIsMatcher CanonicalStatusIs(
+      StatusCodeMatcher&& code_matcher);
+
+  template <typename InnerMatcher>
+  internal_status::IsOkAndHoldsMatcher<InnerMatcher> IsOkAndHolds(
+      InnerMatcher m);
+  }  // namespace status
+
+  class IsTrueMatcher {};
+  IsTrueMatcher IsTrue();
+
+  class IsFalseMatcher {};
+  IsFalseMatcher IsFalse();
+
+  }  // namespace testing
+
+  namespace absl_testing {
+  namespace status_internal {
+  class IsOkMatcher {};
+  template <typename M>
+  class IsOkAndHoldsMatcher {};
+  class StatusIsMatcher {};
+  class CanonicalStatusIsMatcher {};
+  }  // namespace status_internal
+  status_internal::IsOkMatcher IsOk();
+  template <typename InnerMatcher>
+  status_internal::IsOkAndHoldsMatcher<InnerMatcher> IsOkAndHolds(
+      InnerMatcher m);
+  template <typename StatusCodeMatcher>
+  status_internal::StatusIsMatcher StatusIs(StatusCodeMatcher&& code_matcher);
+
+  template <typename StatusCodeMatcher>
+  status_internal::CanonicalStatusIsMatcher CanonicalStatusIs(
+      StatusCodeMatcher&& code_matcher);
+  }  // namespace absl_testing
+
+  using testing::AssertionResult;
+#define EXPECT_TRUE(x)                                          \
+    switch (0)                                                    \
+    case 0:                                                       \
+    default:                                                      \
+      if (const AssertionResult gtest_ar_ = AssertionResult(x)) { \
+      } else /* NOLINT */                                         \
+        ::testing::Message()
+#define EXPECT_FALSE(x) EXPECT_TRUE(!(x))
+
+#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    switch (0)                          \
+    case 0:                             \
+    default:
+
+#define GTEST_ASSERT_(expression, on_failure)                   \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                 \
+    if (const ::testing::AssertionResult gtest_ar = (expression)) \
+      ;                                                           \
+    else                                                          \
+      on_failure(gtest_ar.failure_message())
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure) \
+    GTEST_ASSERT_(pred_format(#v1, v1), on_failure)
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure) \
+    GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), on_failure)
+#define GTEST_MESSAGE_AT_(file, line, message, result_type)             \
+    ::testing::internal::AssertHelper(result_type, file, line, message) = \
+        ::testing::Message()
+#define GTEST_MESSAGE_(message, result_type) \
+    GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+#define GTEST_FATAL_FAILURE_(message) \
+    return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+#define GTEST_NONFATAL_FAILURE_(message) \
+    GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+    GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+    GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+
+#define ASSERT_THAT(value, matcher)                                    \
+    ASSERT_PRED_FORMAT1(                                                 \
+        ::testing::internal::MakePredicateFormatterFromMatcher(matcher), \
+        value)
+#define ASSERT_OK(x) ASSERT_THAT(x, ::testing::status::IsOk())
+
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+    GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+    GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_THAT(value, matcher)                                    \
+    EXPECT_PRED_FORMAT1(                                                 \
+        ::testing::internal::MakePredicateFormatterFromMatcher(matcher), \
+        value)
+#define EXPECT_OK(expression) EXPECT_THAT(expression, ::testing::status::IsOk())
+
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                       \
+    if (const ::testing::AssertionResult gtest_ar_ =                    \
+            ::testing::AssertionResult(expression))                     \
+      ;                                                                 \
+    else                                                                \
+      fail(::testing::internal::GetBoolAssertionFailureMessage(         \
+               gtest_ar_, text, #actual, #expected)                     \
+               .c_str())
+#define GTEST_ASSERT_TRUE(condition) \
+    GTEST_TEST_BOOLEAN_(condition, #condition, false, true, GTEST_FATAL_FAILURE_)
+#define GTEST_ASSERT_FALSE(condition)                        \
+    GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                        GTEST_FATAL_FAILURE_)
+#define ASSERT_TRUE(condition) GTEST_ASSERT_TRUE(condition)
+#define ASSERT_FALSE(condition) GTEST_ASSERT_FALSE(condition)
+
+#define EXPECT_EQ(x, y) \
+    EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, x, y)
+#define EXPECT_NE(x, y) \
+    EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, x, y)
+#define EXPECT_LT(x, y) \
+    EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, x, y)
+#define EXPECT_GT(x, y) \
+    EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, x, y)
+#define EXPECT_LE(x, y) \
+    EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, x, y)
+#define EXPECT_GE(x, y) \
+    EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, x, y)
+
+#define ASSERT_EQ(x, y) \
+    ASSERT_PRED_FORMAT2(testing::internal::EqHelper::Compare, x, y)
+#define ASSERT_NE(x, y) \
+    ASSERT_PRED_FORMAT2(testing::internal::CmpHelperNE, x, y)
+#define ASSERT_LT(x, y) \
+    ASSERT_PRED_FORMAT2(testing::internal::CmpHelperLT, x, y)
+#define ASSERT_GT(x, y) \
+    ASSERT_PRED_FORMAT2(testing::internal::CmpHelperGT, x, y)
+#define ASSERT_LE(x, y) \
+    ASSERT_PRED_FORMAT2(testing::internal::CmpHelperLE, x, y)
+#define ASSERT_GE(x, y) \
+    ASSERT_PRED_FORMAT2(testing::internal::CmpHelperGE, x, y)
+
+#endif  // BASE_DEFS_H_
+)cc";
+
+constexpr const char *kAbslTypeTraitsHeader = R"cc(
+#pragma clang system_header
+
+#ifndef ABSL_TYPE_TRAITS_H_
+#define ABSL_TYPE_TRAITS_H_
+
+#include "std_type_traits.h"
+
+  namespace absl {
+
+  template <typename... Ts>
+  struct conjunction : std::true_type {};
+
+  template <typename T, typename... Ts>
+  struct conjunction<T, Ts...>
+      : std::conditional<T::value, conjunction<Ts...>, T>::type {};
+
+  template <typename T>
+  struct conjunction<T> : T {};
+
+  template <typename... Ts>
+  struct disjunction : std::false_type {};
+
+  template <typename T, typename... Ts>
+  struct disjunction<T, Ts...>
+      : std::conditional<T::value, T, disjunction<Ts...>>::type {};
+
+  template <typename T>
+  struct disjunction<T> : T {};
+
+  template <typename T>
+  struct negation : std::integral_constant<bool, !T::value> {};
+
+  template <typename T>
+  using remove_cv_t = typename std::remove_cv<T>::type;
+
+  template <typename T>
+  using remove_reference_t = typename std::remove_reference<T>::type;
+
+  template <typename T>
+  using decay_t = typename std::decay<T>::type;
+
+  template <bool B, typename T = void>
+  using enable_if_t = typename std::enable_if<B, T>::type;
+
+  template <bool B, typename T, typename F>
+  using conditional_t = typename std::conditional<B, T, F>::type;
+
+  }  // namespace absl
+
+#endif  // ABSL_TYPE_TRAITS_H_
+)cc";
+
+constexpr const char *kStdTypeTraitsHeader = R"cc(
+#pragma clang system_header
+
+#ifndef STD_TYPE_TRAITS_H_
+#define STD_TYPE_TRAITS_H_
+
+#include "stdlib_defs.h"
+
+  namespace std {
+
+  template <bool B, class T, class F>
+  struct conditional {
+    typedef T type;
+  };
+
+  template <class T, class F>
+  struct conditional<false, T, F> {
+    typedef F type;
+  };
+
+  template <bool B, class T, class F>
+  using conditional_t = typename conditional<B, T, F>::type;
+
+  template <class...>
+  struct conjunction : true_type {};
+
+  template <class B1>
+  struct conjunction<B1> : B1 {};
+
+  template <class B1, class... Bn>
+  struct conjunction<B1, Bn...>
+      : conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
+
+  template <bool B, class T = void>
+  struct enable_if {};
+
+  template <class T>
+  struct enable_if<true, T> {
+    typedef T type;
+  };
+
+  template <bool B, class T = void>
+  using enable_if_t = typename enable_if<B, T>::type;
+
+  template <class T, class U>
+  struct is_same : false_type {};
+
+  template <class T>
+  struct is_same<T, T> : true_type {};
+
+  template <class T, class U>
+  inline constexpr bool is_same_v = is_same<T, U>::value;
+
+  template <class T>
+  struct is_array : false_type {};
+
+  template <class T>
+  struct is_array<T[]> : true_type {};
+
+  template <class T, size_t N>
+  struct is_array<T[N]> : true_type {};
+
+  template <class T>
+  struct remove_extent {
+    typedef T type;
+  };
+
+  template <class T>
+  struct remove_extent<T[]> {
+    typedef T type;
+  };
+
+  template <class T, size_t N>
+  struct remove_extent<T[N]> {
+    typedef T type;
+  };
+
+  // primary template
+  template <class>
+  struct is_function : false_type {};
+
+  // specialization for regular functions
+  template <class Ret, class... Args>
+  struct is_function<Ret(Args...)> : true_type {};
+
+  namespace detail {
+
+  template <class T>
+  struct type_identity {
+    using type = T;
+  };  // or use type_identity (since C++20)
+
+  template <class T>
+  auto try_add_pointer(int)
+      -> type_identity<typename remove_reference<T>::type*>;
+  template <class T>
+  auto try_add_pointer(...) -> type_identity<T>;
+
+  }  // namespace detail
+
+  template <class T>
+  struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
+
+  template <class T>
+  struct remove_cv {
+    typedef T type;
+  };
+  template <class T>
+  struct remove_cv<const T> {
+    typedef T type;
+  };
+  template <class T>
+  struct remove_cv<volatile T> {
+    typedef T type;
+  };
+  template <class T>
+  struct remove_cv<const volatile T> {
+    typedef T type;
+  };
+
+  template <class T>
+  struct remove_const {
+    typedef T type;
+  };
+  template <class T>
+  struct remove_const<const T> {
+    typedef T type;
+  };
+
+  template <class T>
+  struct remove_volatile {
+    typedef T type;
+  };
+  template <class T>
+  struct remove_volatile<volatile T> {
+    typedef T type;
+  };
+
+  template <class T>
+  using remove_cv_t = typename remove_cv<T>::type;
+
+  template <class T>
+  using remove_const_t = typename remove_const<T>::type;
+
+  template <class T>
+  using remove_volatile_t = typename remove_volatile<T>::type;
+
+  template <class T>
+  struct decay {
+   private:
+    typedef typename remove_reference<T>::type U;
+
+   public:
+    typedef typename conditional<
+        is_array<U>::value, typename remove_extent<U>::type*,
+        typename conditional<is_function<U>::value,
+                             typename add_pointer<U>::type,
+                             typename remove_cv<U>::type>::type>::type type;
+  };
+
+  namespace detail {
+
+  template <class T>  // Note that `cv void&` is a substitution failure
+  auto try_add_lvalue_reference(int) -> type_identity<T&>;
+  template <class T>  // Handle T = cv void case
+  auto try_add_lvalue_reference(...) -> type_identity<T>;
+
+  template <class T>
+  auto try_add_rvalue_reference(int) -> type_identity<T&&>;
+  template <class T>
+  auto try_add_rvalue_reference(...) -> type_identity<T>;
+
+  }  // namespace detail
+
+  template <class T>
+  struct add_lvalue_reference
+      : decltype(detail::try_add_lvalue_reference<T>(0)) {};
+
+  template <class T>
+  struct add_rvalue_reference
+      : decltype(detail::try_add_rvalue_reference<T>(0)) {};
+
+  template <class T>
+  typename add_rvalue_reference<T>::type declval() noexcept;
+
+  template <class T>
+  struct is_void : is_same<void, typename remove_cv<T>::type> {};
+
+  namespace detail {
+
+  template <class T>
+  auto test_returnable(int)
+      -> decltype(void(static_cast<T (*)()>(nullptr)), true_type{});
+  template <class>
+  auto test_returnable(...) -> false_type;
+
+  template <class From, class To>
+  auto test_implicitly_convertible(int)
+      -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type{});
+  template <class, class>
+  auto test_implicitly_convertible(...) -> false_type;
+
+  }  // namespace detail
+
+  template <class From, class To>
+  struct is_convertible
+      : integral_constant<
+            bool, (decltype(detail::test_returnable<To>(0))::value &&
+                   decltype(detail::test_implicitly_convertible<From, To>(
+                       0))::value) ||
+                      (is_void<From>::value && is_void<To>::value)> {};
+
+  template <class From, class To>
+  inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
+
+  template <class...>
+  using void_t = void;
+
+  template <class, class T, class... Args>
+  struct is_constructible_ : false_type {};
+
+  template <class T, class... Args>
+  struct is_constructible_<void_t<decltype(T(declval<Args>()...))>, T, Args...>
+      : true_type {};
+
+  template <class T, class... Args>
+  using is_constructible = is_constructible_<void_t<>, T, Args...>;
+
+  template <class T, class... Args>
+  inline constexpr bool is_constructible_v =
+      is_constructible<T, Args...>::value;
+
+  template <class T>
+  struct is_reference : false_type {};
+  template <class T>
+  struct is_reference<T&> : true_type {};
+  template <class T>
+  struct is_reference<T&&> : true_type {};
+
+  template <class T>
+  inline constexpr bool is_reference_v = is_reference<T>::value;
+
+  template <class _Tp>
+  struct __uncvref {
+    typedef typename remove_cv<typename remove_reference<_Tp>::type>::type type;
+  };
+
+  template <class _Tp>
+  using __uncvref_t = typename __uncvref<_Tp>::type;
+
+  template <bool _Val>
+  using _BoolConstant = integral_constant<bool, _Val>;
+
+  template <class _Tp, class _Up>
+  using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+
+  template <class _Tp, class _Up>
+  using _IsNotSame = _BoolConstant<!__is_same(_Tp, _Up)>;
+
+  template <bool>
+  struct _MetaBase;
+  template <>
+  struct _MetaBase<true> {
+    template <class _Tp, class _Up>
+    using _SelectImpl = _Tp;
+    template <template <class...> class _FirstFn, template <class...> class,
+              class... _Args>
+    using _SelectApplyImpl = _FirstFn<_Args...>;
+    template <class _First, class...>
+    using _FirstImpl = _First;
+    template <class, class _Second, class...>
+    using _SecondImpl = _Second;
+    template <class _Result, class _First, class... _Rest>
+    using _OrImpl =
+        typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
+            template _OrImpl<_First, _Rest...>;
+  };
+
+  template <>
+  struct _MetaBase<false> {
+    template <class _Tp, class _Up>
+    using _SelectImpl = _Up;
+    template <template <class...> class, template <class...> class _SecondFn,
+              class... _Args>
+    using _SelectApplyImpl = _SecondFn<_Args...>;
+    template <class _Result, class...>
+    using _OrImpl = _Result;
+  };
+
+  template <bool _Cond, class _IfRes, class _ElseRes>
+  using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
+
+  template <class... _Rest>
+  using _Or = typename _MetaBase<sizeof...(_Rest) !=
+                                 0>::template _OrImpl<false_type, _Rest...>;
+
+  template <bool _Bp, class _Tp = void>
+  using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
+
+  template <class...>
+  using __expand_to_true = true_type;
+  template <class... _Pred>
+  __expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
+  template <class...>
+  false_type __and_helper(...);
+  template <class... _Pred>
+  using _And = decltype(__and_helper<_Pred...>(0));
+
+  template <class _Pred>
+  struct _Not : _BoolConstant<!_Pred::value> {};
+
+  struct __check_tuple_constructor_fail {
+    static constexpr bool __enable_explicit_default() { return false; }
+    static constexpr bool __enable_implicit_default() { return false; }
+    template <class...>
+    static constexpr bool __enable_explicit() {
+      return false;
+    }
+    template <class...>
+    static constexpr bool __enable_implicit() {
+      return false;
+    }
+  };
+
+  template <typename, typename _Tp>
+  struct __select_2nd {
+    typedef _Tp type;
+  };
+  template <class _Tp, class _Arg>
+  typename __select_2nd<decltype((declval<_Tp>() = declval<_Arg>())),
+                        true_type>::type
+  __is_assignable_test(int);
+  template <class, class>
+  false_type __is_assignable_test(...);
+  template <class _Tp, class _Arg,
+            bool = is_void<_Tp>::value || is_void<_Arg>::value>
+  struct __is_assignable_imp
+      : public decltype((__is_assignable_test<_Tp, _Arg>(0))) {};
+  template <class _Tp, class _Arg>
+  struct __is_assignable_imp<_Tp, _Arg, true> : public false_type {};
+  template <class _Tp, class _Arg>
+  struct is_assignable : public __is_assignable_imp<_Tp, _Arg> {};
+
+  template <class _Tp>
+  struct __libcpp_is_integral : public false_type {};
+  template <>
+  struct __libcpp_is_integral<bool> : public true_type {};
+  template <>
+  struct __libcpp_is_integral<char> : public true_type {};
+  template <>
+  struct __libcpp_is_integral<signed char> : public true_type {};
+  template <>
+  struct __libcpp_is_integral<unsigned char> : public true_type {};
+  template <>
+  struct __libcpp_is_integral<wchar_t> : public true_type {};
+  template <>
+  struct __libcpp_is_integral<short> : public true_type {};  // NOLINT
+  template <>
+  struct __libcpp_is_integral<unsigned short> : public true_type {};  // NOLINT
+  template <>
+  struct __libcpp_is_integral<int> : public true_type {};
+  template <>
+  struct __libcpp_is_integral<unsigned int> : public true_type {};
+  template <>
+  struct __libcpp_is_integral<long> : public true_type {};  // NOLINT
+  template <>
+  struct __libcpp_is_integral<unsigned long> : public true_type {};  // NOLINT
+  template <>
+  struct __libcpp_is_integral<long long> : public true_type {};  // NOLINT
+  template <>  // NOLINTNEXTLINE
+  struct __libcpp_is_integral<unsigned long long> : public true_type {};
+  template <class _Tp>
+  struct is_integral
+      : public __libcpp_is_integral<typename remove_cv<_Tp>::type> {};
+
+  template <class _Tp>
+  struct __libcpp_is_floating_point : public false_type {};
+  template <>
+  struct __libcpp_is_floating_point<float> : public true_type {};
+  template <>
+  struct __libcpp_is_floating_point<double> : public true_type {};
+  template <>
+  struct __libcpp_is_floating_point<long double> : public true_type {};
+  template <class _Tp>
+  struct is_floating_point
+      : public __libcpp_is_floating_point<typename remove_cv<_Tp>::type> {};
+
+  template <class _Tp>
+  struct is_arithmetic
+      : public integral_constant<bool, is_integral<_Tp>::value ||
+                                           is_floating_point<_Tp>::value> {};
+
+  template <class _Tp>
+  struct __libcpp_is_pointer : public false_type {};
+  template <class _Tp>
+  struct __libcpp_is_pointer<_Tp*> : public true_type {};
+  template <class _Tp>
+  struct is_pointer
+      : public __libcpp_is_pointer<typename remove_cv<_Tp>::type> {};
+
+  template <class _Tp>
+  struct __libcpp_is_member_pointer : public false_type {};
+  template <class _Tp, class _Up>
+  struct __libcpp_is_member_pointer<_Tp _Up::*> : public true_type {};
+  template <class _Tp>
+  struct is_member_pointer
+      : public __libcpp_is_member_pointer<typename remove_cv<_Tp>::type> {};
+
+  template <class _Tp>
+  struct __libcpp_union : public false_type {};
+  template <class _Tp>
+  struct is_union : public __libcpp_union<typename remove_cv<_Tp>::type> {};
+
+  struct __two {
+    char __lx[2];
+  };
+
+  namespace __is_class_imp {
+  template <class _Tp>
+  char __test(int _Tp::*);
+  template <class _Tp>
+  __two __test(...);
+  }  // namespace __is_class_imp
+  template <class _Tp>
+  struct is_class
+      : public integral_constant<bool,
+                                 sizeof(__is_class_imp::__test<_Tp>(0)) == 1 &&
+                                     !is_union<_Tp>::value> {};
+
+  template <class _Tp>
+  struct __is_nullptr_t_impl : public false_type {};
+  template <>
+  struct __is_nullptr_t_impl<nullptr_t> : public true_type {};
+  template <class _Tp>
+  struct __is_nullptr_t
+      : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type> {};
+  template <class _Tp>
+  struct is_null_pointer
+      : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type> {};
+
+  template <class _Tp>
+  struct is_enum
+      : public integral_constant<
+            bool, !is_void<_Tp>::value && !is_integral<_Tp>::value &&
+                      !is_floating_point<_Tp>::value && !is_array<_Tp>::value &&
+                      !is_pointer<_Tp>::value && !is_reference<_Tp>::value &&
+                      !is_member_pointer<_Tp>::value && !is_union<_Tp>::value &&
+                      !is_class<_Tp>::value && !is_function<_Tp>::value> {};
+
+  template <class _Tp>
+  struct is_scalar
+      : public integral_constant<
+            bool, is_arithmetic<_Tp>::value || is_member_pointer<_Tp>::value ||
+                      is_pointer<_Tp>::value || __is_nullptr_t<_Tp>::value ||
+                      is_enum<_Tp>::value> {};
+  template <>
+  struct is_scalar<nullptr_t> : public true_type {};
+
+  }  // namespace std
+
+#endif  // STD_TYPE_TRAITS_H_
+)cc";
+
+constexpr const char *kStdLibDefsHeader = R"cc(
+#pragma clang system_header
+
+#ifndef STDLIB_DEFS_H_
+#define STDLIB_DEFS_H_
+
+  // mock definitions of entities in the C++ standard library.
+  //
+  // mocks are only defined to the extent needed. Feel free to extend their
+  // definitions to suit your new tests.
+  //
+  // If you find that you need to break up this file into smaller files then
+  // break along the boundaries of the stdlib's header files.
+
+  // From stddef.h
+  typedef decltype(sizeof(char)) size_t;      // NOLINT
+  typedef decltype(sizeof(char*)) ptrdiff_t;  // NOLINT
+
+  // From stdint.h
+  typedef __SIZE_TYPE__ size_t;
+  typedef __UINT8_TYPE__ uint8_t;
+  typedef __UINT16_TYPE__ uint16_t;
+  typedef __UINT32_TYPE__ uint32_t;
+  typedef __UINT64_TYPE__ uint64_t;
+  typedef __INT8_TYPE__ int8_t;
+  typedef __INT16_TYPE__ int16_t;
+  typedef __INT32_TYPE__ int32_t;
+  typedef __INT64_TYPE__ int64_t;
+
+  namespace std {
+  // Our implementation of the standard library puts everything inside namespace
+  // std into an inline namespace, whose name should not be hardcoded in
+  // ClangTidy.
+  inline namespace __do_not_hardcode_in_clang_tidy {
+
+  using size_t = ::size_t;
+
+  template <typename T, T V>
+  struct integral_constant {
+    static constexpr T value = V;
+  };
+  using true_type = integral_constant<bool, true>;
+  using false_type = integral_constant<bool, false>;
+
+  using nullptr_t = decltype(nullptr);
+
+  template <typename T>
+  struct _NonDeducedImpl {
+    using type = T;
+  };
+  template <typename T>
+  using _NonDeduced = typename _NonDeducedImpl<T>::type;
+
+  // clang-format off
+template <typename T> struct remove_reference      { using type = T; };
+template <typename T> struct remove_reference<T&>  { using type = T; };
+template <typename T> struct remove_reference<T&&> { using type = T; };
+  // clang-format on
+
+  template <typename T>
+  using remove_reference_t = typename remove_reference<T>::type;
+
+  template <typename T>
+  constexpr T&& forward(remove_reference_t<T>& t) noexcept;
+
+  template <typename T>
+  constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
+
+  template <typename T>
+  void swap(T& a1, T& a2);
+
+  template <typename F>
+  class function {
+   public:
+    function();
+    function(const function&);
+    function(function&&);
+    function& operator=(const function&);
+    function& operator=(function&&);
+    ~function();
+  };
+
+  template <typename T>
+  class initializer_list {
+   public:
+    using size_type = decltype(sizeof(0));
+    const T* begin() const;
+    const T* end() const;
+
+   private:
+    constexpr initializer_list(const T* items, size_type size)
+        : items_(items), size_(size) {}
+    const T* items_;
+    size_type size_;
+  };
+
+  // <functional>
+  template <class T>
+  struct equal_to {
+    bool operator()(const T& lhs, const T& rhs) const;
+  };
+
+  template <class T>
+  struct not_equal_to {
+    bool operator()(const T& lhs, const T& rhs) const;
+  };
+
+  template <class T>
+  struct hash {
+    std::size_t operator()(T const& t) const noexcept;
+  };
+
+  template <class T = void>
+  struct less {
+    constexpr bool operator()(const T& lhs, const T& rhs) const;
+  };
+
+  template <>
+  struct less<void> {
+    using is_transparent = void;
+    template <typename T, typename U>
+    constexpr auto operator()(T&& lhs, U&& rhs) const
+        -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs));
+  };
+
+  template <class T>
+  struct greater {
+    bool operator()(const T& lhs, const T& rhs) const;
+  };
+
+  // <algorithm>
+  template <class T>
+  const T& min(const T& a, const T& b);
+  template <class T, class Compare>
+  const T& min(const T& a, const T& b, Compare comp);
+  template <class T>
+  const T& max(const T& a, const T& b);
+  template <class T, class Compare>
+  const T& max(const T& a, const T& b, Compare comp);
+  template <class T>
+  T min(std::initializer_list<T> ilist);
+  template <class T, class Compare>
+  T min(std::initializer_list<T> ilist, Compare comp);
+  template <class T>
+  T max(std::initializer_list<T> ilist);
+  template <class T, class Compare>
+  T max(std::initializer_list<T> ilist, Compare comp);
+
+  // <memory>
+  template <class T>
+  struct allocator {
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef T value_type;
+
+    T* allocate(size_t n);
+  };
+
+  template <class Alloc>
+  struct allocator_traits {
+    typedef Alloc allocator_type;
+    typedef typename allocator_type::value_type value_type;
+    typedef typename allocator_type::pointer pointer;
+    typedef typename allocator_type::const_pointer const_pointer;
+    typedef typename allocator_type::difference_type difference_type;
+    typedef typename allocator_type::size_type size_type;
+  };
+
+  template <class... T>
+  class tuple {};
+
+  template <std::size_t I, class T>
+  struct tuple_element;
+
+  template <std::size_t I, class T, class... Ts>
+  struct tuple_element<I, std::tuple<T, Ts...>>
+      : std::tuple_element<I - 1, std::tuple<Ts...>> {};
+
+  template <class T, class... Ts>
+  struct tuple_element<0, std::tuple<T, Ts...>> {
+    using type = T;
+  };
+
+  template <std::size_t I, typename T>
+  using tuple_element_t = typename tuple_element<I, T>::type;
+
+  template <class T1, class T2>
+  struct pair {
+    T1 first;
+    T2 second;
+
+    typedef T1 first_type;
+    typedef T2 second_type;
+
+    constexpr pair();
+
+    template <class U1, class U2>
+    pair(pair<U1, U2>&& p);
+
+    template <class U1, class U2>
+    pair(U1&& x, U2&& y);
+  };
+
+  template <class T1, class T2>
+  pair<T1, T2> make_pair(T1&& t1, T2&& t2);
+
+  template <class InputIt1, class InputIt2, class OutputIt>
+  OutputIt set_difference(InputIt1 first1, InputIt1 last1, InputIt2 first2,
+                          InputIt2 last2, OutputIt d_first);
+
+  template <class InputIt1, class InputIt2, class OutputIt>
+  OutputIt set_intersection(InputIt1 first1, InputIt1 last1, InputIt2 first2,
+                            InputIt2 last2, OutputIt d_first);
+
+  template <class InputIt1, class InputIt2, class OutputIt>
+  OutputIt set_union(InputIt1 first1, InputIt1 last1, InputIt2 first2,
+                     InputIt2 last2, OutputIt d_first);
+
+  template <class InputIt1, class InputIt2, class OutputIt>
+  OutputIt set_symmetric_difference(InputIt1 first1, InputIt1 last1,
+                                    InputIt2 first2, InputIt2 last2,
+                                    OutputIt d_first);
+
+  template <class InputIt1, class InputIt2, class OutputIt>
+  OutputIt merge(InputIt1 first1, InputIt1 last1, InputIt2 first2,
+                 InputIt2 last2, OutputIt d_first);
+
+  template <class Key, class T, class Compare = less<Key>,
+            class Allocator = allocator<pair<const Key, T>>>
+  class map {
+   public:
+    map();
+    ~map();
+
+    typedef pair<const Key, T> value_type;
+    struct iterator {
+      struct reference {};
+      reference operator*() const;
+      struct pointer {};
+      pointer operator->() const;
+
+      friend bool operator==(const iterator& lhs, const iterator& rhs);
+      friend bool operator!=(const iterator& lhs, const iterator& rhs);
+      iterator& operator++();
+      iterator operator++(int);
+    };
+    struct const_iterator {
+      struct reference {};
+      reference operator*() const;
+      struct pointer {};
+      pointer operator->() const;
+
+      friend bool operator==(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      friend bool operator!=(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      const_iterator& operator++();
+      const_iterator operator++(int);
+    };
+
+    iterator begin();
+    iterator end();
+    const_iterator begin() const;
+    const_iterator end() const;
+
+    bool empty() const;
+    iterator find(const Key& key);
+    const_iterator find(const Key& key) const;
+    T& operator[](const Key& key);
+    T& at(const Key& key);
+    const T& at(const Key& key) const;
+    pair<iterator, bool> insert(const value_type& value);
+    template <class P>
+    pair<iterator, bool> insert(P&& value);
+    size_t count(const Key& key) const;
+  };
+
+  // <unordered_map>
+  template <class Key, class T, class Hash = hash<Key>,
+            class Pred = equal_to<Key>,
+            class Alloc = allocator<pair<const Key, T>>>
+  class unordered_map {
+   public:
+    // types
+    typedef Key key_type;
+    typedef T mapped_type;
+    typedef Hash hasher;
+    typedef Pred key_equal;
+    typedef Alloc allocator_type;
+    typedef pair<const key_type, mapped_type> value_type;
+    typedef value_type& reference;
+    typedef const value_type& const_reference;
+    typedef typename allocator_traits<allocator_type>::pointer pointer;
+    typedef
+        typename allocator_traits<allocator_type>::const_pointer const_pointer;
+    typedef typename allocator_traits<allocator_type>::size_type size_type;
+    typedef typename allocator_traits<allocator_type>::difference_type
+        difference_type;
+
+    struct iterator {
+      struct reference {};
+      reference operator*() const;
+      struct pointer {};
+      pointer operator->() const;
+
+      friend bool operator==(const iterator& lhs, const iterator& rhs);
+      friend bool operator!=(const iterator& lhs, const iterator& rhs);
+      iterator& operator++();
+      iterator operator++(int);
+    };
+    struct const_iterator {
+      struct reference {};
+      reference operator*() const;
+      struct pointer {};
+      pointer operator->() const;
+
+      friend bool operator==(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      friend bool operator!=(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      const_iterator& operator++();
+      const_iterator operator++(int);
+    };
+
+    unordered_map() noexcept;
+    explicit unordered_map(size_type n, const hasher& hf = hasher(),
+                           const key_equal& eql = key_equal(),
+                           const allocator_type& a = allocator_type());
+    template <class InputIterator>
+    unordered_map(InputIterator f, InputIterator l, size_type n = 0,
+                  const hasher& hf = hasher(),
+                  const key_equal& eql = key_equal(),
+                  const allocator_type& a = allocator_type());
+    explicit unordered_map(const allocator_type&);
+    unordered_map(const unordered_map&);
+    unordered_map(const unordered_map&, const Alloc&);
+    unordered_map(unordered_map&&) noexcept;
+    unordered_map(unordered_map&&, const Alloc&);
+    ~unordered_map();
+    unordered_map& operator=(const unordered_map&);
+
+    allocator_type get_allocator() const noexcept;
+
+    bool empty() const noexcept;
+    size_type size() const noexcept;
+    size_type max_size() const noexcept;
+
+    iterator begin() noexcept;
+    iterator end() noexcept;
+    const_iterator begin() const noexcept;
+    const_iterator end() const noexcept;
+    const_iterator cbegin() const noexcept;
+    const_iterator cend() const noexcept;
+
+    hasher hash_function() const;
+    key_equal key_eq() const;
+
+    iterator find(const key_type& k);
+    const_iterator find(const key_type& k) const;
+    size_type count(const key_type& k) const;
+    bool contains(const key_type& k) const;  // C++20
+    pair<iterator, iterator> equal_range(const key_type& k);
+    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
+
+    mapped_type& operator[](const key_type& k);
+    mapped_type& operator[](key_type&& k);
+
+    mapped_type& at(const key_type& k);
+    const mapped_type& at(const key_type& k) const;
+  };
+
+  template <class Key, class Compare = less<Key>,
+            class Allocator = allocator<Key>>
+  class set {
+   public:
+    typedef Key key_type;
+    typedef key_type value_type;
+    typedef Compare key_compare;
+    typedef key_compare value_compare;
+
+    set();
+    set(initializer_list<value_type> l, const value_compare& c = value_compare());
+    ~set();
+
+    struct iterator {
+      Key& operator*();
+      friend bool operator==(const iterator& lhs, const iterator& rhs);
+      friend bool operator!=(const iterator& lhs, const iterator& rhs);
+      iterator& operator++();
+    };
+    struct const_iterator {
+      Key& operator*() const;
+      friend bool operator==(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      friend bool operator!=(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      const_iterator& operator++();
+    };
+
+    iterator begin();
+    iterator end();
+    const_iterator begin() const;
+    const_iterator end() const;
+
+    bool empty() const;
+    iterator find(const key_type& key);
+    const_iterator find(const key_type& key) const;
+    pair<iterator, bool> insert(const value_type& value);
+    size_t count(const key_type& key) const;
+  };
+
+  template <class Key, class Hash = hash<Key>, class KeyEqual = equal_to<Key>,
+            class Allocator = allocator<Key>>
+  class unordered_set {
+   public:
+    using key_type = Key;
+    using value_type = Key;
+    using size_type = typename allocator_traits<Allocator>::size_type;
+    using difference_type = typename allocator_traits<Allocator>::difference_type;
+    using hasher = Hash;
+    using key_equal = KeyEqual;
+    using allocator_type = Allocator;
+    using reference = value_type&;
+    using const_reference = const value_type&;
+    using pointer = typename allocator_traits<Allocator>::pointer;
+    using const_pointer = typename allocator_traits<Allocator>::const_pointer;
+
+    struct iterator {
+      reference operator*() const;
+      pointer operator->() const;
+
+      friend bool operator==(const iterator& lhs, const iterator& rhs);
+      friend bool operator!=(const iterator& lhs, const iterator& rhs);
+      iterator& operator++();
+      iterator operator++(int);
+    };
+    struct const_iterator {
+      const_reference operator*() const;
+      const_pointer operator->() const;
+
+      friend bool operator==(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      friend bool operator!=(const const_iterator& lhs,
+                             const const_iterator& rhs);
+      const_iterator& operator++();
+      const_iterator operator++(int);
+    };
+
+    unordered_set() noexcept;
+    explicit unordered_set(size_type bucket_count, const Hash& hash = Hash(),
+                           const key_equal& equal = key_equal(),
+                           const Allocator& alloc = Allocator());
+    unordered_set(size_type bucket_count, const Allocator& alloc);
+    unordered_set(size_type bucket_count, const Hash& hash,
+                  const Allocator& alloc);
+    explicit unordered_set(const Allocator& alloc);
+    template <class InputIt>
+    unordered_set(InputIt first, InputIt last, size_type bucket_count = 1,
+                  const Hash& hash = Hash(),
+                  const key_equal& equal = key_equal(),
+                  const Allocator& alloc = Allocator());
+    template <class InputIt>
+    unordered_set(InputIt first, InputIt last, size_type bucket_count,
+                  const Allocator& alloc);
+    template <class InputIt>
+    unordered_set(InputIt first, InputIt last, size_type bucket_count,
+                  const Hash& hash, const Allocator& alloc);
+    unordered_set(const unordered_set& other);
+    unordered_set(const unordered_set& other, const Allocator& alloc);
+    unordered_set(unordered_set&& other);
+    unordered_set(unordered_set&& other, const Allocator& alloc);
+    unordered_set(initializer_list<value_type> init, size_type bucket_count = 1,
+                  const Hash& hash = Hash(),
+                  const key_equal& equal = key_equal(),
+                  const Allocator& alloc = Allocator());
+    unordered_set(initializer_list<value_type> init, size_type bucket_count,
+                  const Allocator& alloc);
+    unordered_set(initializer_list<value_type> init, size_type bucket_count,
+                  const Hash& hash, const Allocator& alloc);
+
+    ~unordered_set();
+
+    unordered_set& operator=(const unordered_set& other);
+    unordered_set& operator=(unordered_set&& other);
+    unordered_set& operator=(initializer_list<value_type> ilist);
+
+    iterator begin() noexcept;
+    const_iterator begin() const noexcept;
+    const_iterator cbegin() const noexcept;
+    iterator end() noexcept;
+    const_iterator end() const noexcept;
+    const_iterator cend() const noexcept;
+
+    bool empty() const noexcept;
+    size_type size() const noexcept;
+
+    void clear() noexcept;
+
+    std::pair<iterator, bool> insert(const value_type& value);
+    std::pair<iterator, bool> insert(value_type&& value);
+    iterator insert(const_iterator hint, const value_type& value);
+    iterator insert(const_iterator hint, value_type&& value);
+    template <class InputIt>
+    void insert(InputIt first, InputIt last);
+    void insert(initializer_list<value_type> ilist);
+
+    template <class... Args>
+    pair<iterator, bool> emplace(Args&&... args);
+
+    iterator erase(const_iterator pos);
+    iterator erase(const_iterator first, const_iterator last);
+    size_type erase(const key_type& key);
+
+    void swap(unordered_set& other);
+
+    size_type count(const Key& key) const;
+    iterator find(const Key& key);
+    const_iterator find(const Key& key) const;
+  };
+
+  template <typename T, class Allocator = allocator<T>>
+  class vector {
+   public:
+    using value_type = T;
+    using size_type = typename allocator_traits<Allocator>::size_type;
+
+    // Constructors.
+    vector() {}
+    vector(size_type, const Allocator& = Allocator()) {}
+    vector(initializer_list<T> initializer_list,
+           const Allocator& = Allocator()) {}
+    vector(const vector& vector) {}
+    ~vector();
+
+    // Modifiers.
+    void push_back(const T& value);
+    void push_back(T&& value);
+    template <typename... Args>
+    T& emplace_back(Args&&... args);
+
+    // Iterators
+    class InputIterator {
+     public:
+      InputIterator(const InputIterator&);
+      ~InputIterator();
+      InputIterator& operator=(const InputIterator&);
+      InputIterator& operator++();
+      T& operator*() const;
+      bool operator!=(const InputIterator&) const;
+      bool operator==(const InputIterator&) const;
+    };
+    typedef InputIterator iterator;
+    typedef const InputIterator const_iterator;
+    iterator begin() noexcept;
+    const_iterator begin() const noexcept;
+    const_iterator cbegin() const noexcept;
+    iterator end() noexcept;
+    const_iterator end() const noexcept;
+    const_iterator cend() const noexcept;
+    T* data() noexcept;
+    const T* data() const noexcept;
+    T& operator[](int n);
+    const T& operator[](int n) const;
+    T& at(int n);
+    const T& at(int n) const;
+    size_t size() const;
+  };
+
+  template <typename T, class Allocator = allocator<T>>
+  class deque {
+   public:
+    using value_type = T;
+    using size_type = typename allocator_traits<Allocator>::size_type;
+
+    // Constructors.
+    deque() {}
+    deque(size_type, const Allocator& = Allocator()) {}
+    deque(initializer_list<T> initializer_list, const Allocator& = Allocator()) {}
+    deque(const deque& deque) {}
+    ~deque();
+
+    // Modifiers.
+    void push_back(const T& value);
+    void push_back(T&& value);
+    void push_front(const T& value);
+    void push_front(T&& value);
+    template <typename... Args>
+    T& emplace_back(Args&&... args);
+    template <typename... Args>
+    T& emplace_front(Args&&... args);
+
+    // Iterators
+    class InputIterator {
+     public:
+      InputIterator(const InputIterator&);
+      ~InputIterator();
+      InputIterator& operator=(const InputIterator&);
+      InputIterator& operator++();
+      T& operator*() const;
+      bool operator!=(const InputIterator&) const;
+      bool operator==(const InputIterator&) const;
+    };
+    typedef InputIterator iterator;
+    typedef const InputIterator const_iterator;
+    iterator begin() noexcept;
+    const_iterator begin() const noexcept;
+    iterator end() noexcept;
+    const_iterator end() const noexcept;
+    T* data() noexcept;
+    const T* data() const noexcept;
+    T& operator[](size_t n);
+    const T& operator[](size_t n) const;
+    T& at(size_t n);
+    const T& at(size_t n) const;
+    size_t size() const;
+  };
+
+  template <class T, size_t N>
+  struct array {
+    using value_type = T;
+    void fill(const T& value);
+    void swap(array& other) noexcept;
+    size_t size() const noexcept;
+    size_t max_size() const noexcept;
+    bool empty() const noexcept;
+    T& operator[](size_t n) noexcept;
+    const T& operator[](size_t n) const noexcept;
+    T& at(size_t n);
+    const T& at(size_t n) const;
+    T& front() noexcept;
+    const T& front() const noexcept;
+    T& back() noexcept;
+    const T& back() const noexcept;
+    T* data() noexcept;
+    const T* data() const noexcept;
+  };
+
+  template <typename T>
+  struct default_delete {};
+
+  template <typename T, typename D = default_delete<T>>
+  class unique_ptr {
+   public:
+    using element_type = T;
+    using deleter_type = D;
+
+    constexpr unique_ptr();
+    constexpr unique_ptr(nullptr_t) noexcept;
+    unique_ptr(unique_ptr&&);
+    explicit unique_ptr(T*);
+    template <typename U, typename E>
+    unique_ptr(unique_ptr<U, E>&&);
+
+    ~unique_ptr();
+
+    unique_ptr& operator=(unique_ptr&&);
+    template <typename U, typename E>
+    unique_ptr& operator=(unique_ptr<U, E>&&);
+    unique_ptr& operator=(nullptr_t);
+
+    void reset(T* = nullptr) noexcept;
+    T* release();
+    T* get() const;
+
+    T& operator*() const;
+    T* operator->() const;
+    explicit operator bool() const noexcept;
+  };
+
+  template <typename T, typename D>
+  class unique_ptr<T[], D> {
+   public:
+    T* get() const;
+    T& operator[](size_t i);
+    const T& operator[](size_t i) const;
+  };
+
+  template <typename T, typename... Args>
+  unique_ptr<T> make_unique(Args&&...);
+
+  template <class T, class D>
+  void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
+
+  template <class T1, class D1, class T2, class D2>
+  bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
+  template <class T1, class D1, class T2, class D2>
+  bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
+  template <class T1, class D1, class T2, class D2>
+  bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
+  template <class T1, class D1, class T2, class D2>
+  bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
+  template <class T1, class D1, class T2, class D2>
+  bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
+  template <class T1, class D1, class T2, class D2>
+  bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
+
+  template <class T, class D>
+  bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
+  template <class T, class D>
+  bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept;
+  template <class T, class D>
+  bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
+  template <class T, class D>
+  bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept;
+  template <class T, class D>
+  bool operator<(const unique_ptr<T, D>& x, nullptr_t);
+  template <class T, class D>
+  bool operator<(nullptr_t, const unique_ptr<T, D>& y);
+  template <class T, class D>
+  bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
+  template <class T, class D>
+  bool operator<=(nullptr_t, const unique_ptr<T, D>& y);
+  template <class T, class D>
+  bool operator>(const unique_ptr<T, D>& x, nullptr_t);
+  template <class T, class D>
+  bool operator>(nullptr_t, const unique_ptr<T, D>& y);
+  template <class T, class D>
+  bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
+  template <class T, class D>
+  bool operator>=(nullptr_t, const unique_ptr<T, D>& y);
+
+  template <typename T>
+  class shared_ptr_base {
+   public:
+    ~shared_ptr_base();
+    T& operator*() const;
+    T* operator->() const;
+  };
+
+  template <typename T>
+  class shared_ptr : public shared_ptr_base<T> {
+   public:
+    constexpr shared_ptr();
+    ~shared_ptr();
+  };
+
+  template <class T, class... Args>
+  shared_ptr<T> make_shared(Args&&... args);
+
+  template <typename T>
+  class weak_ptr {
+   public:
+    constexpr weak_ptr() noexcept;
+    ~weak_ptr();
+  };
+
+  template <typename T>
+  class reference_wrapper {
+   public:
+    reference_wrapper(T& ref);
+    T& get() const noexcept;
+    operator T&() const noexcept;
+  };
+
+  template <typename Container>
+  typename Container::iterator begin(Container&);
+  template <typename Container>
+  typename Container::iterator end(Container&);
+
+  template <class T>
+  reference_wrapper<const T> cref(const T& t);
+
+  template <typename T>
+  constexpr std::remove_reference_t<T>&& move(T&& x);
+
+  struct nothrow_t {
+    explicit nothrow_t() = default;
+  };
+  extern const std::nothrow_t nothrow;
+
+  }  // namespace __do_not_hardcode_in_clang_tidy
+  }  // namespace std
+
+#endif  // STDLIB_DEFS_H_
+)cc";
+
+constexpr const char *kStringDefsHeader = R"cc(
+  // string_defs.h
+  //
+  // This file contains minimal mock declarations of the string type and
+  // friends. It can be used in tests to use matchers as they would be used in a
+  // prod google3 environment. This only contains what has been necessary for
+  // the tests that use it. It can be expanded if tests need more of it.
+
+#pragma clang system_header
+
+#ifndef STRING_DEFS_H_
+#define STRING_DEFS_H_
+
+#include "std_char_traits.h"
+#include "std_string_view.h"
+#include "std_type_traits.h"
+#include "stdlib_defs.h"
+
+#define ABSL_PRINTF_ATTRIBUTE(a, b) __attribute__((format(printf, a, b)))
+
+  namespace __gnu_cxx {
+  inline namespace __do_not_hardcode_in_clang_tidy {
+  template <typename A, typename B, typename C>
+  class __string_base {};
+  }  // namespace __do_not_hardcode_in_clang_tidy
+  }  // namespace __gnu_cxx
+
+  namespace std {
+  inline namespace __do_not_hardcode_in_clang_tidy {
+
+  template <class _CharT, class _Traits, class _Tp>
+  struct __can_be_converted_to_string_view {
+    static std::true_type Test(std::basic_string_view<_CharT, _Traits>);
+    static std::false_type Test(...);
+    static const _Tp& Instance();
+    static constexpr bool value = decltype(Test(Instance()))::value;
+  };
+
+  template <typename A, typename B = std::char_traits<A>,
+            typename C = std::allocator<A>>
+  class basic_string : public __gnu_cxx::__string_base<A, B, C> {
+   public:
+    basic_string();
+    basic_string(const basic_string&);
+    basic_string(basic_string&&) noexcept;
+    basic_string(const A*, const C& = C());
+    basic_string(const A*, int, const C& = C());
+    basic_string(const basic_string&, int, int, C = C());
+
+    template <class _Tp, class = enable_if_t<__can_be_converted_to_string_view<
+                             A, B, _Tp>::value>>
+    explicit basic_string(const _Tp& __t);
+
+    template <class _Tp, class = enable_if_t<__can_be_converted_to_string_view<
+                             A, B, _Tp>::value>>
+    explicit basic_string(const _Tp& __t, const C& __a);
+
+    ~basic_string();
+
+    basic_string& operator=(const basic_string&);
+    basic_string& operator=(basic_string&&) noexcept;
+    basic_string& operator=(const A*);
+    template <class _Tp, class = enable_if_t<__can_be_converted_to_string_view<
+                             A, B, _Tp>::value>>
+    basic_string& operator=(const _Tp& __t);
+
+    basic_string& operator+=(const basic_string&);
+
+    static const int npos = -1;
+    const char* c_str() const;
+    const char* data() const;
+    char* data();
+    size_t size() const;
+    size_t capacity() const;
+    size_t length() const;
+    bool empty() const;
+    char& operator[](int);
+    const char& operator[](int) const;
+    char& at(int);
+    const char& at(int) const;
+    void clear();
+    void resize(int);
+    int compare(const basic_string&) const;
+    int find(const basic_string&, int pos = 0) const;
+    int find(const char*, int pos = 0) const;
+    int rfind(const basic_string&, int pos = 0) const;
+    int rfind(const char*, int pos = 0) const;
+
+    operator std::basic_string_view<A, B>() const noexcept;
+  };
+
+  template <typename A, typename B, typename C>
+  basic_string<A, B, C> operator+(const basic_string<A, B, C>&,
+                                  const basic_string<A, B, C>&);
+  template <typename A, typename B, typename C>
+  basic_string<A, B, C> operator+(const basic_string<A, B, C>&, const char*);
+
+  typedef basic_string<char> string;
+
+  bool operator==(const string&, const string&);
+  bool operator==(const string&, const char*);
+  bool operator==(const char*, const string&);
+
+  bool operator!=(const string&, const string&);
+  bool operator<(const string&, const string&);
+  bool operator>(const string&, const string&);
+  bool operator<=(const string&, const string&);
+  bool operator>=(const string&, const string&);
+  }  // namespace __do_not_hardcode_in_clang_tidy
+  }  // namespace std
+
+#endif  // STRING_DEFS_H_
+)cc";
+
+constexpr const char *kStdCharTraitsHeader = R"cc(
+#ifndef STD_CHAR_TRAITS_H_
+#define STD_CHAR_TRAITS_H_
+
+  namespace std {
+  inline namespace __do_not_hardcode_in_clang_tidy {
+  template <typename T>
+  class char_traits {};
+  }  // namespace __do_not_hardcode_in_clang_tidy
+  }  // namespace std
+
+#endif  // STD_CHAR_TRAITS_H_
+)cc";
+
+constexpr const char *kStdStringViewHeader = R"cc(
+  // This file is a mock of the <string_view> standard library header.
+
+#pragma clang system_header
+
+#ifndef STD_STRING_VIEW_H_
+#define STD_STRING_VIEW_H_
+
+#include "std_char_traits.h"
+#include "stdlib_defs.h"
+
+  constexpr size_t strlen(const char* p) {
+    return *p ? strlen(p + 1) + 1 : 0;
+  }
+
+  namespace std {
+  inline namespace __do_not_hardcode_in_clang_tidy {
+
+  template <typename CharT, typename Traits = std::char_traits<CharT>>
+  class basic_string_view {
+   public:
+    using traits_type = Traits;
+
+    constexpr basic_string_view() noexcept;
+    constexpr basic_string_view(const CharT* null_terminated_string) {  // NOLINT
+      (void)strlen(null_terminated_string);  // some checks need to see strlen.
+    }
+    constexpr basic_string_view(const CharT*, size_t);
+
+#if __cplusplus >= 202002L
+    // A subset of:
+    // template <contiguous_iterator _It, sized_sentinel_for<_It> _End>
+    //   requires(is_same_v<iter_value_t<_It>, _CharT> &&
+    //            !is_convertible_v<_End, size_type>)
+    // constexpr basic_string_view(_It __begin, _End __end);
+    // to avoid having to define all the underlying concepts, etc.
+    constexpr basic_string_view(const CharT* __begin, const CharT* __end);
+#endif
+
+    constexpr const char* data() const noexcept;
+    constexpr size_t size() const noexcept;
+    constexpr size_t length() const noexcept;
+    constexpr const CharT& operator[](size_t pos) const;
+    constexpr const CharT& at(size_t pos) const;
+  };
+
+  using string_view = basic_string_view<char>;
+
+  template <class CharT, class Traits>
+  constexpr bool operator==(basic_string_view<CharT, Traits> lhs,
+                            basic_string_view<CharT, Traits> rhs) noexcept;
+  template <class CharT, class Traits>
+  constexpr bool operator==(_NonDeduced<basic_string_view<CharT, Traits>> lhs,
+                            basic_string_view<CharT, Traits> rhs) noexcept;
+  template <class CharT, class Traits>
+  constexpr bool operator==(
+      basic_string_view<CharT, Traits> lhs,
+      _NonDeduced<basic_string_view<CharT, Traits>> rhs) noexcept;
+
+  }  // namespace __do_not_hardcode_in_clang_tidy
+  }  // namespace std
+
+#endif  // STD_STRING_VIEW_H_
+)cc";
+
+constexpr const char *kStatusOrDefsHeader =
+    R"cc(
+#ifndef STATUSOR_H_
+#define STATUSOR_H_
+
+#include "absl_defs.h"
+#include "std_string_view.h"
+#include "stdlib_defs.h"
+#include "string_defs.h"
+
+  namespace absl {
+  template <typename>
+  class AnyInvocable;
+  template <typename R, typename... A>
+  class AnyInvocable<R(A...) &&> {
+   public:
+    AnyInvocable();
+    ~AnyInvocable();
+    template <typename F>
+    AnyInvocable(F&& f, decltype(f(A{}...), 0) = 0);
+
+    R operator()(A...) &&;
+  };
+  }  // namespace absl
+
+  namespace absl {
+  struct SourceLocation {
+    static constexpr SourceLocation current();
+    static constexpr SourceLocation DoNotInvokeDirectlyNoSeriouslyDont(
+        int line, const char* file_name);
+  };
+  }  // namespace absl
+  namespace absl {
+  enum class StatusCode : int {
+    kOk,
+    kCancelled,
+    kUnknown,
+    kInvalidArgument,
+    kDeadlineExceeded,
+    kNotFound,
+    kAlreadyExists,
+    kPermissionDenied,
+    kResourceExhausted,
+    kFailedPrecondition,
+    kAborted,
+    kOutOfRange,
+    kUnimplemented,
+    kInternal,
+    kUnavailable,
+    kDataLoss,
+    kUnauthenticated,
+  };
+  }  // namespace absl
+
+  namespace absl {
+  enum class StatusToStringMode : int {
+    kWithNoExtraData = 0,
+    kWithPayload = 1 << 0,
+    kWithSourceLocation = 1 << 1,
+    kWithEverything = ~kWithNoExtraData,
+    kDefault = kWithPayload,
+  };
+  class Status {
+   public:
+    Status();
+    template <typename Enum>
+    Status(Enum code, std::string_view msg);
+    Status(absl::StatusCode code, std::string_view msg,
+           absl::SourceLocation loc = SourceLocation::current());
+    Status(const Status& base_status, absl::SourceLocation loc);
+    Status(Status&& base_status, absl::SourceLocation loc);
+    ~Status() {}
+
+    Status(const Status&);
+    Status& operator=(const Status& x);
+
+    Status(Status&&) noexcept;
+    Status& operator=(Status&&);
+
+    friend bool operator==(const Status&, const Status&);
+    friend bool operator!=(const Status&, const Status&);
+
+    bool ok() const { return true; }
+    void CheckSuccess() const;
+    void IgnoreError() const;
+    int error_code() const;
+    absl::Status ToCanonical() const;
+    std::string ToString(
+        StatusToStringMode m = StatusToStringMode::kDefault) const;
+    void Update(const Status& new_status);
+    void Update(Status&& new_status);
+
+   private:
+    void TestToStringSimplification() const {
+      LOG(INFO) << this->ToString() << ToString();
+    }
+  };
+
+  bool operator==(const Status& lhs, const Status& rhs);
+  bool operator!=(const Status& lhs, const Status& rhs);
+
+  Status OkStatus();
+  Status InvalidArgumentError(char*);
+
+  template <typename T>
+  struct StatusOr;
+
+  namespace internal_statusor {
+
+  template <typename T, typename U, typename = void>
+  struct HasConversionOperatorToStatusOr : std::false_type {};
+
+  template <typename T, typename U>
+  void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
+
+  template <typename T, typename U>
+  struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
+      : std::true_type {};
+
+  template <typename T, typename U>
+  using IsConstructibleOrConvertibleFromStatusOr =
+      absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
+                        std::is_constructible<T, const StatusOr<U>&>,
+                        std::is_constructible<T, StatusOr<U>&&>,
+                        std::is_constructible<T, const StatusOr<U>&&>,
+                        std::is_convertible<StatusOr<U>&, T>,
+                        std::is_convertible<const StatusOr<U>&, T>,
+                        std::is_convertible<StatusOr<U>&&, T>,
+                        std::is_convertible<const StatusOr<U>&&, T>>;
+
+  template <typename T, typename U>
+  using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
+      absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
+                        std::is_assignable<T&, StatusOr<U>&>,
+                        std::is_assignable<T&, const StatusOr<U>&>,
+                        std::is_assignable<T&, StatusOr<U>&&>,
+                        std::is_assignable<T&, const StatusOr<U>&&>>;
+
+  template <typename T, typename U>
+  struct IsDirectInitializationAmbiguous
+      : public absl::conditional_t<
+            std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                         U>::value,
+            std::false_type,
+            IsDirectInitializationAmbiguous<
+                T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+  template <typename T, typename V>
+  struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
+      : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
+
+  template <typename T, typename U>
+  using IsDirectInitializationValid = absl::disjunction<
+      // Short circuits if T is basically U.
+      std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+      absl::negation<absl::disjunction<
+          std::is_same<absl::StatusOr<T>,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          std::is_same<absl::Status,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          std::is_same<absl::in_place_t,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          IsDirectInitializationAmbiguous<T, U>>>>;
+
+  template <typename T, typename U>
+  struct IsForwardingAssignmentAmbiguous
+      : public absl::conditional_t<
+            std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                         U>::value,
+            std::false_type,
+            IsForwardingAssignmentAmbiguous<
+                T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+  template <typename T, typename U>
+  struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
+      : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
+
+  template <typename T, typename U>
+  using IsForwardingAssignmentValid = absl::disjunction<
+      // Short circuits if T is basically U.
+      std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+      absl::negation<absl::disjunction<
+          std::is_same<absl::StatusOr<T>,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          std::is_same<absl::Status,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          std::is_same<absl::in_place_t,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          IsForwardingAssignmentAmbiguous<T, U>>>>;
+
+  template <typename T, typename U>
+  using IsForwardingAssignmentValid = absl::disjunction<
+      // Short circuits if T is basically U.
+      std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+      absl::negation<absl::disjunction<
+          std::is_same<absl::StatusOr<T>,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          std::is_same<absl::Status,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          std::is_same<absl::in_place_t,
+                       absl::remove_cv_t<absl::remove_reference_t<U>>>,
+          IsForwardingAssignmentAmbiguous<T, U>>>>;
+
+  template <typename T>
+  struct OperatorBase {
+    const T& value() const&;
+    T& value() &;
+    const T&& value() const&&;
+    T&& value() &&;
+
+    const T& operator*() const&;
+    T& operator*() &;
+    const T&& operator*() const&&;
+    T&& operator*() &&;
+
+    // To test that analyses are okay if there is a use of operator*
+    // within this base class.
+    const T* operator->() const { return __builtin_addressof(**this); }
+    T* operator->() { return __builtin_addressof(**this); }
+  };
+
+  }  // namespace internal_statusor
+
+  template <typename T>
+  struct StatusOr : private internal_statusor::OperatorBase<T> {
+    explicit StatusOr();
+
+    StatusOr(const StatusOr&) = default;
+    StatusOr& operator=(const StatusOr&) = default;
+
+    StatusOr(StatusOr&&) = default;
+    StatusOr& operator=(StatusOr&&) = default;
+
+    template <
+        typename U,
+        absl::enable_if_t<
+            absl::conjunction<
+                absl::negation<std::is_same<T, U>>,
+                std::is_constructible<T, const U&>,
+                std::is_convertible<const U&, T>,
+                absl::negation<
+                    internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                        T, U>>>::value,
+            int> = 0>
+    StatusOr(const StatusOr<U>&);
+
+    template <
+        typename U,
+        absl::enable_if_t<
+            absl::conjunction<
+                absl::negation<std::is_same<T, U>>,
+                std::is_constructible<T, const U&>,
+                absl::negation<std::is_convertible<const U&, T>>,
+                absl::negation<
+                    internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                        T, U>>>::value,
+            int> = 0>
+    explicit StatusOr(const StatusOr<U>&);
+
+    template <
+        typename U,
+        absl::enable_if_t<
+            absl::conjunction<
+                absl::negation<std::is_same<T, U>>,
+                std::is_constructible<T, U&&>, std::is_convertible<U&&, T>,
+                absl::negation<
+                    internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                        T, U>>>::value,
+            int> = 0>
+    StatusOr(StatusOr<U>&&);
+
+    template <
+        typename U,
+        absl::enable_if_t<
+            absl::conjunction<
+                absl::negation<std::is_same<T, U>>,
+                std::is_constructible<T, U&&>,
+                absl::negation<std::is_convertible<U&&, T>>,
+                absl::negation<
+                    internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                        T, U>>>::value,
+            int> = 0>
+    explicit StatusOr(StatusOr<U>&&);
+
+    template <
+        typename U,
+        absl::enable_if_t<
+            absl::conjunction<
+                absl::negation<std::is_same<T, U>>,
+                std::is_constructible<T, const U&>,
+                std::is_assignable<T, const U&>,
+                absl::negation<
+                    internal_statusor::
+                        IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                            T, U>>>::value,
+            int> = 0>
+    StatusOr& operator=(const StatusOr<U>&);
+
+    template <
+        typename U,
+        absl::enable_if_t<
+            absl::conjunction<
+                absl::negation<std::is_same<T, U>>,
+                std::is_constructible<T, U&&>, std::is_assignable<T, U&&>,
+                absl::negation<
+                    internal_statusor::
+                        IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                            T, U>>>::value,
+            int> = 0>
+    StatusOr& operator=(StatusOr<U>&&);
+
+    template <typename U = absl::Status,
+              absl::enable_if_t<
+                  absl::conjunction<
+                      std::is_convertible<U&&, absl::Status>,
+                      std::is_constructible<absl::Status, U&&>,
+                      absl::negation<
+                          std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+                      absl::negation<std::is_same<absl::decay_t<U>, T>>,
+                      absl::negation<
+                          std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>::value,
+                  int> = 0>
+    StatusOr(U&&);
+
+    template <typename U = absl::Status,
+              absl::enable_if_t<
+                  absl::conjunction<
+                      absl::negation<std::is_convertible<U&&, absl::Status>>,
+                      std::is_constructible<absl::Status, U&&>,
+                      absl::negation<
+                          std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+                      absl::negation<std::is_same<absl::decay_t<U>, T>>,
+                      absl::negation<
+                          std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>::value,
+                  int> = 0>
+    explicit StatusOr(U&&);
+
+    template <typename U = absl::Status,
+              absl::enable_if_t<
+                  absl::conjunction<
+                      std::is_convertible<U&&, absl::Status>,
+                      std::is_constructible<absl::Status, U&&>,
+                      absl::negation<
+                          std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+                      absl::negation<std::is_same<absl::decay_t<U>, T>>,
+                      absl::negation<
+                          std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>::value,
+                  int> = 0>
+    StatusOr& operator=(U&&);
+
+    template <
+        typename U = T,
+        typename = typename std::enable_if<absl::conjunction<
+            std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>,
+            absl::disjunction<
+                std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>,
+                absl::conjunction<
+                    absl::negation<std::is_convertible<U&&, absl::Status>>,
+                    absl::negation<
+                        internal_statusor::HasConversionOperatorToStatusOr<
+                            T, U&&>>>>,
+            internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::
+            type>
+    StatusOr& operator=(U&&);
+
+    template <typename... Args>
+    explicit StatusOr(absl::in_place_t, Args&&...);
+
+    template <typename U, typename... Args>
+    explicit StatusOr(absl::in_place_t, std::initializer_list<U>, Args&&...);
+
+    template <
+        typename U = T,
+        absl::enable_if_t<
+            absl::conjunction<
+                internal_statusor::IsDirectInitializationValid<T, U&&>,
+                std::is_constructible<T, U&&>, std::is_convertible<U&&, T>,
+                absl::disjunction<
+                    std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                                 T>,
+                    absl::conjunction<
+                        absl::negation<std::is_convertible<U&&, absl::Status>>,
+                        absl::negation<
+                            internal_statusor::HasConversionOperatorToStatusOr<
+                                T, U&&>>>>>::value,
+            int> = 0>
+    StatusOr(U&&);
+
+    template <
+        typename U = T,
+        absl::enable_if_t<
+            absl::conjunction<
+                internal_statusor::IsDirectInitializationValid<T, U&&>,
+                absl::disjunction<
+                    std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                                 T>,
+                    absl::conjunction<
+                        absl::negation<
+                            std::is_constructible<absl::Status, U&&>>,
+                        absl::negation<
+                            internal_statusor::HasConversionOperatorToStatusOr<
+                                T, U&&>>>>,
+                std::is_constructible<T, U&&>,
+                absl::negation<std::is_convertible<U&&, T>>>::value,
+            int> = 0>
+    explicit StatusOr(U&&);
+
+    bool ok() const;
+
+    const Status& status() const& { return status_; }
+    Status status() &&;
+
+    using StatusOr::OperatorBase::value;
+
+    const T& ValueOrDie() const&;
+    T& ValueOrDie() &;
+    const T&& ValueOrDie() const&&;
+    T&& ValueOrDie() &&;
+
+    using StatusOr::OperatorBase::operator*;
+
+    using StatusOr::OperatorBase::operator->;
+
+    template <typename U>
+    T value_or(U&& default_value) const&;
+    template <typename U>
+    T value_or(U&& default_value) &&;
+
+    template <typename... Args>
+    T& emplace(Args&&... args);
+
+    template <
+        typename U, typename... Args,
+        absl::enable_if_t<std::is_constructible<T, std::initializer_list<U>&,
+                                                Args&&...>::value,
+                          int> = 0>
+    T& emplace(std::initializer_list<U> ilist, Args&&... args);
+
+   private:
+    absl::Status status_;
+  };
+
+  template <typename T>
+  bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs);
+
+  template <typename T>
+  bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs);
+
+  }  // namespace absl
+
+#endif  // STATUSOR_H_
+    )cc";
+
+TEST_P(UncheckedStatusOrAccessModelTest, NoStatusOrMention) {
+  ExpectDiagnosticsFor(R"cc(
+    void target() { "nop"; }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Lvalue_CallToValue) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, NonExplicitInitialization) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+    STATUSOR_INT target() {
+      STATUSOR_INT x = Make<STATUSOR_INT>();
+      return x.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Lvalue_CallToValue_NewLine) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Rvalue_CallToValue) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      std::move(sor).value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Lvalue_CallToValueOrDie) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      sor.ValueOrDie();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Rvalue_CallToValueOrDie) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      std::move(sor).ValueOrDie();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Lvalue_CallToOperatorStar) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      *sor;  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Lvalue_CallToOperatorStarSeparateLine) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      *  // [[unsafe]]
+          sor;
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Rvalue_CallToOperatorStar) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      *std::move(sor);  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Lvalue_CallToOperatorArrow) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      void foo();
+    };
+
+    void target(absl::StatusOr<Foo> sor) {
+      sor->foo();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest,
+       UnwrapWithoutCheck_Rvalue_CallToOperatorArrow) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      void foo();
+    };
+
+    void target(absl::StatusOr<Foo> sor) {
+      std::move(sor)->foo();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, UnwrapRvalueWithCheck) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (sor.ok()) std::move(sor).value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ParensInDeclInitExpr) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      auto sor = (Make<STATUSOR_INT>());
+      if (sor.ok()) sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ReferenceInDeclInitExpr) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      const STATUSOR_INT& GetStatusOrInt() const;
+    };
+
+    void target(Foo foo) {
+      auto sor = foo.GetStatusOrInt();
+      if (sor.ok()) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      STATUSOR_INT& GetStatusOrInt();
+    };
+
+    void target(Foo foo) {
+      auto sor = foo.GetStatusOrInt();
+      if (sor.ok()) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      STATUSOR_INT&& GetStatusOrInt() &&;
+    };
+
+    void target(Foo foo) {
+      auto sor = std::move(foo).GetStatusOrInt();
+      if (sor.ok()) sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT sor) {
+          if (sor.ok())
+            sor.value();
+          else
+            sor.value();  // [[unsafe]]
+
+          sor.value();  // [[unsafe]]
+        }
+      )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      if (auto sor = Make<STATUSOR_INT>(); sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, JoinSafeSafe) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT sor, bool b) {
+          if (sor.ok()) {
+            if (b)
+              sor.value();
+            else
+              sor.value();
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, JoinUnsafeUnsafe) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor, bool b) {
+      if (b)
+        sor.value();  // [[unsafe]]
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, InversedIfThenElse) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT sor) {
+          if (!sor.ok())
+            sor.value();  // [[unsafe]]
+          else
+            sor.value();
+
+          sor.value();  // [[unsafe]]
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, DoubleInversedIfThenElse) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (!!sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, TripleInversedIfThenElse) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (!!!sor.ok())
+        sor.value();  // [[unsafe]]
+      else
+        sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_LhsAndRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      if (x.ok() && y.ok()) {
+        x.value();
+
+        y.value();
+      } else {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_NotLhsAndRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!x.ok() && y.ok()) {
+            y.value();
+
+            x.value();  // [[unsafe]]
+          } else {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_LhsAndNotRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (x.ok() && !y.ok()) {
+            x.value();
+
+            y.value();  // [[unsafe]]
+          } else {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_NotLhsAndNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      if (!x.ok() && !y.ok()) {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      } else {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_LhsAndRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!(x.ok() && y.ok())) {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          } else {
+            x.value();
+
+            y.value();
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_NotLhsAndRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!(!x.ok() && y.ok())) {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          } else {
+            y.value();
+
+            x.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_LhsAndNotRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!(x.ok() && !y.ok())) {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          } else {
+            x.value();
+
+            y.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_NotLhsAndNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      if (!(!x.ok() && !y.ok())) {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      } else {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_LhsOrRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      if (x.ok() || y.ok()) {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      } else {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_NotLhsOrRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!x.ok() || y.ok()) {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          } else {
+            x.value();
+
+            y.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_LhsOrNotRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (x.ok() || !y.ok()) {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          } else {
+            y.value();
+
+            x.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_NotLhsOrNotRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!x.ok() || !y.ok()) {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          } else {
+            x.value();
+
+            y.value();
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_LhsOrRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      if (!(x.ok() || y.ok())) {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      } else {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_NotLhsOrRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!(!x.ok() || y.ok())) {
+            x.value();
+
+            y.value();  // [[unsafe]]
+          } else {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_LhsOrNotRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!(x.ok() || !y.ok())) {
+            y.value();
+
+            x.value();  // [[unsafe]]
+          } else {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, IfThenElse_Not_NotLhsOrNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      if (!(!x.ok() || !y.ok())) {
+        x.value();
+
+        y.value();
+      } else {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, TerminatingIfThenBranch) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (!sor.ok()) return;
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (sor.ok()) return;
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!x.ok() || !y.ok()) return;
+
+          x.value();
+
+          y.value();
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, TerminatingIfElseBranch) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (sor.ok()) {
+      } else {
+        return;
+      }
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (!sor.ok()) {
+      } else {
+        return;
+      }
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, TerminatingIfThenBranchInLoop) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (Make<bool>()) {
+        if (!sor.ok()) continue;
+
+        sor.value();
+      }
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (Make<bool>()) {
+        if (!sor.ok()) break;
+
+        sor.value();
+      }
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, TernaryConditionalOperator) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      sor.ok() ? sor.value() : 21;
+
+      sor.ok() ? 21 : sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      !sor.ok() ? 21 : sor.value();
+
+      !sor.ok() ? sor.value() : 21;  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor1, STATUSOR_INT sor2) {
+      !((__builtin_expect(false || (!(sor1.ok() && sor2.ok())), false)))
+          ? (void)0
+          : (void)1;
+      do {
+        sor1.value();  // [[unsafe]]
+        sor2.value();  // [[unsafe]]
+      } while (true);
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (Make<bool>()) sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (sor.ok()) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (!sor.ok()) sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (!!sor.ok()) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (!!!sor.ok()) sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_LhsAndRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          while (x.ok() && y.ok()) {
+            x.value();
+
+            y.value();
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_NotLhsAndRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() && y.ok()) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() && y.ok()) y.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_LhsAndNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (x.ok() && !y.ok()) x.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (x.ok() && !y.ok()) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_NotLhsAndNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() && !y.ok()) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() && !y.ok()) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_LhsAndRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() && y.ok())) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() && y.ok())) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_NotLhsAndRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(!x.ok() && y.ok())) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(!x.ok() && y.ok())) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_LhsAndNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() && !y.ok())) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() && !y.ok())) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_NotLhsAndNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(!x.ok() && !y.ok())) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(!x.ok() && !y.ok())) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_LhsOrRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (x.ok() || y.ok()) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (x.ok() || y.ok()) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_NotLhsOrRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() || y.ok()) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() || y.ok()) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_LhsOrNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (x.ok() || !y.ok()) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (x.ok() || !y.ok()) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_NotLhsOrNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() || !y.ok()) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!x.ok() || !y.ok()) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_LhsOrRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() || y.ok())) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() || y.ok())) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_NotLhsOrRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(!x.ok() || y.ok())) x.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(!x.ok() || y.ok())) y.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_LhsOrNotRhs) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() || !y.ok())) x.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT x, STATUSOR_INT y) {
+      while (!(x.ok() || !y.ok())) y.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_Not_NotLhsOrNotRhs) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          while (!(!x.ok() || !y.ok())) {
+            x.value();
+
+            y.value();
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_AccessAfterStmt) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (sor.ok()) {
+      }
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (!sor.ok()) {
+      }
+
+      sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_TerminatingBranch_Return) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (!sor.ok()) return;
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (sor.ok()) return;
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_TerminatingBranch_Continue) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (Make<bool>()) {
+        if (!sor.ok()) continue;
+
+        sor.value();
+      }
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, While_NestedIfWithBinaryCondition) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          while (Make<bool>()) {
+            if (x.ok() && y.ok()) {
+              x.value();
+
+              y.value();
+            }
+          }
+        }
+      )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          while (Make<bool>()) {
+            if (!(!x.ok() || !y.ok())) {
+              x.value();
+
+              y.value();
+            }
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, BuiltinExpect) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT x, STATUSOR_INT y) {
+          if (!__builtin_expect(!x.ok() || __builtin_expect(!y.ok(), true), false)) {
+            x.value();
+
+            y.value();
+          }
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, CopyAssignment) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      STATUSOR_INT sor = Make<STATUSOR_INT>();
+      if (sor.ok()) {
+        sor = Make<STATUSOR_INT>();
+        sor.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      STATUSOR_INT sor = Make<STATUSOR_INT>();
+      if (!sor.ok()) return;
+
+      sor = Make<STATUSOR_INT>();
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      STATUSOR_INT x = Make<STATUSOR_INT>();
+      if (x.ok()) {
+        STATUSOR_INT y = x;
+        x = Make<STATUSOR_INT>();
+
+        y.value();
+
+        x.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target() {
+          STATUSOR_INT x = Make<STATUSOR_INT>();
+          STATUSOR_INT y = x;
+          if (!y.ok()) return;
+
+          x.value();
+
+          y = Make<STATUSOR_INT>();
+          x.value();
+        }
+      )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      STATUSOR_INT bar;
+    };
+
+    void target(Foo foo) {
+      foo.bar = Make<STATUSOR_INT>();
+      if (foo.bar.ok()) {
+        foo.bar.value();
+
+        foo.bar = Make<STATUSOR_INT>();
+        foo.bar.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ShortCircuitingBinaryOperators) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_BOOL sor) {
+      bool b = sor.ok() & sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_BOOL sor) {
+      bool b = sor.ok() && sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_BOOL sor) {
+      bool b = !sor.ok() && sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_BOOL sor) {
+      bool b = sor.ok() || sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_BOOL sor) {
+      bool b = !sor.ok() || sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      if (b || sor.ok()) {
+        do {
+          sor.value();  // [[unsafe]]
+        } while (true);
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      if (__builtin_expect(b || sor.ok(), false)) {
+        do {
+          sor.value();  // [[unsafe]]
+        } while (false);
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT sor1, STATUSOR_INT sor2) {
+          while (sor1.ok() && sor2.ok()) sor1.value();
+          while (sor1.ok() && sor2.ok()) sor2.value();
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, References) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      STATUSOR_INT x = Make<STATUSOR_INT>();
+      STATUSOR_INT& y = x;
+      if (x.ok()) {
+        x.value();
+
+        y.value();
+      } else {
+        x.value();  // [[unsafe]]
+
+        y.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target() {
+          STATUSOR_INT x = Make<STATUSOR_INT>();
+          STATUSOR_INT& y = x;
+          if (y.ok()) {
+            x.value();
+
+            y.value();
+          } else {
+            x.value();  // [[unsafe]]
+
+            y.value();  // [[unsafe]]
+          }
+        }
+      )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target() {
+          STATUSOR_INT x = Make<STATUSOR_INT>();
+          STATUSOR_INT& y = x;
+          if (!y.ok()) return;
+
+          x.value();
+
+          y = Make<STATUSOR_INT>();
+          x.value();  // [[unsafe]]
+        }
+      )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target() {
+          STATUSOR_INT x = Make<STATUSOR_INT>();
+          const STATUSOR_INT& y = x;
+          if (!y.ok()) return;
+
+          y.value();
+
+          x = Make<STATUSOR_INT>();
+          y.value();  // [[unsafe]]
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, NoReturnAttribute) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    __attribute__((noreturn)) void f();
+
+    void target(STATUSOR_INT sor) {
+      if (!sor.ok()) f();
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void f();
+
+    void target(STATUSOR_INT sor) {
+      if (!sor.ok()) f();
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      __attribute__((noreturn)) ~Foo();
+      void Bar();
+    };
+
+    void target(STATUSOR_INT sor) {
+      if (!sor.ok()) Foo().Bar();
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      ~Foo();
+      void Bar();
+    };
+
+    void target(STATUSOR_INT sor) {
+      if (!sor.ok()) Foo().Bar();
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void f();
+    __attribute__((noreturn)) void g();
+
+    void target(STATUSOR_INT sor) {
+      sor.ok() ? f() : g();
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    __attribute__((noreturn)) void f();
+    void g();
+
+    void target(STATUSOR_INT sor) {
+      !sor.ok() ? f() : g();
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void f();
+    void g();
+
+    void target(STATUSOR_INT sor) {
+      sor.ok() ? f() : g();
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void terminate() __attribute__((noreturn));
+
+    void target(STATUSOR_INT sor) {
+      sor.value();  // [[unsafe]]
+      terminate();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void terminate() __attribute__((noreturn));
+
+    void target(STATUSOR_INT sor) {
+      if (sor.ok()) sor.value();
+      terminate();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void terminate() __attribute__((noreturn));
+
+    struct Foo {
+      ~Foo() __attribute__((noreturn));
+    };
+
+    void target() {
+      auto sor = Make<absl::StatusOr<Foo>>();
+      !(false || !(sor.ok())) ? (void)0 : terminate();
+      sor.value();
+      terminate();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, DeclInLoop) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      while (auto ok = sor.ok()) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    using BoolAlias = bool;
+
+    void target(STATUSOR_INT sor) {
+      while (BoolAlias ok = sor.ok()) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      while (Make<bool>()) {
+        STATUSOR_INT sor = Make<STATUSOR_INT>();
+        sor.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    using StatusOrInt = STATUSOR_INT;
+
+    void target() {
+      while (Make<bool>()) {
+        StatusOrInt sor = Make<STATUSOR_INT>();
+        sor.value();  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, NonEvaluatedExprInCondition) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        bool unknown();
+
+        void target(STATUSOR_INT sor) {
+          if (unknown() && sor.ok()) sor.value();
+          if (sor.ok() && unknown()) sor.value();
+        }
+      )cc");
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        bool unknown();
+
+        void target(STATUSOR_INT sor) {
+          if (!(!unknown() || !sor.ok())) sor.value();
+          if (!(!sor.ok() || !unknown())) sor.value();
+        }
+      )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    bool unknown();
+
+    void target(STATUSOR_INT sor) {
+      if (unknown() || sor.ok()) sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    bool unknown();
+
+    void target(STATUSOR_INT sor) {
+      if (sor.ok() || unknown()) sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, CorrelatedBranches) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      if (b || sor.ok()) {
+        if (!b) sor.value();
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      if (b && !sor.ok()) return;
+      if (b) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      if (sor.ok()) b = true;
+      if (b) sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      if (b) return;
+      if (sor.ok()) b = true;
+      if (b) sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ConditionWithInitStmt) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      if (STATUSOR_INT sor = Make<STATUSOR_INT>(); sor.ok()) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      if (STATUSOR_INT sor = Make<STATUSOR_INT>(); !sor.ok())
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, DeadCode) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      bool b = false;
+      if (b) sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      bool b;
+      b = false;
+      if (b) sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, TemporaryDestructors) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      sor.ok() ? sor.value() : Fatal().value();
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      !sor.ok() ? Fatal().value() : sor.value();
+
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      b ? 0 : sor.ok() ? sor.value() : Fatal().value();
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      for (int i = 0; i < 10; i++) {
+        (b && sor.ok()) ? sor.value() : Fatal().value();
+
+        if (b) sor.value();
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      for (int i = 0; i < 10; i++) {
+        (b || !sor.ok()) ? Fatal().value() : 0;
+
+        if (!b) sor.value();
+      }
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b, STATUSOR_INT sor) {
+      for (int i = 0; i < 10; i++) {
+        (false || !(b && sor.ok())) ? Fatal().value() : 0;
+
+        do {
+          sor.value();
+        } while (b);
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, CheckMacro) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      CHECK(sor.ok());
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      CHECK(!sor.ok());
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, QcheckMacro) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      QCHECK(sor.ok());
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      QCHECK(!sor.ok());
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, CheckNeMacro) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      CHECK_NE(sor.status(), absl::OkStatus());
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, QcheckNeMacro) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      QCHECK_NE(sor.status(), absl::OkStatus());
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, GlobalVars) {
+  // The following examples are not sound as there could be opaque calls between
+  // the ok() and the value() calls that change the StatusOr value.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    static STATUSOR_INT sor;
+
+    void target() {
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      static STATUSOR_INT sor;
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      static STATUSOR_INT sor;
+    };
+
+    void target(Foo foo) {
+      if (foo.sor.ok())
+        foo.sor.value();
+      else
+        foo.sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      static STATUSOR_INT sor;
+    };
+
+    void target() {
+      if (Foo::sor.ok())
+        Foo::sor.value();
+      else
+        Foo::sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      static STATUSOR_INT sor;
+
+      static void target() {
+        if (sor.ok())
+          sor.value();
+        else
+          sor.value();  // [[unsafe]]
+      }
+    };
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      static STATUSOR_INT sor;
+
+      void target() {
+        if (sor.ok())
+          sor.value();
+        else
+          sor.value();  // [[unsafe]]
+      }
+    };
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct S {
+      static const int x = -1;
+    };
+
+    int target(S s) { return s.x; }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ReferenceReceivers) {
+  // The following examples are not sound as there could be opaque calls between
+  // the ok() and the value() calls that change the StatusOr value. However,
+  // this is the behavior that users expect so it is here to stay.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT& sor) {
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      STATUSOR_INT& sor;
+    };
+
+    void target(Foo foo) {
+      if (foo.sor.ok())
+        foo.sor.value();
+      else
+        foo.sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Bar {
+      STATUSOR_INT sor;
+    };
+
+    struct Foo {
+      Bar& bar;
+    };
+
+    void target(Foo foo) {
+      if (foo.bar.sor.ok())
+        foo.bar.sor.value();
+      else
+        foo.bar.sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      STATUSOR_INT& sor;
+    };
+
+    void target(Foo& foo) {
+      if (foo.sor.ok())
+        foo.sor.value();
+      else
+        foo.sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, Lambdas) {
+  ExpectDiagnosticsForLambda(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      [](STATUSOR_INT sor) {
+        if (sor.ok())
+          sor.value();
+        else
+          sor.value();  // [[unsafe]]
+      }(Make<STATUSOR_INT>());
+    }
+  )cc");
+  ExpectDiagnosticsForLambda(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      [sor]() {
+        if (sor.ok())
+          sor.value();
+        else
+          sor.value();  // [[unsafe]]
+      }();
+    }
+  )cc");
+  ExpectDiagnosticsForLambda(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      [&sor]() {
+        if (sor.ok())
+          sor.value();
+        else
+          sor.value();  // [[unsafe]]
+      }();
+    }
+  )cc");
+  ExpectDiagnosticsForLambda(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      [sor2 = sor]() {
+        if (sor2.ok())
+          sor2.value();
+        else
+          sor2.value();  // [[unsafe]]
+      }();
+    }
+  )cc");
+  ExpectDiagnosticsForLambda(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      [&]() {
+        if (sor.ok())
+          sor.value();
+        else
+          sor.value();  // [[unsafe]]
+      }();
+    }
+  )cc");
+  ExpectDiagnosticsForLambda(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      [=]() {
+        if (sor.ok())
+          sor.value();
+        else
+          sor.value();  // [[unsafe]]
+      }();
+    }
+  )cc");
+  ExpectDiagnosticsForLambda(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct Foo {
+      STATUSOR_INT sor;
+
+      void target() {
+        [this]() {
+          if (sor.ok())
+            sor.value();
+          else
+            sor.value();  // [[unsafe]]
+        }();
+      }
+    };
+  )cc");
+}
+
+// TODO(sgatev): Ensure the following test cases are covered.
+TEST_P(UncheckedStatusOrAccessModelTest, Status) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void foo();
+
+    void target(STATUS s) {
+      if (s.ok()) foo();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void foo();
+
+    void target() {
+      STATUS s = Make<STATUSOR_INT>().status();
+      if (s.ok()) foo();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ExpectThatMacro) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      EXPECT_THAT(sor, testing::status::IsOk());
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      EXPECT_THAT(sor.status(), testing::status::IsOk());
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      STATUSOR_INT sor = Make<STATUSOR_INT>();
+      EXPECT_THAT(sor, testing::status::IsOk());
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ExpectOkMacro) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      EXPECT_OK(sor);
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      EXPECT_OK(sor.status());
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      STATUSOR_INT sor = Make<STATUSOR_INT>();
+      EXPECT_OK(sor);
+
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, BreadthFirstBlockTraversalLoop) {
+  // Evaluating the CFG blocks of the code below in breadth-first order results
+  // in an infinite loop. Each iteration of the while loop below results in a
+  // new value being assigned to the storage location of sor1. However,
+  // following a bread-first order of evaluation, downstream blocks will join
+  // environments of different generations of predecessor blocks having distinct
+  // values assigned to the sotrage location of sor1, resulting in not assigning
+  // a value to the storage location of sor1 in successors. As iterations of the
+  // analysis go, the state of the environment flips between having a value
+  // assigned to the storage location of sor1 and not having a value assigned to
+  // it. Since the evaluation of the copy constructor expression in bar(sor1)
+  // depends on a value being assigned to sor1, the state of the environment
+  // also flips between having a storage location assigned to the bar(sor1)
+  // expression and not having a storage location assigned to it. This leads to
+  // an infinite loop as the environment can't stabilize.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void foo(int, int);
+    STATUSOR_INT bar(STATUSOR_INT);
+    void baz(int);
+
+    void target() {
+      while (true) {
+        STATUSOR_INT sor1 = Make<STATUSOR_INT>();
+        if (sor1.ok()) {
+          STATUSOR_INT sor2 = Make<STATUSOR_INT>();
+          if (sor2.ok()) foo(sor1.value(), sor2.value());
+        }
+
+        STATUSOR_INT sor3 = bar(sor1);
+        for (int i = 0; i < 5; i++) sor3 = bar(sor1);
+
+        baz(sor3.value());  // [[unsafe]]
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, UsingDeclaration) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      STATUSOR_INT sor = Make<STATUSOR_INT>();
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, Goto) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+    label:
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+      goto label;
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+    label:
+      if (!sor.ok()) goto label;
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      if (!sor.ok()) return;
+      goto label;
+    label:
+      sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, JoinDistinctValues) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b) {
+      STATUSOR_INT sor;
+      if (b)
+        sor = Make<STATUSOR_INT>();
+      else
+        sor = Make<STATUSOR_INT>();
+
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b) {
+      STATUSOR_INT sor;
+      if (b) {
+        sor = Make<STATUSOR_INT>();
+        if (!sor.ok()) return;
+      } else {
+        sor = Make<STATUSOR_INT>();
+        if (!sor.ok()) return;
+      }
+      sor.value();
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(bool b) {
+      STATUSOR_INT sor;
+      if (b) {
+        sor = Make<STATUSOR_INT>();
+        if (!sor.ok()) return;
+      } else {
+        sor = Make<STATUSOR_INT>();
+      }
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, VarDeclInitExprWithoutValue) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      auto sor = Make<std::pair<int, STATUSOR_INT>>().second;
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      const auto& sor = Make<std::pair<int, STATUSOR_INT>>().second;
+      if (sor.ok())
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, LValueToRValueCastOfChangingValue) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    bool foo();
+
+    void target(bool b1) {
+      STATUSOR_INT sor;
+      if (b1)
+        sor = Make<STATUSOR_INT>();
+      else
+        sor = Make<STATUSOR_INT>();
+
+      do {
+        const auto& b2 = foo();
+        if (b2) break;
+
+        sor.value();  // [[unsafe]]
+      } while (true);
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ConstructorInitializer) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    class target {
+      target() : foo_(Make<STATUSOR_INT>().value()) {  // [[unsafe]]
+      }
+      int foo_;
+    };
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, AssignStatusToBoolVar) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      bool ok = sor.ok();
+      if (ok)
+        sor.value();
+      else
+        sor.value();  // [[unsafe]]
+    }
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target(STATUSOR_INT sor) {
+      bool not_ok = !sor.ok();
+      if (not_ok)
+        sor.value();  // [[unsafe]]
+      else
+        sor.value();
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, StructuredBindings) {
+  // Binding to a pair (which is actually a struct in the mock header).
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      const auto [sor, x] = Make<std::pair<STATUSOR_INT, int>>();
+      if (sor.ok()) sor.value();
+    }
+  )cc");
+
+  // Unsafe case.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      const auto [sor, x] = Make<std::pair<STATUSOR_INT, int>>();
+      sor.value();  // [[unsafe]]
+    }
+  )cc");
+
+  // As a reference.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      const auto& [sor, x] = Make<std::pair<STATUSOR_INT, int>>();
+      if (sor.ok()) sor.value();
+    }
+  )cc");
+
+  // Binding to a ref in a struct.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    struct S {
+      STATUSOR_INT& sor;
+      int i;
+    };
+
+    void target() {
+      const auto& [sor, i] = Make<S>();
+      if (sor.ok()) sor.value();
+    }
+  )cc");
+
+  // In a loop.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      auto vals = Make<std::vector<std::pair<int, STATUSOR_INT>>>();
+      for (const auto& [x, sor] : vals)
+        if (sor.ok()) sor.value();
+    }
+  )cc");
+
+  // Similar to the above, but InitExpr already has the storage initialized,
+  // and bindings refer to them.
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    void target() {
+      auto vals = Make<std::vector<std::pair<int, STATUSOR_INT>>>();
+      for (const auto& p : vals) {
+        const auto& [i, sor] = p;
+        if (sor.ok()) sor.value();
+      }
+    }
+  )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, AssignCompositeLogicExprToVar) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT sor, bool b) {
+          bool c = sor.ok() && b;
+          if (c) sor.value();
+        }
+      )cc");
+
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        void target(STATUSOR_INT sor, bool b) {
+          bool c = !(!sor.ok() || !b);
+          if (c) sor.value();
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, Subclass) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        class Bar;
+
+        class Foo : public absl::StatusOr<Bar> {};
+
+        void target(Foo opt) {
+          opt.value();  // [[unsafe]]
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, SubclassStatus) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        class Foo : public STATUS {};
+
+        void target(Foo opt) { opt.ok(); }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, SubclassOk) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        class Bar;
+
+        class Foo : public absl::StatusOr<Bar> {};
+
+        void target(Foo opt) {
+          if (opt.ok()) opt.value();
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, SubclassOperator) {
+  ExpectDiagnosticsFor(
+      R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+        class Bar;
+
+        class Foo : public absl::StatusOr<Bar> {};
+
+        void target(Foo opt) {
+          *opt;  // [[unsafe]]
+        }
+      )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, GoodLambda) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_use_test_defs.h"
+
+    int target() {
+      STATUSOR_INT sor = Make<STATUSOR_INT>();
+      if (sor.ok()) return [&s = sor.value()] { return s; }();
+      return 0;
+    }
+  )cc");
+}
+
+} // namespace
+
+std::string
+GetAliasMacros(UncheckedStatusOrAccessModelTestAliasKind AliasKind) {
+  switch (AliasKind) {
+  case UncheckedStatusOrAccessModelTestAliasKind::kUnaliased:
+    return R"cc(
+#define STATUSOR_INT ::absl::StatusOr<int>
+#define STATUSOR_BOOL ::absl::StatusOr<bool>
+#define STATUSOR_VOIDPTR ::absl::StatusOr<void*>
+#define STATUS ::absl::Status
+      )cc";
+  case UncheckedStatusOrAccessModelTestAliasKind::kPartiallyAliased:
+    return R"cc(
+        template <typename T>
+        using StatusOrAlias = ::absl::StatusOr<T>;
+#define STATUSOR_INT StatusOrAlias<int>
+#define STATUSOR_BOOL StatusOrAlias<bool>
+#define STATUSOR_VOIDPTR StatusOrAlias<void*>
+#define STATUS ::absl::Status
+      )cc";
+  case UncheckedStatusOrAccessModelTestAliasKind::kFullyAliased:
+    return R"cc(
+        using StatusOrIntAlias = ::absl::StatusOr<int>;
+#define STATUSOR_INT StatusOrIntAlias
+        using StatusOrBoolAlias = ::absl::StatusOr<bool>;
+#define STATUSOR_BOOL StatusOrBoolAlias
+        using StatusOrVoidPtrAlias = ::absl::StatusOr<void*>;
+#define STATUSOR_VOIDPTR StatusOrVoidPtrAlias
+        using StatusAlias = ::absl::Status;
+#define STATUS StatusAlias
+      )cc";
+  }
+  llvm_unreachable("Unknown alias kind.");
+}
+
+std::vector<std::pair<std::string, std::string>>
+GetHeaders(UncheckedStatusOrAccessModelTestAliasKind AliasKind) {
+  std::vector<std::pair<std::string, std::string>> Headers;
+  Headers.emplace_back("absl_type_traits.h", kAbslTypeTraitsHeader);
+  Headers.emplace_back("absl_defs.h", kAbslDefsHeader);
+  Headers.emplace_back("std_type_traits.h", kStdTypeTraitsHeader);
+  Headers.emplace_back("std_string_view.h", kStdStringViewHeader);
+  Headers.emplace_back("std_char_traits.h", kStdCharTraitsHeader);
+  Headers.emplace_back("string_defs.h", kStringDefsHeader);
+  Headers.emplace_back("statusor_defs.h", kStatusOrDefsHeader);
+  Headers.emplace_back("stdlib_defs.h", kStdLibDefsHeader);
+  Headers.emplace_back("unchecked_statusor_use_test_defs.h",
+                       R"cc(
+#include "absl_defs.h"
+#include "statusor_defs.h"
+
+                             template <typename T>
+                             T Make();
+
+                             class Fatal {
+                              public:
+                               ~Fatal() __attribute__((noreturn));
+                               int value();
+                             };
+                       )cc" +
+                           GetAliasMacros(AliasKind));
+  return Headers;
+}
+} // namespace clang::dataflow::statusor_model
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h
new file mode 100644
index 0000000000000..19505eb7740be
--- /dev/null
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h
@@ -0,0 +1,159 @@
+//===- UncheckedStatusOrAccessModelTestFixture.h --------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_UNCHECKEDSTATUSORACCESSMODELTESTFIXTURE_H_
+#define LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_UNCHECKEDSTATUSORACCESSMODELTESTFIXTURE_H_
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "TestingSupport.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang::dataflow::statusor_model {
+
+enum class UncheckedStatusOrAccessModelTestAliasKind {
+  kUnaliased = 0,        // no alias
+  kPartiallyAliased = 1, // template<typename T> using Alias = absl::StatusOr;
+  kFullyAliased = 2,     // using Alias = absl::StatusOr<int>;
+};
+
+// Base class for the test executors. This is needed to abstract away the
+// template parameter from the UncheckedStatusOrAccessModelTestExecutor. This
+// allows us to use UncheckedStatusOrAccessModelTestExecutorBase* in the
+// UncheckedStatusOrAccessModelTest.
+class UncheckedStatusOrAccessModelTestExecutorBase {
+public:
+  virtual void
+  ExpectDiagnosticsFor(std::string SourceCode,
+                       UncheckedStatusOrAccessModelTestAliasKind) const = 0;
+  virtual void ExpectDiagnosticsForLambda(
+      std::string SourceCode,
+      UncheckedStatusOrAccessModelTestAliasKind) const = 0;
+  virtual ~UncheckedStatusOrAccessModelTestExecutorBase() = default;
+};
+
+// Returns these macros according to the alias kind:
+//  - STATUS
+//  - STATUSOR_INT
+//  - STATUSOR_BOOL
+//  - STATUSOR_VOIDPTR
+// Tests should use these macros instead of e.g. absl::StatusOr<int> to ensure
+// the model is insensitive to whether the StatusOr<> is aliased or not.
+std::string GetAliasMacros(UncheckedStatusOrAccessModelTestAliasKind AliasKind);
+
+std::vector<std::pair<std::string, std::string>>
+GetHeaders(UncheckedStatusOrAccessModelTestAliasKind AliasKind);
+
+// This allows us to run the same test suite for multiple models. This allows
+// vendors to model internal APIs in an extension of the base model, and make
+// sure that these tests still pass.
+template <typename Model>
+class UncheckedStatusOrAccessModelTestExecutor
+    : public UncheckedStatusOrAccessModelTestExecutorBase {
+public:
+  void ExpectDiagnosticsFor(
+      std::string SourceCode,
+      UncheckedStatusOrAccessModelTestAliasKind AliasKind) const override {
+    using namespace ::clang::ast_matchers; // NOLINT: Too many names
+    ExpectDiagnosticsFor(SourceCode, hasName("target"), AliasKind);
+  }
+
+  void ExpectDiagnosticsForLambda(
+      std::string SourceCode,
+      UncheckedStatusOrAccessModelTestAliasKind AliasKind) const override {
+    using namespace ::clang::ast_matchers; // NOLINT: Too many names
+    // TODO(sgatev): Investigate why we need to specify the operator name to
+    // avoid matching the lambda destructor here and not in other similar tests.
+    ExpectDiagnosticsFor(SourceCode,
+                         allOf(hasOverloadedOperatorName("()"),
+                               hasDeclContext(cxxRecordDecl(isLambda()))),
+                         AliasKind);
+  }
+
+  template <typename FuncDeclMatcher>
+  void ExpectDiagnosticsFor(
+      std::string SourceCode, FuncDeclMatcher FuncMatcher,
+      UncheckedStatusOrAccessModelTestAliasKind AliasKind) const {
+    std::vector<std::pair<std::string, std::string>> Headers =
+        GetHeaders(AliasKind);
+
+    UncheckedStatusOrAccessModelOptions Options{};
+    std::vector<SourceLocation> Diagnostics;
+    llvm::Error Error = test::checkDataflow<Model>(
+        test::AnalysisInputs<Model>(
+            SourceCode, std::move(FuncMatcher),
+            [](ASTContext &Ctx, Environment &Env) { return Model(Ctx, Env); })
+            .withPostVisitCFG(
+                [&Diagnostics,
+                 Diagnoser = UncheckedStatusOrAccessDiagnoser(Options)](
+                    ASTContext &Ctx, const CFGElement &Elt,
+                    const TransferStateForDiagnostics<
+                        UncheckedStatusOrAccessModel::Lattice> &State) mutable {
+                  auto EltDiagnostics = Diagnoser(Elt, Ctx, State);
+                  llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
+                })
+            .withASTBuildArgs(
+                {"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"})
+            .withASTBuildVirtualMappedFiles(
+                tooling::FileContentMappings(Headers.begin(), Headers.end())),
+        /*VerifyResults=*/[&Diagnostics, SourceCode](
+                              const llvm::DenseMap<unsigned, std::string>
+                                  &Annotations,
+                              const test::AnalysisOutputs &AO) {
+          llvm::DenseSet<unsigned> AnnotationLines;
+          for (const auto &[Line, _] : Annotations)
+            AnnotationLines.insert(Line);
+          auto &SrcMgr = AO.ASTCtx.getSourceManager();
+          llvm::DenseSet<unsigned> DiagnosticLines;
+          for (SourceLocation &Loc : Diagnostics)
+            DiagnosticLines.insert(SrcMgr.getPresumedLineNumber(Loc));
+
+          EXPECT_THAT(DiagnosticLines, testing::ContainerEq(AnnotationLines))
+              << "\nFailing code:\n"
+              << SourceCode;
+        });
+    if (Error)
+      FAIL() << llvm::toString(std::move(Error));
+  }
+};
+
+class UncheckedStatusOrAccessModelTest
+    : public ::testing::TestWithParam<
+          std::pair<UncheckedStatusOrAccessModelTestExecutorBase *,
+                    UncheckedStatusOrAccessModelTestAliasKind>> {
+protected:
+  void ExpectDiagnosticsFor(std::string SourceCode) {
+    GetParam().first->ExpectDiagnosticsFor(SourceCode, GetParam().second);
+  }
+
+  void ExpectDiagnosticsForLambda(std::string SourceCode) {
+    GetParam().first->ExpectDiagnosticsForLambda(SourceCode, GetParam().second);
+  }
+};
+
+} // namespace clang::dataflow::statusor_model
+
+#endif // LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_UNCHECKEDSTATUSORACCESSMODELTESTFIXTURE_H_
diff --git a/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/Models/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/Models/BUILD.gn
index 3fd3aab7970d5..01a05bcfda415 100644
--- a/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/Models/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/Models/BUILD.gn
@@ -11,5 +11,6 @@ static_library("Models") {
   sources = [
     "ChromiumCheckModel.cpp",
     "UncheckedOptionalAccessModel.cpp",
+    "UncheckedStatusOrAccessModel.cpp",
   ]
 }
diff --git a/llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
index 1afd342f67ce4..d4e4db24a57ec 100644
--- a/llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
@@ -43,6 +43,8 @@ unittest("ClangAnalysisFlowSensitiveTests") {
     "TransferTest.cpp",
     "TypeErasedDataflowAnalysisTest.cpp",
     "UncheckedOptionalAccessModelTest.cpp",
+    "UncheckedStatusOrAccessModelTest.cpp",
+    "UncheckedStatusOrAccessModelTestFixture.cpp",
     "ValueTest.cpp",
     "WatchedLiteralsSolverTest.cpp",
   ]

>From 21442747b6a79cb84b4b831c43992517b357d981 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Fri, 10 Oct 2025 15:16:55 -0700
Subject: [PATCH 2/3] nit

Created using spr 1.3.4
---
 .../FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp   | 1 -
 .../FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h     | 2 --
 2 files changed, 3 deletions(-)

diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
index af30e98c51c56..6d9e7614f9260 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -4697,7 +4697,6 @@ TEST_P(UncheckedStatusOrAccessModelTest, Lambdas) {
   )cc");
 }
 
-// TODO(sgatev): Ensure the following test cases are covered.
 TEST_P(UncheckedStatusOrAccessModelTest, Status) {
   ExpectDiagnosticsFor(R"cc(
 #include "unchecked_statusor_use_test_defs.h"
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h
index 19505eb7740be..ff1d323a0086f 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.h
@@ -85,8 +85,6 @@ class UncheckedStatusOrAccessModelTestExecutor
       std::string SourceCode,
       UncheckedStatusOrAccessModelTestAliasKind AliasKind) const override {
     using namespace ::clang::ast_matchers; // NOLINT: Too many names
-    // TODO(sgatev): Investigate why we need to specify the operator name to
-    // avoid matching the lambda destructor here and not in other similar tests.
     ExpectDiagnosticsFor(SourceCode,
                          allOf(hasOverloadedOperatorName("()"),
                                hasDeclContext(cxxRecordDecl(isLambda()))),

>From 2d827ee73550c63762d6d78cdb40e942ef202a1c Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Fri, 10 Oct 2025 16:33:34 -0700
Subject: [PATCH 3/3] remove some mock headers

Created using spr 1.3.4
---
 ...ncheckedStatusOrAccessModelTestFixture.cpp | 362 ------------------
 1 file changed, 362 deletions(-)

diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
index 6d9e7614f9260..c9c655481d271 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -1504,299 +1504,6 @@ template <typename T> struct remove_reference<T&&> { using type = T; };
   OutputIt merge(InputIt1 first1, InputIt1 last1, InputIt2 first2,
                  InputIt2 last2, OutputIt d_first);
 
-  template <class Key, class T, class Compare = less<Key>,
-            class Allocator = allocator<pair<const Key, T>>>
-  class map {
-   public:
-    map();
-    ~map();
-
-    typedef pair<const Key, T> value_type;
-    struct iterator {
-      struct reference {};
-      reference operator*() const;
-      struct pointer {};
-      pointer operator->() const;
-
-      friend bool operator==(const iterator& lhs, const iterator& rhs);
-      friend bool operator!=(const iterator& lhs, const iterator& rhs);
-      iterator& operator++();
-      iterator operator++(int);
-    };
-    struct const_iterator {
-      struct reference {};
-      reference operator*() const;
-      struct pointer {};
-      pointer operator->() const;
-
-      friend bool operator==(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      friend bool operator!=(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      const_iterator& operator++();
-      const_iterator operator++(int);
-    };
-
-    iterator begin();
-    iterator end();
-    const_iterator begin() const;
-    const_iterator end() const;
-
-    bool empty() const;
-    iterator find(const Key& key);
-    const_iterator find(const Key& key) const;
-    T& operator[](const Key& key);
-    T& at(const Key& key);
-    const T& at(const Key& key) const;
-    pair<iterator, bool> insert(const value_type& value);
-    template <class P>
-    pair<iterator, bool> insert(P&& value);
-    size_t count(const Key& key) const;
-  };
-
-  // <unordered_map>
-  template <class Key, class T, class Hash = hash<Key>,
-            class Pred = equal_to<Key>,
-            class Alloc = allocator<pair<const Key, T>>>
-  class unordered_map {
-   public:
-    // types
-    typedef Key key_type;
-    typedef T mapped_type;
-    typedef Hash hasher;
-    typedef Pred key_equal;
-    typedef Alloc allocator_type;
-    typedef pair<const key_type, mapped_type> value_type;
-    typedef value_type& reference;
-    typedef const value_type& const_reference;
-    typedef typename allocator_traits<allocator_type>::pointer pointer;
-    typedef
-        typename allocator_traits<allocator_type>::const_pointer const_pointer;
-    typedef typename allocator_traits<allocator_type>::size_type size_type;
-    typedef typename allocator_traits<allocator_type>::difference_type
-        difference_type;
-
-    struct iterator {
-      struct reference {};
-      reference operator*() const;
-      struct pointer {};
-      pointer operator->() const;
-
-      friend bool operator==(const iterator& lhs, const iterator& rhs);
-      friend bool operator!=(const iterator& lhs, const iterator& rhs);
-      iterator& operator++();
-      iterator operator++(int);
-    };
-    struct const_iterator {
-      struct reference {};
-      reference operator*() const;
-      struct pointer {};
-      pointer operator->() const;
-
-      friend bool operator==(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      friend bool operator!=(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      const_iterator& operator++();
-      const_iterator operator++(int);
-    };
-
-    unordered_map() noexcept;
-    explicit unordered_map(size_type n, const hasher& hf = hasher(),
-                           const key_equal& eql = key_equal(),
-                           const allocator_type& a = allocator_type());
-    template <class InputIterator>
-    unordered_map(InputIterator f, InputIterator l, size_type n = 0,
-                  const hasher& hf = hasher(),
-                  const key_equal& eql = key_equal(),
-                  const allocator_type& a = allocator_type());
-    explicit unordered_map(const allocator_type&);
-    unordered_map(const unordered_map&);
-    unordered_map(const unordered_map&, const Alloc&);
-    unordered_map(unordered_map&&) noexcept;
-    unordered_map(unordered_map&&, const Alloc&);
-    ~unordered_map();
-    unordered_map& operator=(const unordered_map&);
-
-    allocator_type get_allocator() const noexcept;
-
-    bool empty() const noexcept;
-    size_type size() const noexcept;
-    size_type max_size() const noexcept;
-
-    iterator begin() noexcept;
-    iterator end() noexcept;
-    const_iterator begin() const noexcept;
-    const_iterator end() const noexcept;
-    const_iterator cbegin() const noexcept;
-    const_iterator cend() const noexcept;
-
-    hasher hash_function() const;
-    key_equal key_eq() const;
-
-    iterator find(const key_type& k);
-    const_iterator find(const key_type& k) const;
-    size_type count(const key_type& k) const;
-    bool contains(const key_type& k) const;  // C++20
-    pair<iterator, iterator> equal_range(const key_type& k);
-    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
-
-    mapped_type& operator[](const key_type& k);
-    mapped_type& operator[](key_type&& k);
-
-    mapped_type& at(const key_type& k);
-    const mapped_type& at(const key_type& k) const;
-  };
-
-  template <class Key, class Compare = less<Key>,
-            class Allocator = allocator<Key>>
-  class set {
-   public:
-    typedef Key key_type;
-    typedef key_type value_type;
-    typedef Compare key_compare;
-    typedef key_compare value_compare;
-
-    set();
-    set(initializer_list<value_type> l, const value_compare& c = value_compare());
-    ~set();
-
-    struct iterator {
-      Key& operator*();
-      friend bool operator==(const iterator& lhs, const iterator& rhs);
-      friend bool operator!=(const iterator& lhs, const iterator& rhs);
-      iterator& operator++();
-    };
-    struct const_iterator {
-      Key& operator*() const;
-      friend bool operator==(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      friend bool operator!=(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      const_iterator& operator++();
-    };
-
-    iterator begin();
-    iterator end();
-    const_iterator begin() const;
-    const_iterator end() const;
-
-    bool empty() const;
-    iterator find(const key_type& key);
-    const_iterator find(const key_type& key) const;
-    pair<iterator, bool> insert(const value_type& value);
-    size_t count(const key_type& key) const;
-  };
-
-  template <class Key, class Hash = hash<Key>, class KeyEqual = equal_to<Key>,
-            class Allocator = allocator<Key>>
-  class unordered_set {
-   public:
-    using key_type = Key;
-    using value_type = Key;
-    using size_type = typename allocator_traits<Allocator>::size_type;
-    using difference_type = typename allocator_traits<Allocator>::difference_type;
-    using hasher = Hash;
-    using key_equal = KeyEqual;
-    using allocator_type = Allocator;
-    using reference = value_type&;
-    using const_reference = const value_type&;
-    using pointer = typename allocator_traits<Allocator>::pointer;
-    using const_pointer = typename allocator_traits<Allocator>::const_pointer;
-
-    struct iterator {
-      reference operator*() const;
-      pointer operator->() const;
-
-      friend bool operator==(const iterator& lhs, const iterator& rhs);
-      friend bool operator!=(const iterator& lhs, const iterator& rhs);
-      iterator& operator++();
-      iterator operator++(int);
-    };
-    struct const_iterator {
-      const_reference operator*() const;
-      const_pointer operator->() const;
-
-      friend bool operator==(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      friend bool operator!=(const const_iterator& lhs,
-                             const const_iterator& rhs);
-      const_iterator& operator++();
-      const_iterator operator++(int);
-    };
-
-    unordered_set() noexcept;
-    explicit unordered_set(size_type bucket_count, const Hash& hash = Hash(),
-                           const key_equal& equal = key_equal(),
-                           const Allocator& alloc = Allocator());
-    unordered_set(size_type bucket_count, const Allocator& alloc);
-    unordered_set(size_type bucket_count, const Hash& hash,
-                  const Allocator& alloc);
-    explicit unordered_set(const Allocator& alloc);
-    template <class InputIt>
-    unordered_set(InputIt first, InputIt last, size_type bucket_count = 1,
-                  const Hash& hash = Hash(),
-                  const key_equal& equal = key_equal(),
-                  const Allocator& alloc = Allocator());
-    template <class InputIt>
-    unordered_set(InputIt first, InputIt last, size_type bucket_count,
-                  const Allocator& alloc);
-    template <class InputIt>
-    unordered_set(InputIt first, InputIt last, size_type bucket_count,
-                  const Hash& hash, const Allocator& alloc);
-    unordered_set(const unordered_set& other);
-    unordered_set(const unordered_set& other, const Allocator& alloc);
-    unordered_set(unordered_set&& other);
-    unordered_set(unordered_set&& other, const Allocator& alloc);
-    unordered_set(initializer_list<value_type> init, size_type bucket_count = 1,
-                  const Hash& hash = Hash(),
-                  const key_equal& equal = key_equal(),
-                  const Allocator& alloc = Allocator());
-    unordered_set(initializer_list<value_type> init, size_type bucket_count,
-                  const Allocator& alloc);
-    unordered_set(initializer_list<value_type> init, size_type bucket_count,
-                  const Hash& hash, const Allocator& alloc);
-
-    ~unordered_set();
-
-    unordered_set& operator=(const unordered_set& other);
-    unordered_set& operator=(unordered_set&& other);
-    unordered_set& operator=(initializer_list<value_type> ilist);
-
-    iterator begin() noexcept;
-    const_iterator begin() const noexcept;
-    const_iterator cbegin() const noexcept;
-    iterator end() noexcept;
-    const_iterator end() const noexcept;
-    const_iterator cend() const noexcept;
-
-    bool empty() const noexcept;
-    size_type size() const noexcept;
-
-    void clear() noexcept;
-
-    std::pair<iterator, bool> insert(const value_type& value);
-    std::pair<iterator, bool> insert(value_type&& value);
-    iterator insert(const_iterator hint, const value_type& value);
-    iterator insert(const_iterator hint, value_type&& value);
-    template <class InputIt>
-    void insert(InputIt first, InputIt last);
-    void insert(initializer_list<value_type> ilist);
-
-    template <class... Args>
-    pair<iterator, bool> emplace(Args&&... args);
-
-    iterator erase(const_iterator pos);
-    iterator erase(const_iterator first, const_iterator last);
-    size_type erase(const key_type& key);
-
-    void swap(unordered_set& other);
-
-    size_type count(const Key& key) const;
-    iterator find(const Key& key);
-    const_iterator find(const Key& key) const;
-  };
-
   template <typename T, class Allocator = allocator<T>>
   class vector {
    public:
@@ -1845,75 +1552,6 @@ template <typename T> struct remove_reference<T&&> { using type = T; };
     size_t size() const;
   };
 
-  template <typename T, class Allocator = allocator<T>>
-  class deque {
-   public:
-    using value_type = T;
-    using size_type = typename allocator_traits<Allocator>::size_type;
-
-    // Constructors.
-    deque() {}
-    deque(size_type, const Allocator& = Allocator()) {}
-    deque(initializer_list<T> initializer_list, const Allocator& = Allocator()) {}
-    deque(const deque& deque) {}
-    ~deque();
-
-    // Modifiers.
-    void push_back(const T& value);
-    void push_back(T&& value);
-    void push_front(const T& value);
-    void push_front(T&& value);
-    template <typename... Args>
-    T& emplace_back(Args&&... args);
-    template <typename... Args>
-    T& emplace_front(Args&&... args);
-
-    // Iterators
-    class InputIterator {
-     public:
-      InputIterator(const InputIterator&);
-      ~InputIterator();
-      InputIterator& operator=(const InputIterator&);
-      InputIterator& operator++();
-      T& operator*() const;
-      bool operator!=(const InputIterator&) const;
-      bool operator==(const InputIterator&) const;
-    };
-    typedef InputIterator iterator;
-    typedef const InputIterator const_iterator;
-    iterator begin() noexcept;
-    const_iterator begin() const noexcept;
-    iterator end() noexcept;
-    const_iterator end() const noexcept;
-    T* data() noexcept;
-    const T* data() const noexcept;
-    T& operator[](size_t n);
-    const T& operator[](size_t n) const;
-    T& at(size_t n);
-    const T& at(size_t n) const;
-    size_t size() const;
-  };
-
-  template <class T, size_t N>
-  struct array {
-    using value_type = T;
-    void fill(const T& value);
-    void swap(array& other) noexcept;
-    size_t size() const noexcept;
-    size_t max_size() const noexcept;
-    bool empty() const noexcept;
-    T& operator[](size_t n) noexcept;
-    const T& operator[](size_t n) const noexcept;
-    T& at(size_t n);
-    const T& at(size_t n) const;
-    T& front() noexcept;
-    const T& front() const noexcept;
-    T& back() noexcept;
-    const T& back() const noexcept;
-    T* data() noexcept;
-    const T* data() const noexcept;
-  };
-
   template <typename T>
   struct default_delete {};
 



More information about the llvm-commits mailing list