Implement transfer function for identifying `this` pointer as always non-null.

PiperOrigin-RevId: 454134063
diff --git a/nullability_verification/pointer_nullability_analysis.cc b/nullability_verification/pointer_nullability_analysis.cc
index a512ec4..0745567 100644
--- a/nullability_verification/pointer_nullability_analysis.cc
+++ b/nullability_verification/pointer_nullability_analysis.cc
@@ -44,20 +44,29 @@
 }
 
 void initialisePointerNotNullProperty(
-    const Expr* PointerExpr, TransferState<PointerNullabilityLattice>& State) {
+    const Expr* PointerExpr, TransferState<PointerNullabilityLattice>& State,
+    BoolValue* NotNullProperty = nullptr) {
   if (auto* PointerVal = cast_or_null<PointerValue>(
           State.Env.getValue(*PointerExpr, SkipPast::Reference))) {
     if (!State.Lattice.hasPointerNotNullProperty(PointerVal)) {
-      State.Lattice.setPointerNotNullProperty(PointerVal,
-                                              &State.Env.makeAtomicBoolValue());
+      State.Lattice.setPointerNotNullProperty(
+          PointerVal,
+          NotNullProperty ? NotNullProperty : &State.Env.makeAtomicBoolValue());
     }
   }
 }
 
 void transferInitPointerVariableReference(
-    const Expr* Expr, const MatchFinder::MatchResult&,
+    const Expr* PointerExpr, const MatchFinder::MatchResult&,
     TransferState<PointerNullabilityLattice>& State) {
-  initialisePointerNotNullProperty(Expr, State);
+  initialisePointerNotNullProperty(PointerExpr, State);
+}
+
+void transferInitCXXThisExpr(const Expr* ThisExpr,
+                             const MatchFinder::MatchResult&,
+                             TransferState<PointerNullabilityLattice>& State) {
+  initialisePointerNotNullProperty(ThisExpr, State,
+                                   &State.Env.getBoolLiteralValue(true));
 }
 
 void transferNullPointerLiteral(
@@ -167,6 +176,7 @@
       // Handles initialization of the null states of pointers
       .CaseOf<Expr>(isPointerVariableReference(),
                     transferInitPointerVariableReference)
+      .CaseOf<Expr>(isCXXThisExpr(), transferInitCXXThisExpr)
       // Handles initialization of null states of member pointers and safety of
       // member access (->) on pointers
       .CaseOf<MemberExpr>(isMemberExprInvolvingPointers(),
diff --git a/nullability_verification/pointer_nullability_analysis_test.cc b/nullability_verification/pointer_nullability_analysis_test.cc
index d8c66d4..77f64bf 100644
--- a/nullability_verification/pointer_nullability_analysis_test.cc
+++ b/nullability_verification/pointer_nullability_analysis_test.cc
@@ -486,6 +486,27 @@
       UnorderedElementsAre(Pair("safe", IsSafe()), Pair("unsafe-1", IsUnsafe()),
                            Pair("unsafe-2", IsUnsafe())));
 
+  std::string DerefStructMemberInsideMemberFunction = R"(
+    struct Foo {
+      Foo* ptr;
+      void target() {
+        if (ptr) {
+          *ptr;
+          /*[[safe]]*/
+        } else {
+          *ptr;
+          /*[[unsafe-1]]*/
+        }
+        *ptr;
+        /*[[unsafe-2]]*/
+      }
+    };
+  )";
+  expectDataflow(
+      DerefStructMemberInsideMemberFunction,
+      UnorderedElementsAre(Pair("safe", IsSafe()), Pair("unsafe-1", IsUnsafe()),
+                           Pair("unsafe-2", IsUnsafe())));
+
   std::string DerefClassMember = R"(
     class Foo {
      public:
@@ -531,6 +552,43 @@
       UnorderedElementsAre(Pair("safe", IsSafe()), Pair("unsafe-1", IsUnsafe()),
                            Pair("unsafe-2", IsUnsafe())));
 
+  std::string MemberAccessOnImplicitThis = R"(
+    struct Foo {
+      void foo();
+      void target() {
+        foo();
+        /*[[safe]]*/
+      }
+    };
+  )";
+  expectDataflow(MemberAccessOnImplicitThis,
+                 UnorderedElementsAre(Pair("safe", IsSafe())));
+
+  std::string MemberAccessOnExplicitThis = R"(
+    struct Foo {
+      void foo();
+      void target() {
+        this->foo();
+        /*[[safe]]*/
+      }
+    };
+  )";
+  expectDataflow(MemberAccessOnExplicitThis,
+                 UnorderedElementsAre(Pair("safe", IsSafe())));
+
+  std::string MemberAccessOnCopyOfThis = R"(
+    struct Foo {
+      void foo();
+      void target() {
+        Foo *thisCopy = this;
+        thisCopy->foo();
+        /*[[safe]]*/
+      }
+    };
+  )";
+  expectDataflow(MemberAccessOnCopyOfThis,
+                 UnorderedElementsAre(Pair("safe", IsSafe())));
+
   std::string AccessChainOnlyCheckOnFirst = R"(
     struct Foo {
       Foo* foo;
diff --git a/nullability_verification/pointer_nullability_matchers.cc b/nullability_verification/pointer_nullability_matchers.cc
index c37ce4a..e3b235e 100644
--- a/nullability_verification/pointer_nullability_matchers.cc
+++ b/nullability_verification/pointer_nullability_matchers.cc
@@ -13,6 +13,7 @@
 
 using ast_matchers::anyOf;
 using ast_matchers::binaryOperator;
+using ast_matchers::cxxThisExpr;
 using ast_matchers::declRefExpr;
 using ast_matchers::expr;
 using ast_matchers::hasAnyOperatorName;
@@ -51,6 +52,7 @@
 Matcher<Stmt> isMemberExprInvolvingPointers() {
   return memberExpr(anyOf(isArrow(), hasType(isAnyPointer())));
 }
+Matcher<Stmt> isCXXThisExpr() { return cxxThisExpr(); }
 }  // namespace nullability
 }  // namespace tidy
 }  // namespace clang
diff --git a/nullability_verification/pointer_nullability_matchers.h b/nullability_verification/pointer_nullability_matchers.h
index b4f4a78..23b42b8 100644
--- a/nullability_verification/pointer_nullability_matchers.h
+++ b/nullability_verification/pointer_nullability_matchers.h
@@ -13,6 +13,7 @@
 
 ast_matchers::internal::Matcher<Stmt> isPointerVariableReference();
 ast_matchers::internal::Matcher<Stmt> isMemberExprInvolvingPointers();
+ast_matchers::internal::Matcher<Stmt> isCXXThisExpr();
 ast_matchers::internal::Matcher<Stmt> isNullPointerLiteral();
 ast_matchers::internal::Matcher<Stmt> isAddrOf();
 ast_matchers::internal::Matcher<Stmt> isPointerDereference();