[nullability] Add some basic tests for smart pointers.

As we don't actually support smart pointers yet, these contain a lot of false
negatives. For now, the tests are mainly intended to ensure that we don't
introduce assertion failures or crashes as we add support for smart pointers.

PiperOrigin-RevId: 581934095
Change-Id: I4d5d34589443153a6890470b0c308891b39f0a67
diff --git a/nullability/inference/infer_tu_test.cc b/nullability/inference/infer_tu_test.cc
index 1a76de5..9421631 100644
--- a/nullability/inference/infer_tu_test.cc
+++ b/nullability/inference/infer_tu_test.cc
@@ -27,6 +27,7 @@
 using ast_matchers::hasName;
 using testing::_;
 using testing::ElementsAre;
+using testing::IsEmpty;
 using testing::UnorderedElementsAre;
 
 MATCHER_P2(inferredSlot, I, Nullability, "") {
@@ -268,5 +269,44 @@
                     {inferredSlot(1, Inference::NONNULL)})));
 }
 
+using InferTUSmartPointerTest = InferTUTest;
+
+TEST_F(InferTUSmartPointerTest, ParamsFromCallSite) {
+  build(R"cc(
+#include <memory>
+    void callee(std::unique_ptr<int> p, std::unique_ptr<int> q,
+                std::unique_ptr<int> r);
+    void target(std::unique_ptr<int> a, Nonnull<std::unique_ptr<int>> b,
+                Nullable<std::unique_ptr<int>> c) {
+      callee(a, b, c);
+    }
+  )cc");
+
+  // TODO(b/304963199): Currently not inferring anything because we don't
+  // support smart pointers. The expected result is the same as for the
+  // `ParamsFromCallSite` test.
+  ASSERT_THAT(infer(), IsEmpty());
+}
+
+TEST_F(InferTUSmartPointerTest, ReturnTypeNullable) {
+  build(R"cc(
+#include <memory>
+    std::unique_ptr<int> target() { return std::unique_ptr<int>(); }
+  )cc");
+  // TODO(b/304963199): Currently not inferring anything because we don't
+  // support smart pointers. The expected result is a nullable return type.
+  EXPECT_THAT(infer(), IsEmpty());
+}
+
+TEST_F(InferTUSmartPointerTest, ReturnTypeNonnull) {
+  build(R"cc(
+#include <memory>
+    std::unique_ptr<int> target() { return std::make_unique<int>(0); }
+  )cc");
+  // TODO(b/304963199): Currently not inferring anything because we don't
+  // support smart pointers. The expected result is a nonnull return type.
+  EXPECT_THAT(infer(), IsEmpty());
+}
+
 }  // namespace
 }  // namespace clang::tidy::nullability
diff --git a/nullability/test/BUILD b/nullability/test/BUILD
index 438fbd2..ad3c253 100644
--- a/nullability/test/BUILD
+++ b/nullability/test/BUILD
@@ -248,6 +248,16 @@
     ],
 )
 
+cc_test(
+    name = "smart_pointers",
+    srcs = ["smart_pointers.cc"],
+    deps = [
+        ":check_diagnostics",
+        "@llvm-project//third-party/unittest:gtest",
+        "@llvm-project//third-party/unittest:gtest_main",
+    ],
+)
+
 nullability_test(
     name = "symbolic_nullability",
     srcs = ["symbolic_nullability.cc"],
diff --git a/nullability/test/headers_for_test.cc b/nullability/test/headers_for_test.cc
index ad84453..74587e2 100644
--- a/nullability/test/headers_for_test.cc
+++ b/nullability/test/headers_for_test.cc
@@ -40,8 +40,24 @@
   void *operator new(std::size_t size, const std::nothrow_t &) noexcept;
 )cc";
 
+constexpr char kMemoryHeader[] = R"cc(
+  namespace std {
+  template <class T>
+  class unique_ptr {
+   public:
+    unique_ptr() {}
+    T &operator*() const;
+  };
+
+  template <class T, class... Args>
+  unique_ptr<T> make_unique(Args &&...args);
+  }  // namespace std
+)cc";
+
 tooling::FileContentMappings headersForTest() {
-  return {{"preamble.h", kPreamble}, {"new", kNewHeader}};
+  return {{"preamble.h", kPreamble},
+          {"new", kNewHeader},
+          {"memory", kMemoryHeader}};
 }
 
 llvm::StringMap<std::string> headersForTestAsStringMap() {
diff --git a/nullability/test/smart_pointers.cc b/nullability/test/smart_pointers.cc
new file mode 100644
index 0000000..08d9b05
--- /dev/null
+++ b/nullability/test/smart_pointers.cc
@@ -0,0 +1,90 @@
+// Part of the Crubit project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Tests that involve smart pointers.
+
+// TODO(b/304963199): We do not actually check smart pointers, so these tests
+// are full of false negatives. For now, they are mainly intended to check that
+// the check does not crash or assert-fail on smart pointers.
+
+#include "nullability/test/check_diagnostics.h"
+#include "third_party/llvm/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h"
+
+namespace clang::tidy::nullability {
+namespace {
+
+TEST(SmartPointerTest, DefaultConstructedSmartPointerIsNull) {
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+#include <memory>
+    void target() {
+      std::unique_ptr<int> p;
+      *p;  // TODO(b/304963199): False negative.
+    }
+  )cc"));
+}
+
+TEST(SmartPointerTest, MakeUniqueReturnsNonNull) {
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+#include <memory>
+    void target() {
+      auto p = std::make_unique<int>(0);
+      *p;
+    }
+  )cc"));
+}
+
+TEST(SmartPointerTest, ParameterAnnotations) {
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+#include <memory>
+    void target(Nonnull<std::unique_ptr<int>> nonnull,
+                Nullable<std::unique_ptr<int>> nullable,
+                std::unique_ptr<int> unknown) {
+      *nonnull;
+      *nullable;  // TODO(b/304963199): False negative.
+      *unknown;
+    }
+  )cc"));
+}
+
+TEST(SmartPointerTest, ReturnValue_Nonnull) {
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+#include <memory>
+    bool cond();
+    Nonnull<std::unique_ptr<int>> target() {
+      if (cond())
+        return std::make_unique<int>(0);
+      else
+        return std::unique_ptr<int>();  // TODO(b/304963199): False negative.
+    }
+  )cc"));
+}
+
+TEST(SmartPointerTest, ReturnValue_Nullable) {
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+#include <memory>
+    bool cond();
+    Nullable<std::unique_ptr<int>> target() {
+      if (cond())
+        return std::make_unique<int>(0);
+      else
+        return std::unique_ptr<int>();
+    }
+  )cc"));
+}
+
+TEST(SmartPointerTest, ReturnValue_Unknown) {
+  EXPECT_TRUE(checkDiagnostics(R"cc(
+#include <memory>
+    bool cond();
+    std::unique_ptr<int> target() {
+      if (cond())
+        return std::make_unique<int>(0);
+      else
+        return std::unique_ptr<int>();
+    }
+  )cc"));
+}
+
+}  // namespace
+}  // namespace clang::tidy::nullability