[WebKit checkers] Treat NULL, 0, and nil like nullptr (#157700)

This PR makes WebKit checkers treat NULL, 0, and nil like nullptr in
various places.

GitOrigin-RevId: db74eae1dc92719fe91e0101d8255427933a61d5
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index 0d2294e..9a7f5b7 100644
--- a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -217,6 +217,16 @@
   return isa<CXXThisExpr>(E);
 }
 
+bool isNullPtr(const clang::Expr *E) {
+  if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E))
+    return true;
+  if (auto *Int = dyn_cast_or_null<IntegerLiteral>(E)) {
+    if (Int->getValue().isZero())
+      return true;
+  }
+  return false;
+}
+
 bool isConstOwnerPtrMemberExpr(const clang::Expr *E) {
   if (auto *MCE = dyn_cast<CXXMemberCallExpr>(E)) {
     if (auto *Callee = MCE->getDirectCallee()) {
@@ -275,7 +285,7 @@
   bool VisitReturnStmt(const ReturnStmt *RS) {
     if (auto *RV = RS->getRetValue()) {
       RV = RV->IgnoreParenCasts();
-      if (isa<CXXNullPtrLiteralExpr>(RV))
+      if (isNullPtr(RV))
         return true;
       return isConstOwnerPtrMemberExpr(RV);
     }
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h
index 8302bbe..3a009d6 100644
--- a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h
+++ b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h
@@ -66,6 +66,9 @@
 /// \returns Whether \p E is a safe call arugment.
 bool isASafeCallArg(const clang::Expr *E);
 
+/// \returns true if E is nullptr or __null.
+bool isNullPtr(const clang::Expr *E);
+
 /// \returns true if E is a MemberExpr accessing a const smart pointer type.
 bool isConstOwnerPtrMemberExpr(const clang::Expr *E);
 
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp
index ec0c2c1..9deb184 100644
--- a/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp
@@ -272,7 +272,7 @@
           ArgExpr = ArgExpr->IgnoreParenCasts();
       }
     }
-    if (isa<CXXNullPtrLiteralExpr>(ArgExpr) || isa<IntegerLiteral>(ArgExpr) ||
+    if (isNullPtr(ArgExpr) || isa<IntegerLiteral>(ArgExpr) ||
         isa<CXXDefaultArgExpr>(ArgExpr))
       return;
     if (auto *DRE = dyn_cast<DeclRefExpr>(ArgExpr)) {
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
index 764e2c6..e80f174 100644
--- a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
@@ -217,13 +217,11 @@
         [&](const clang::Expr *ArgOrigin, bool IsSafe) {
           if (IsSafe)
             return true;
-          if (isa<CXXNullPtrLiteralExpr>(ArgOrigin)) {
-            // foo(nullptr)
+          if (isNullPtr(ArgOrigin))
             return true;
-          }
           if (isa<IntegerLiteral>(ArgOrigin)) {
             // FIXME: Check the value.
-            // foo(NULL)
+            // foo(123)
             return true;
           }
           if (isa<ObjCStringLiteral>(ArgOrigin))
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
index 7cd86a6..f4f6e28 100644
--- a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
@@ -295,7 +295,7 @@
                 if (isa<CXXThisExpr>(InitArgOrigin))
                   return true;
 
-                if (isa<CXXNullPtrLiteralExpr>(InitArgOrigin))
+                if (isNullPtr(InitArgOrigin))
                   return true;
 
                 if (isa<IntegerLiteral>(InitArgOrigin))
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
index d74fec2..5c1b2d7 100644
--- a/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -177,7 +177,8 @@
       CreateOrCopyFnCall.insert(Arg); // Avoid double reporting.
       return;
     }
-    if (Result == IsOwnedResult::Owned || Result == IsOwnedResult::Skip) {
+    if (Result == IsOwnedResult::Owned || Result == IsOwnedResult::Skip ||
+        isNullPtr(Arg)) {
       CreateOrCopyFnCall.insert(Arg);
       return;
     }
@@ -486,7 +487,7 @@
           continue;
         }
       }
-      if (isa<CXXNullPtrLiteralExpr>(E))
+      if (isNullPtr(E))
         return IsOwnedResult::NotOwned;
       if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
         auto QT = DRE->getType();
diff --git a/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp b/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp
index f709560..7959daf 100644
--- a/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp
+++ b/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp
@@ -71,12 +71,21 @@
     return m_obj5.get();
   }
 
+  CheckedObj* ensureObj6() {
+    if (!m_obj6)
+      const_cast<std::unique_ptr<CheckedObj>&>(m_obj6) = new CheckedObj;
+    if (m_obj6->next())
+      return (CheckedObj *)0;
+    return m_obj6.get();
+  }
+
 private:
   const std::unique_ptr<CheckedObj> m_obj1;
   std::unique_ptr<CheckedObj> m_obj2;
   const std::unique_ptr<CheckedObj> m_obj3;
   const std::unique_ptr<CheckedObj> m_obj4;
   const std::unique_ptr<CheckedObj> m_obj5;
+  const std::unique_ptr<CheckedObj> m_obj6;
 };
 
 void Foo::bar() {
@@ -87,6 +96,7 @@
   badEnsureObj4().method();
   // expected-warning@-1{{Call argument for 'this' parameter is unchecked and unsafe}}
   ensureObj5()->method();
+  ensureObj6()->method();
 }
 
 } // namespace call_args_const_unique_ptr
diff --git a/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm b/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
index 83c87b1..7699017 100644
--- a/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
+++ b/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
@@ -13,6 +13,8 @@
   auto ns4 = adoptNS([ns3 mutableCopy]);
   auto ns5 = adoptNS([ns3 copyWithValue:3]);
   auto ns6 = retainPtr([ns3 next]);
+  auto ns7 = retainPtr((SomeObj *)0);
+  auto ns8 = adoptNS(nil);
   CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10));
   auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault));
   auto cf3 = adoptCF(checked_cf_cast<CFArrayRef>(CFCopyArray(cf1)));
@@ -111,6 +113,10 @@
   return adoptCF(rawBuffer);
 }
 
+RetainPtr<SomeObj> return_nil() {
+  return nil;
+}
+
 RetainPtr<SomeObj> return_nullptr() {
   return nullptr;
 }
diff --git a/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp b/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
index 0540ed9..3364637 100644
--- a/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
+++ b/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
@@ -121,6 +121,7 @@
     RefCountable *bar = foo->trivial() ? foo.get() : nullptr;
     // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
     foo = nullptr;
+    foo = (RefCountable *)0;
     bar->method();
   }
 }
diff --git a/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/test/Analysis/Checkers/WebKit/unretained-call-args.mm
index c69113c..3feecd9 100644
--- a/test/Analysis/Checkers/WebKit/unretained-call-args.mm
+++ b/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -456,6 +456,8 @@
   // expected-warning@-1{{Call argument is unretained and unsafe}}
   // expected-warning@-2{{Call argument is unretained and unsafe}}
   [self doWork:@"hello", RetainPtr<SomeObj> { provide() }.get(), RetainPtr<CFMutableArrayRef> { provide_cf() }.get()];
+  [self doWork:__null];
+  [self doWork:nil];
 }
 
 - (SomeObj *)getSomeObj {