[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