[nullability] Move test CallExprParamAssignment to function_calls.cc
PiperOrigin-RevId: 523623034
diff --git a/nullability_verification/test/function_calls.cc b/nullability_verification/test/function_calls.cc
index 4fb965d..01f66ec 100644
--- a/nullability_verification/test/function_calls.cc
+++ b/nullability_verification/test/function_calls.cc
@@ -123,6 +123,207 @@
)cc"));
}
+TEST(PointerNullabilityTest, CallExprParamAssignment) {
+ // free function with single param
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ void takeNonnull(int *_Nonnull);
+ void takeNullable(int *_Nullable);
+ void takeUnannotated(int *);
+ void target(int *_Nonnull ptr_nonnull, int *_Nullable ptr_nullable,
+ int *ptr_unannotated) {
+ takeNonnull(nullptr); // [[unsafe]]
+ takeNonnull(ptr_nonnull);
+ takeNonnull(ptr_nullable); // [[unsafe]]
+ takeNonnull(ptr_unannotated);
+
+ takeNullable(nullptr);
+ takeNullable(ptr_nonnull);
+ takeNullable(ptr_nullable);
+ takeNullable(ptr_unannotated);
+
+ takeUnannotated(nullptr);
+ takeUnannotated(ptr_nonnull);
+ takeUnannotated(ptr_nullable);
+ takeUnannotated(ptr_unannotated);
+ }
+ )cc"));
+
+ // overloaded operator with single param
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ // map<int * _Nonnull, int>
+ struct MapWithNonnullKeys {
+ int &operator[](int *_Nonnull key);
+ };
+ // map<int * _Nullable, int>
+ struct MapWithNullableKeys {
+ int &operator[](int *_Nullable key);
+ };
+ // map<int *, int>
+ struct MapWithUnannotatedKeys {
+ int &operator[](int *key);
+ };
+ void target(int *_Nonnull ptr_nonnull, int *_Nullable ptr_nullable,
+ int *ptr_unannotated) {
+ MapWithNonnullKeys nonnull_keys;
+ nonnull_keys[nullptr] = 42; // [[unsafe]]
+ nonnull_keys[ptr_nonnull] = 42;
+ nonnull_keys[ptr_nullable] = 42; // [[unsafe]]
+ nonnull_keys[ptr_unannotated] = 42;
+
+ MapWithNullableKeys nullable_keys;
+ nullable_keys[nullptr] = 42;
+ nullable_keys[ptr_nonnull] = 42;
+ nullable_keys[ptr_nullable] = 42;
+ nullable_keys[ptr_unannotated] = 42;
+
+ MapWithUnannotatedKeys unannotated_keys;
+ unannotated_keys[nullptr] = 42;
+ unannotated_keys[ptr_nonnull] = 42;
+ unannotated_keys[ptr_nullable] = 42;
+ unannotated_keys[ptr_unannotated] = 42;
+ }
+ )cc"));
+
+ // free function with multiple params of mixed nullability
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ void takeMixed(int *, int *_Nullable, int *_Nonnull);
+ void target() {
+ takeMixed(nullptr, nullptr, nullptr); // [[unsafe]]
+ }
+ )cc"));
+
+ // overloaded operator with multiple params of mixed nullability
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ struct TakeMixed {
+ void operator()(int *, int *_Nullable, int *_Nonnull);
+ };
+ void target() {
+ TakeMixed takeMixed;
+ takeMixed(nullptr, nullptr, nullptr); // [[unsafe]]
+ }
+ )cc"));
+
+ // member function
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ struct Foo {
+ void takeNonnull(int *_Nonnull);
+ void takeNullable(int *_Nullable);
+ void takeUnannotated(int *);
+ };
+ void target(Foo foo) {
+ foo.takeNonnull(nullptr); // [[unsafe]]
+ foo.takeNullable(nullptr);
+ foo.takeUnannotated(nullptr);
+ }
+ )cc"));
+
+ // function pointer
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ void target(void (*takeNonnull)(int *_Nonnull),
+ void (*takeNullable)(int *_Nullable),
+ void (*takeUnannotated)(int *)) {
+ takeNonnull(nullptr); // [[unsafe]]
+ takeNullable(nullptr);
+ takeUnannotated(nullptr);
+ }
+ )cc"));
+
+ // pointer to function pointer
+ //
+ // TODO(b/233582219): Fix false negative. Implement support for retrieving
+ // parameter types from a pointer to function pointer.
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ void target(void (**takeNonnull)(int *_Nonnull),
+ void (**takeNullable)(int *_Nullable),
+ void (**takeUnannotated)(int *)) {
+ (*takeNonnull)(nullptr); // false-negative
+ (*takeNullable)(nullptr);
+ (*takeUnannotated)(nullptr);
+ }
+ )cc"));
+
+ // function returned from function
+ //
+ // TODO(b/233582219): Fix false negative. Implement support for retrieving
+ // parameter types for functions returned by another function.
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ typedef void (*takeNonnullF)(int *_Nonnull);
+ typedef void (*takeNullableF)(int *_Nullable);
+ typedef void (*takeUnannotatedF)(int *);
+ void target(takeNonnullF (*takeNonnull)(), takeNullableF (*takeNullable)(),
+ takeUnannotatedF (*takeUnannotated)()) {
+ (*takeNonnull)()(nullptr); // false-negative
+ (*takeNullable)()(nullptr);
+ (*takeUnannotated)()(nullptr);
+ }
+ )cc"));
+
+ // passing a reference to a nonnull pointer
+ //
+ // TODO(b/233582219): Fix false negative. When the nonnull pointer is passed
+ // by reference into the callee which takes a nullable parameter, its value
+ // may be changed to null, making it unsafe to dereference when we return from
+ // the function call. Some possible approaches for handling this case:
+ // (1) Disallow passing a nonnull pointer as a nullable reference - and warn
+ // at the function call.
+ // (2) Assume in worst case the nonnull pointer becomes nullable after the
+ // call - and warn at the dereference.
+ // (3) Sacrifice soundness for reduction in noise, and skip the warning.
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ void takeNonnullRef(int *_Nonnull &);
+ void takeNullableRef(int *_Nullable &);
+ void takeUnannotatedRef(int *&);
+ void target(int *_Nonnull ptr_nonnull) {
+ takeNonnullRef(ptr_nonnull);
+ *ptr_nonnull;
+
+ // false-negative
+ takeNullableRef(ptr_nonnull);
+ *ptr_nonnull;
+
+ takeUnannotatedRef(ptr_nonnull);
+ *ptr_nonnull;
+ }
+ )cc"));
+
+ // passing a reference to a nullable pointer
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ void takeNonnullRef(int *_Nonnull &);
+ void takeNullableRef(int *_Nullable &);
+ void takeUnannotatedRef(int *&);
+ void target(int *_Nullable ptr_nullable) {
+ takeNonnullRef(ptr_nullable); // [[unsafe]]
+ *ptr_nullable; // [[unsafe]]
+
+ takeNullableRef(ptr_nullable);
+ *ptr_nullable; // [[unsafe]]
+
+ takeUnannotatedRef(ptr_nullable);
+ *ptr_nullable; // [[unsafe]]
+ }
+ )cc"));
+
+ // passing a reference to an unannotated pointer
+ //
+ // TODO(b/233582219): Fix false negative. The unannotated pointer should be
+ // considered nullable if it has been used as a nullable pointer.
+ EXPECT_TRUE(checkDiagnostics(R"cc(
+ void takeNonnullRef(int *_Nonnull &);
+ void takeNullableRef(int *_Nullable &);
+ void takeUnannotatedRef(int *&);
+ void target(int *ptr_unannotated) {
+ takeNonnullRef(ptr_unannotated);
+ *ptr_unannotated;
+
+ takeNullableRef(ptr_unannotated);
+ *ptr_unannotated; // false-negative
+
+ takeUnannotatedRef(ptr_unannotated);
+ *ptr_unannotated;
+ }
+ )cc"));
+}
+
} // namespace
} // namespace nullability
} // namespace tidy