[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