blob: c61b1240c47be681fac71f5a199154d363fefa58 [file] [log] [blame]
Martin Brænnec4903062023-04-24 23:40:36 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5// Tests for nullability of function pointers.
6
Googler7f19b2b2023-05-01 09:44:57 -07007#include "nullability/test/check_diagnostics.h"
Martin Brænnec4903062023-04-24 23:40:36 -07008#include "third_party/llvm/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h"
9
Sam McCall4f6be422023-06-27 02:51:22 -070010namespace clang::tidy::nullability {
Martin Brænnec4903062023-04-24 23:40:36 -070011namespace {
12
13TEST(PointerNullabilityTest, FunctionToPointerDecayIsNonnull) {
14 EXPECT_TRUE(checkDiagnostics(R"cc(
15 void target() {
16 // Use `static_cast` to force function-to-pointer decay.
17 __assert_nullability<NK_nonnull>(static_cast<void (*)()>(target));
18 }
19 )cc"));
20}
21
22TEST(PointerNullabilityTest, CallExplicitlyDereferencedDirectCallee) {
23 EXPECT_TRUE(checkDiagnostics(R"cc(
24 void callee();
25 void target() { (*callee)(); }
26 )cc"));
27}
28
29TEST(PointerNullabilityTest, AnnotationsInReturnType) {
30 EXPECT_TRUE(checkDiagnostics(R"cc(
Sam McCall7d9afee2023-06-27 01:43:24 -070031 int *_Nullable target() {
Martin Brænnec4903062023-04-24 23:40:36 -070032 // Use `static_cast` to force function-to-pointer decay.
33 __assert_nullability<NK_nonnull, NK_nullable>(
Sam McCall7d9afee2023-06-27 01:43:24 -070034 static_cast<int *(*)()>(target));
Martin Brænnec4903062023-04-24 23:40:36 -070035 return nullptr;
36 }
37 )cc"));
38}
39
40TEST(PointerNullabilityTest, AnnotationsInParameters) {
41 EXPECT_TRUE(checkDiagnostics(R"cc(
42 void target(int *_Nullable) {
43 // Use `static_cast` to force function-to-pointer decay.
44 __assert_nullability<NK_nonnull, NK_nullable>(
45 static_cast<void (*)(int *)>(target));
46 }
47 )cc"));
48}
49
50TEST(PointerNullabilityTest, NonnullCallback) {
51 EXPECT_TRUE(checkDiagnostics(R"cc(
52 void target(void (*_Nonnull callback)()) {
53 // Both an explicit dereference and an implicit dereference done by a
54 // function call should be allowed.
55 (*callback)();
56 callback();
57 }
58 )cc"));
59}
60
61TEST(PointerNullabilityTest, NullableCallback) {
62 EXPECT_TRUE(checkDiagnostics(R"cc(
63 void target(void (*_Nullable callback)()) {
64 // Both an explicit dereference and an implicit dereference done by a
65 // function call should be marked as unsafe.
66 (*callback)(); // [[unsafe]]
67 callback(); // [[unsafe]]
68 }
69 )cc"));
70}
71
72TEST(PointerNullabilityTest, NonnullCallbackWithoutCalleeDecl) {
73 EXPECT_TRUE(checkDiagnostics(R"cc(
74 using NonnullCallbackType = void (*_Nonnull)();
75 NonnullCallbackType getCallback();
76 void target() {
77 __assert_nullability<NK_nonnull>(getCallback());
78 (*getCallback())();
79 getCallback()();
80 }
81 )cc"));
82}
83
84TEST(PointerNullabilityTest, NullableCallbackWithoutCalleeDecl) {
85 EXPECT_TRUE(checkDiagnostics(R"cc(
86 using NullableCallbackType = void (*_Nullable)();
87 NullableCallbackType getCallback();
88 void target(bool b) {
89 __assert_nullability<NK_nullable>(getCallback());
90 (*getCallback())(); // [[unsafe]]
91 getCallback()(); // [[unsafe]]
92 }
93 )cc"));
94}
95
96} // namespace
Sam McCall4f6be422023-06-27 02:51:22 -070097} // namespace clang::tidy::nullability