blob: 86131d0280779661a09fd7a9b6f7b7cf31650fd4 [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.
*(nullable + i); // [[unsafe]]
*(nullable - i); // [[unsafe]]
*+nullable; // [[unsafe]]
// Operations with side-effects; these need to restore the original value
// of `nullable` every time.
*nullable++; // [[unsafe]]
nullable = orig;
// TODO(mboehme): False negative. The increment operation is creating a
// new nonnull value, so the dereference isn't considered unsafe, but the
// increment of a nullable pointer should itself be considered unsafe.
*++nullable;
nullable = orig;
*nullable--; // [[unsafe]]
nullable = orig;
// TODO(mboehme): False negative. The decrement operation is creating a
// new nonnull value, so the dereference isn't considered unsafe, but the
// decrement of a nullable pointer should itself be considered unsafe.
*--nullable;
nullable = orig;
// On a nullable pointer, the pointer arithmetic itself should already be
// considered unsafe, unless we know that the offset is zero.
nullable + i; // TODO(b/321265696): False negative.
nullable - i; // TODO(b/321265696): False negative.
nullable + 0;
nullable - 0;
// Unary `+` is safe on a nullable pointer.
+nullable;
++nullable; // TODO(b/321265696): False negative.
nullable = orig;
nullable++; // TODO(b/321265696): False negative.
nullable = orig;
--nullable; // TODO(b/321265696): False negative.
nullable = orig;
nullable--; // TODO(b/321265696): False negative.
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;
}
)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;
}
)cc"));
}
} // namespace
} // namespace clang::tidy::nullability