blob: e450f44ed70e54f3c4d8c889ad4057cc19a3fa89 [file] [log] [blame]
// 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 for pointer arithmetic.
#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, PointerArithmeticNullable) {
EXPECT_TRUE(checkDiagnostics(R"cc(
void target(int *_Nullable nullable, int i) {
int *orig = nullable;
// Operations without side-effects.
// On a nullable pointer, the pointer arithmetic itself should already be
// considered unsafe, unless we know that the offset is zero.
nullable + i; // [[unsafe]]
nullable - i; // [[unsafe]]
nullable + 0;
nullable - 0;
// Unary `+` is safe on a nullable pointer.
+nullable;
// Operations with side-effects; these need to restore the original value
// of `nullable` every time.
nullable++; // [[unsafe]]
nullable = orig;
++nullable; // [[unsafe]]
nullable = orig;
nullable--; // [[unsafe]]
nullable = orig;
--nullable; // [[unsafe]]
nullable = orig;
nullable += 1; // [[unsafe]]
nullable = orig;
nullable -= 1; // [[unsafe]]
nullable = orig;
}
)cc"));
}
TEST(PointerNullabilityTest, PointerArithmeticNonnull) {
EXPECT_TRUE(checkDiagnostics(R"cc(
void target(int *_Nonnull nonnull, int i) {
int *orig = nonnull;
nonnull + i;
nonnull - i;
+nonnull;
++nonnull;
nonnull = orig;
nonnull++;
nonnull = orig;
--nonnull;
nonnull = orig;
nonnull--;
nonnull = orig;
nonnull += 1;
nonnull = orig;
nonnull -= 1;
nonnull = orig;
}
)cc"));
}
TEST(PointerNullabilityTest, PointerArithmeticUnknown) {
EXPECT_TRUE(checkDiagnostics(R"cc(
void target(int *unknown, int i) {
int *orig = unknown;
unknown + i;
unknown - i;
+unknown;
++unknown;
unknown = orig;
unknown++;
unknown = orig;
--unknown;
unknown = orig;
unknown--;
unknown = orig;
unknown += 1;
unknown = orig;
unknown -= 1;
unknown = orig;
}
)cc"));
}
TEST(PointerNullabilityTest, PointerDifference) {
EXPECT_TRUE(checkDiagnostics(R"cc(
void target(int *_Nullable nullable, int *_Nonnull nonnull, int *unknown) {
nullable - nullable; // [[unsafe]]
nullable - nonnull; // [[unsafe]]
nullable - unknown; // [[unsafe]]
nonnull - nullable; // [[unsafe]]
nonnull - nonnull;
nonnull - unknown;
unknown - nullable; // [[unsafe]]
unknown - nonnull;
unknown - unknown;
}
)cc"));
}
} // namespace
} // namespace clang::tidy::nullability