diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 478bd85177143..f62a868ccd2cd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -215,6 +215,16 @@ bool isASafeCallArg(const Expr *E) { return isa(E); } +bool isNullPtr(const clang::Expr *E) { + if (isa(E) || isa(E)) + return true; + if (auto *Int = dyn_cast_or_null(E)) { + if (Int->getValue().isZero()) + return true; + } + return false; +} + bool isConstOwnerPtrMemberExpr(const clang::Expr *E) { if (auto *MCE = dyn_cast(E)) { if (auto *Callee = MCE->getDirectCallee()) { @@ -273,7 +283,7 @@ class EnsureFunctionVisitor bool VisitReturnStmt(const ReturnStmt *RS) { if (auto *RV = RS->getRetValue()) { RV = RV->IgnoreParenCasts(); - if (isa(RV)) + if (isNullPtr(RV)) return true; return isConstOwnerPtrMemberExpr(RV); } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h index 8302bbe3084c2..3a009d65efea6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h @@ -66,6 +66,9 @@ bool tryToFindPtrOrigin( /// \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/clang/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp index ec0c2c117fb29..9deb1845a2f1a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp @@ -272,7 +272,7 @@ class ForwardDeclChecker : public Checker> { ArgExpr = ArgExpr->IgnoreParenCasts(); } } - if (isa(ArgExpr) || isa(ArgExpr) || + if (isNullPtr(ArgExpr) || isa(ArgExpr) || isa(ArgExpr)) return; if (auto *DRE = dyn_cast(ArgExpr)) { diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp index 764e2c640feb8..e80f1749d595b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp @@ -217,13 +217,11 @@ class RawPtrRefCallArgsChecker [&](const clang::Expr *ArgOrigin, bool IsSafe) { if (IsSafe) return true; - if (isa(ArgOrigin)) { - // foo(nullptr) + if (isNullPtr(ArgOrigin)) return true; - } if (isa(ArgOrigin)) { // FIXME: Check the value. - // foo(NULL) + // foo(123) return true; } if (isa(ArgOrigin)) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp index 7cd86a682c0a9..f4f6e28c97ea1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp @@ -295,7 +295,7 @@ class RawPtrRefLocalVarsChecker if (isa(InitArgOrigin)) return true; - if (isa(InitArgOrigin)) + if (isNullPtr(InitArgOrigin)) return true; if (isa(InitArgOrigin)) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp index d74fec2c551d4..5c1b2d7cce45d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp @@ -177,7 +177,8 @@ class RetainPtrCtorAdoptChecker 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 @@ class RetainPtrCtorAdoptChecker continue; } } - if (isa(E)) + if (isNullPtr(E)) return IsOwnedResult::NotOwned; if (auto *DRE = dyn_cast(E)) { auto QT = DRE->getType(); diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp index f7095606c77a4..7959daf0ceaaf 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp @@ -71,12 +71,21 @@ class Foo { return m_obj5.get(); } + CheckedObj* ensureObj6() { + if (!m_obj6) + const_cast&>(m_obj6) = new CheckedObj; + if (m_obj6->next()) + return (CheckedObj *)0; + return m_obj6.get(); + } + private: const std::unique_ptr m_obj1; std::unique_ptr m_obj2; const std::unique_ptr m_obj3; const std::unique_ptr m_obj4; const std::unique_ptr m_obj5; + const std::unique_ptr m_obj6; }; void Foo::bar() { @@ -87,6 +96,7 @@ void Foo::bar() { 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/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm index 83c87b14158b9..769901778cdf0 100644 --- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm +++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm @@ -13,6 +13,8 @@ void basic_correct() { 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(CFCopyArray(cf1))); @@ -111,6 +113,10 @@ - (void)setValue:value { return adoptCF(rawBuffer); } +RetainPtr return_nil() { + return nil; +} + RetainPtr return_nullptr() { return nullptr; } diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp index 0540ed93c5707..3364637369799 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp @@ -121,6 +121,7 @@ void foo8(RefCountable* obj) { 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/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm index c69113c48806d..3feecd930f109 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm @@ -456,6 +456,8 @@ - (void)doWorkOnSelf { // expected-warning@-1{{Call argument is unretained and unsafe}} // expected-warning@-2{{Call argument is unretained and unsafe}} [self doWork:@"hello", RetainPtr { provide() }.get(), RetainPtr { provide_cf() }.get()]; + [self doWork:__null]; + [self doWork:nil]; } - (SomeObj *)getSomeObj {