blob: 635d1c7c4f4366111725b27623ecb3e8ddd302dc [file] [log] [blame] [edit]
// 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 check that `__assert_nullability` works correctly.
//
// Note that this file should not contain all tests that use
// `__assert_nullability`, but only tests to verify that `__assert_nullability`
// itself works.
//
// TODO(mboehme): Because this test is doing something different than the
// other tests, we would ideally want to place it in a different directory.
// For the time being, the `_test` suffix at the end of the filename is
// intended as a weak way of indicating this.
#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(PointerNullabilityTest, AssertNullability) {
// Concrete struct.
EXPECT_TRUE(checkDiagnostics(R"cc(
struct StructNonnullNullable {
int *_Nonnull nonnull;
int *_Nullable nullable;
};
void target(StructNonnullNullable p) {
__assert_nullability<>(p);
__assert_nullability<NK_nonnull>(p); // [[unsafe]]
__assert_nullability<NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_nonnull, NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_nonnull, NK_unspecified>(p); // [[unsafe]]
__assert_nullability<NK_nonnull, NK_nonnull>(p); // [[unsafe]]
__assert_nullability<NK_nullable, NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_unspecified, NK_nullable>(p); // [[unsafe]]
}
)cc"));
// Struct with two template type parameters.
EXPECT_TRUE(checkDiagnostics(R"cc(
template <typename T0, typename T1>
struct Struct2Arg {};
void target(Struct2Arg<int *, int *_Nullable> p) {
__assert_nullability<NK_unspecified>(p); // [[unsafe]]
__assert_nullability<NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_unspecified, NK_nonnull>(p); // [[unsafe]]
__assert_nullability<NK_unspecified, NK_nullable>(p);
__assert_nullability<NK_unspecified, NK_unspecified>(p); // [[unsafe]]
__assert_nullability<NK_nonnull, NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_nullable, NK_nullable>(p); // [[unsafe]]
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_unspecified>(p);
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nullable>(p);
}
)cc"));
// Struct with one type and non-type template parameters.
EXPECT_TRUE(checkDiagnostics(R"cc(
template <int I0, typename T1, typename T2>
struct Struct3ArgWithInt {};
void target(Struct3ArgWithInt<2147483647, int *_Nullable, int *_Nonnull> p) {
__assert_nullability<>(p); // [[unsafe]]
__assert_nullability<NK_nonnull>(p); // [[unsafe]]
__assert_nullability<NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_unspecified, NK_nonnull>(p); // [[unsafe]]
__assert_nullability<NK_nonnull, NK_nonnull>(p); // [[unsafe]]
__assert_nullability<NK_nonnull, NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_nullable, NK_nonnull>(p);
__assert_nullability<NK_nullable, NK_nullable>(p); // [[unsafe]]
__assert_nullability<NK_nullable, NK_unspecified>(p); // [[unsafe]]
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nonnull>(p);
}
)cc"));
// Nested template arguments.
EXPECT_TRUE(checkDiagnostics(R"cc(
template <typename T0, typename T1>
struct Struct2Arg {};
void target(
Struct2Arg<Struct2Arg<int *, int *_Nullable>,
Struct2Arg<Struct2Arg<int *_Nullable, int *_Nonnull>,
Struct2Arg<int *_Nullable, int *_Nullable>>>
p) {
__assert_nullability<>(p); // [[unsafe]]
__assert_nullability<NK_unspecified, NK_nullable, NK_nullable, NK_nonnull,
NK_nullable, NK_nullable>(p);
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nullable, NK_nonnull, NK_nullable,
NK_nullable, NK_nullable>(p);
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nullable, NK_nonnull, NK_nullable>(
p);
}
)cc"));
// Struct with two template parameters substituted with concrete structs.
EXPECT_TRUE(checkDiagnostics(R"cc(
struct StructUnknownNullable {
int *unknown;
int *_Nullable nullable;
};
struct StructNullableNonnull {
int *_Nullable nullable;
int *_Nonnull nonnull;
};
template <typename T1, typename T2>
struct Struct2Arg {};
void target(Struct2Arg<StructUnknownNullable, StructNullableNonnull> p) {
__assert_nullability<>(p);
__assert_nullability<NK_unspecified, NK_nullable>(p); // [[unsafe]]
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nullable>(p);
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nullable, NK_nonnull>(p);
__assert_nullability // [[unsafe]]
<NK_nonnull, NK_nullable, NK_nullable, NK_nonnull>(p);
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nullable, NK_nonnull,
NK_unspecified>(p);
}
)cc"));
EXPECT_TRUE(checkDiagnostics(R"cc(
template <typename T0, typename T1>
struct Struct2Arg {
T0 arg0;
T1 arg1;
T0 getT0();
T1 getT1();
};
void target(
Struct2Arg<Struct2Arg<int *, int *_Nullable>,
Struct2Arg<Struct2Arg<int *_Nullable, int *_Nonnull>,
Struct2Arg<int *_Nullable, int *_Nullable>>>
p) {
__assert_nullability<NK_unspecified, NK_nullable, NK_nullable, NK_nonnull,
NK_nullable, NK_nullable>(p);
__assert_nullability<NK_unspecified, NK_nullable>(p.arg0);
__assert_nullability<NK_unspecified>(p.arg0.arg0);
__assert_nullability<NK_nullable>(p.arg0.arg1);
__assert_nullability<NK_nullable, NK_nonnull, NK_nullable, NK_nullable>(
p.arg1);
__assert_nullability<NK_nullable, NK_nonnull>(p.arg1.arg0);
__assert_nullability<NK_nullable>(p.arg1.arg0.arg0);
__assert_nullability<NK_nonnull>(p.arg1.arg0.arg1);
__assert_nullability<NK_nullable, NK_nullable>(p.arg1.arg1);
__assert_nullability<NK_nullable>(p.arg1.arg1.arg0);
__assert_nullability<NK_nullable>(p.arg1.arg1.arg1);
__assert_nullability<>(p.arg0.arg0); // [[unsafe]]
__assert_nullability<NK_unspecified>(p.arg0); // [[unsafe]]
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_nonnull, NK_nullable, NK_nullable>(
p.arg1);
__assert_nullability<NK_unspecified, NK_nullable>(p.getT0());
__assert_nullability<NK_nonnull>(p.getT1().getT0().getT1());
__assert_nullability // [[unsafe]]
<NK_unspecified, NK_nullable, NK_unspecified>(p.getT0());
__assert_nullability // [[unsafe]]
<NK_unspecified>(p.getT0());
__assert_nullability<NK_nonnull>(p.getT1().arg0.getT1());
__assert_nullability<NK_nonnull>(p.arg1.getT0().arg1);
__assert_nullability<NK_nonnull>(p.arg1.arg0.arg1);
__assert_nullability // [[unsafe]]
<>(p.getT1().getT0().getT1());
__assert_nullability // [[unsafe]]
<NK_nonnull, NK_nonnull>(p.arg1.getT0().arg1);
}
)cc"));
EXPECT_TRUE(checkDiagnostics(R"cc(
void target(int *_Nullable p, int *_Nonnull q, int *r) {
__assert_nullability<NK_nonnull, NK_nullable>(&p);
__assert_nullability<NK_nonnull, NK_nonnull>(&q);
__assert_nullability<NK_nonnull>(&*p); // [[unsafe]]
__assert_nullability<NK_nonnull>(&*q);
__assert_nullability<NK_nonnull>(&*r);
}
)cc"));
}
} // namespace
} // namespace clang::tidy::nullability