[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/haoNoQ closed https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81400 >From 6f94c583f5201fbd73156969fa410669d6e1be93 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Tue, 13 Feb 2024 20:05:18 -0800 Subject: [PATCH 1/3] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. --- .../WebKit/UncountedCallArgsChecker.cpp | 67 +-- .../Checkers/WebKit/uncounted-obj-arg.cpp | 18 + 2 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index f4e6191cf05a3c..d4bf3e2c2e75db 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,15 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = +isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -94,25 +103,7 @@ class UncountedCallArgsChecker if (auto *defaultArg = dyn_cast(Arg)) Arg = defaultArg->getExpr(); -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); @@ -120,6 +111,28 @@ class UncountedCallArgsChecker } } + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } + bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) return false; @@ -196,6 +209,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager()); +auto Report = std::make_unique(Bug, Os.str(), BSLoc); +Report->addRange(CallArg->getSourceRange()); +BR->emitReport(std::move(Report)); + } }; } // namespace diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp new file mode 100644 index 00..e5e39e3faac714 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s + +#include "mock-types.h" + +class RefCounted { +public: + void ref() const; + void deref() const; + void someFunction(); +}; + +RefCounted* refCountedObj(); + +void test() +{ + refCountedObj()->someFunction(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} >From c15967f8f09198c01aec8b0161cc08484c78f66a Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Tue, 13 Feb 2024 19:36:09 -0800 Subject: [PATCH 2/3] Address the review comment. Namely avoid calling getTypePtrOrNull and don't use raw_svector_ostream. --- .../Checkers/WebKit/UncountedCallArgsChecker.cpp | 9 ++--- 1 file chang
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
rniwa wrote: Rebased. https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81400 >From 6f94c583f5201fbd73156969fa410669d6e1be93 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Tue, 13 Feb 2024 20:05:18 -0800 Subject: [PATCH 1/2] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. --- .../WebKit/UncountedCallArgsChecker.cpp | 67 +-- .../Checkers/WebKit/uncounted-obj-arg.cpp | 18 + 2 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index f4e6191cf05a3c..d4bf3e2c2e75db 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,15 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = +isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -94,25 +103,7 @@ class UncountedCallArgsChecker if (auto *defaultArg = dyn_cast(Arg)) Arg = defaultArg->getExpr(); -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); @@ -120,6 +111,28 @@ class UncountedCallArgsChecker } } + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } + bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) return false; @@ -196,6 +209,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager()); +auto Report = std::make_unique(Bug, Os.str(), BSLoc); +Report->addRange(CallArg->getSourceRange()); +BR->emitReport(std::move(Report)); + } }; } // namespace diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp new file mode 100644 index 00..e5e39e3faac714 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s + +#include "mock-types.h" + +class RefCounted { +public: + void ref() const; + void deref() const; + void someFunction(); +}; + +RefCounted* refCountedObj(); + +void test() +{ + refCountedObj()->someFunction(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} >From c15967f8f09198c01aec8b0161cc08484c78f66a Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Tue, 13 Feb 2024 19:36:09 -0800 Subject: [PATCH 2/2] Address the review comment. Namely avoid calling getTypePtrOrNull and don't use raw_svector_ostream. --- .../Checkers/WebKit/UncountedCallArgsChecker.cpp | 9 ++--- 1 file chang
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/haoNoQ approved this pull request. Great! Needs a rebase now though. https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
@@ -183,6 +196,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; rniwa wrote: Good point. Fixed. https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81400 >From 04e18254efc4f671e0bbd9625c7e994fe47c1636 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Sun, 11 Feb 2024 00:07:30 -0800 Subject: [PATCH 1/2] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. --- .../WebKit/UncountedCallArgsChecker.cpp | 67 +-- .../Checkers/WebKit/uncounted-obj-arg.cpp | 18 + 2 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 31ccae8b097b89..cda96b70ea8735 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,15 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = +isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -91,25 +100,7 @@ class UncountedCallArgsChecker const auto *Arg = CE->getArg(ArgIdx); -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); @@ -117,6 +108,28 @@ class UncountedCallArgsChecker } } + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } + bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) return false; @@ -183,6 +196,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager()); +auto Report = std::make_unique(Bug, Os.str(), BSLoc); +Report->addRange(CallArg->getSourceRange()); +BR->emitReport(std::move(Report)); + } }; } // namespace diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp new file mode 100644 index 00..e5e39e3faac714 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s + +#include "mock-types.h" + +class RefCounted { +public: + void ref() const; + void deref() const; + void someFunction(); +}; + +RefCounted* refCountedObj(); + +void test() +{ + refCountedObj()->someFunction(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} >From 2d780389a46e5c053053c1432d2ec3af2a7653e9 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Tue, 13 Feb 2024 19:36:09 -0800 Subject: [PATCH 2/2] Address the review comment. Namely avoid calling getTypePtrOrNull and don't use raw_svector_ostream. --- .../Checkers/WebKit/UncountedCallArgsChecker.cpp | 9 ++--- 1 file changed, 2 insertions(+), 7 deletions(-) d
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
@@ -70,6 +70,15 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); rniwa wrote: Ah, okay. Will do that. https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
@@ -183,6 +196,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; haoNoQ wrote: This is a constant string, no need to stream it, just put it straight into the `BugReport` constructor. https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
@@ -70,6 +70,15 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); haoNoQ wrote: ```suggestion QualType ArgType = MemberCallExpr->getObjectType(); ``` `getTypePtrOrNull()` is typically redundant; `QualType` provides an overloaded `operator ->()` that allows you to call methods on the underlying unqualified `Type` directly. https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81400 >From 04e18254efc4f671e0bbd9625c7e994fe47c1636 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Sun, 11 Feb 2024 00:07:30 -0800 Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. --- .../WebKit/UncountedCallArgsChecker.cpp | 67 +-- .../Checkers/WebKit/uncounted-obj-arg.cpp | 18 + 2 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 31ccae8b097b89..cda96b70ea8735 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,15 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = +isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -91,25 +100,7 @@ class UncountedCallArgsChecker const auto *Arg = CE->getArg(ArgIdx); -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); @@ -117,6 +108,28 @@ class UncountedCallArgsChecker } } + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } + bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) return false; @@ -183,6 +196,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager()); +auto Report = std::make_unique(Bug, Os.str(), BSLoc); +Report->addRange(CallArg->getSourceRange()); +BR->emitReport(std::move(Report)); + } }; } // namespace diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp new file mode 100644 index 00..e5e39e3faac714 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s + +#include "mock-types.h" + +class RefCounted { +public: + void ref() const; + void deref() const; + void someFunction(); +}; + +RefCounted* refCountedObj(); + +void test() +{ + refCountedObj()->someFunction(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81400 >From c8ac9ad6ecd95a3dbd023458a572b08a4664de03 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Sun, 11 Feb 2024 00:07:30 -0800 Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. It also removes the exemption of local variables from this checker so that each local variable's safety is checked if it's used in a function call instead of relying on the local variable checker to find those since local variable checker currently has exemption for "for" and "if" statements. --- .../Checkers/WebKit/ASTUtils.cpp | 2 +- .../WebKit/UncountedCallArgsChecker.cpp | 67 +-- .../WebKit/call-args-inside-if-statement.cpp | 20 ++ 3 files changed, 69 insertions(+), 20 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 4526fac64735bf..da0d52e361c946 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -85,7 +85,7 @@ bool isASafeCallArg(const Expr *E) { assert(E); if (auto *Ref = dyn_cast(E)) { if (auto *D = dyn_cast_or_null(Ref->getFoundDecl())) { - if (isa(D) || D->isLocalVarDecl()) + if (isa(D)) return true; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 31ccae8b097b89..cda96b70ea8735 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,15 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = +isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -91,25 +100,7 @@ class UncountedCallArgsChecker const auto *Arg = CE->getArg(ArgIdx); -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); @@ -117,6 +108,28 @@ class UncountedCallArgsChecker } } + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } + bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) return false; @@ -183,6 +196,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager()); +auto Report = std::make_unique(Bug, Os.str(), BSLoc); +Report->addRange(CallArg->getSourceRange()); +BR->emitReport(std::move(Report)); + } }; } // namespace diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp new fi
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81400 >From 16d5c240639cdf25b824f5a1a60c256d33fe3565 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Sun, 11 Feb 2024 00:07:30 -0800 Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. It also removes the exemption of local variables from this checker so that each local variable's safety is checked if it's used in a function call instead of relying on the local variable checker to find those since local variable checker currently has exemption for "for" and "if" statements. --- .../Checkers/WebKit/ASTUtils.cpp | 2 +- .../WebKit/UncountedCallArgsChecker.cpp | 66 +-- .../WebKit/call-args-inside-if-statement.cpp | 20 ++ 3 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 4526fac64735bf..da0d52e361c946 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -85,7 +85,7 @@ bool isASafeCallArg(const Expr *E) { assert(E); if (auto *Ref = dyn_cast(E)) { if (auto *D = dyn_cast_or_null(Ref->getFoundDecl())) { - if (isa(D) || D->isLocalVarDecl()) + if (isa(D)) return true; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 31ccae8b097b89..170ff7f531f9e9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,14 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto *MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -91,25 +99,7 @@ class UncountedCallArgsChecker const auto *Arg = CE->getArg(ArgIdx); -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); @@ -117,6 +107,28 @@ class UncountedCallArgsChecker } } + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } + bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) return false; @@ -183,6 +195,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager()); +auto Report = std::make_unique(Bug, Os.str(), BSLoc); +Report->addRange(CallArg->getSourceRange()); +BR->emitReport(std::move(Report)); + } }; } // namespace diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp new file mode 10064
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 8ea7f1d20ad8ab8c381800eefda948d85c6860cc b7121ce4f2ef69b4a410f2399fbd9d9525156b93 -- clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index fa6aeb4741..cda96b70ea 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,10 +70,11 @@ public: // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); - if (auto* MemberCallExpr = dyn_cast(CE)) { + if (auto *MemberCallExpr = dyn_cast(CE)) { auto *E = MemberCallExpr->getImplicitObjectArgument(); auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); -std::optional IsUncounted = isUncounted(ArgType->getAsCXXRecordDecl()); +std::optional IsUncounted = +isUncounted(ArgType->getAsCXXRecordDecl()); if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) reportBugOnThis(E); } @@ -98,7 +99,7 @@ public: continue; const auto *Arg = CE->getArg(ArgIdx); - + if (isPtrOriginSafe(Arg)) continue; @@ -106,7 +107,7 @@ public: } } } - + bool isPtrOriginSafe(const Expr *Arg) const { std::pair ArgOrigin = tryToFindPtrOrigin(Arg, true); `` https://github.com/llvm/llvm-project/pull/81400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
llvmbot wrote: @llvm/pr-subscribers-clang-static-analyzer-1 @llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) Changes This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. It also removes the exemption of local variables from this checker so that each local variable's safety is checked if it's used in a function call instead of relying on the local variable checker to find those since local variable checker currently has exemption for "for" and "if" statements. --- Full diff: https://github.com/llvm/llvm-project/pull/81400.diff 3 Files Affected: - (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp (+1-1) - (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp (+48-20) - (added) clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp (+20) ``diff diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 4526fac64735bf..da0d52e361c946 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -85,7 +85,7 @@ bool isASafeCallArg(const Expr *E) { assert(E); if (auto *Ref = dyn_cast(E)) { if (auto *D = dyn_cast_or_null(Ref->getFoundDecl())) { - if (isa(D) || D->isLocalVarDecl()) + if (isa(D)) return true; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 31ccae8b097b89..fa6aeb4741d0b7 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,14 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto* MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -90,32 +98,36 @@ class UncountedCallArgsChecker continue; const auto *Arg = CE->getArg(ArgIdx); - -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) + +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); } } } + + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) @@ -183,6 +195,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager()); +auto Report = std::make_unique(Bug, Os.str(), BSLoc); +Report->addRange(CallArg->getSourceRange()); +BR->emitReport(std::move(Report)); + } }; } // namespace diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp new file mode 100644 index 00..6f7c959b2fccca --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit
[clang] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. (PR #81400)
https://github.com/rniwa created https://github.com/llvm/llvm-project/pull/81400 This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. It also removes the exemption of local variables from this checker so that each local variable's safety is checked if it's used in a function call instead of relying on the local variable checker to find those since local variable checker currently has exemption for "for" and "if" statements. >From b7121ce4f2ef69b4a410f2399fbd9d9525156b93 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Sun, 11 Feb 2024 00:07:30 -0800 Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Check the safety of the object argument in a member function call. This PR makes alpha.webkit.UncountedCallArgsChecker eplicitly check the safety of the object argument in a member function call. It also removes the exemption of local variables from this checker so that each local variable's safety is checked if it's used in a function call instead of relying on the local variable checker to find those since local variable checker currently has exemption for "for" and "if" statements. --- .../Checkers/WebKit/ASTUtils.cpp | 2 +- .../WebKit/UncountedCallArgsChecker.cpp | 68 +-- .../WebKit/call-args-inside-if-statement.cpp | 20 ++ 3 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/call-args-inside-if-statement.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 4526fac64735bf..da0d52e361c946 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -85,7 +85,7 @@ bool isASafeCallArg(const Expr *E) { assert(E); if (auto *Ref = dyn_cast(E)) { if (auto *D = dyn_cast_or_null(Ref->getFoundDecl())) { - if (isa(D) || D->isLocalVarDecl()) + if (isa(D)) return true; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 31ccae8b097b89..fa6aeb4741d0b7 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -70,6 +70,14 @@ class UncountedCallArgsChecker // or std::function call operator). unsigned ArgIdx = isa(CE) && isa_and_nonnull(F); + if (auto* MemberCallExpr = dyn_cast(CE)) { +auto *E = MemberCallExpr->getImplicitObjectArgument(); +auto *ArgType = MemberCallExpr->getObjectType().getTypePtrOrNull(); +std::optional IsUncounted = isUncounted(ArgType->getAsCXXRecordDecl()); +if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E)) + reportBugOnThis(E); + } + for (auto P = F->param_begin(); // FIXME: Also check variadic function parameters. // FIXME: Also check default function arguments. Probably a different @@ -90,32 +98,36 @@ class UncountedCallArgsChecker continue; const auto *Arg = CE->getArg(ArgIdx); - -std::pair ArgOrigin = -tryToFindPtrOrigin(Arg, true); - -// Temporary ref-counted object created as part of the call argument -// would outlive the call. -if (ArgOrigin.second) - continue; - -if (isa(ArgOrigin.first)) { - // foo(nullptr) - continue; -} -if (isa(ArgOrigin.first)) { - // FIXME: Check the value. - // foo(NULL) - continue; -} - -if (isASafeCallArg(ArgOrigin.first)) + +if (isPtrOriginSafe(Arg)) continue; reportBug(Arg, *P); } } } + + bool isPtrOriginSafe(const Expr *Arg) const { +std::pair ArgOrigin = +tryToFindPtrOrigin(Arg, true); + +// Temporary ref-counted object created as part of the call argument +// would outlive the call. +if (ArgOrigin.second) + return true; + +if (isa(ArgOrigin.first)) { + // foo(nullptr) + return true; +} +if (isa(ArgOrigin.first)) { + // FIXME: Check the value. + // foo(NULL) + return true; +} + +return isASafeCallArg(ArgOrigin.first); + } bool shouldSkipCall(const CallExpr *CE) const { if (CE->getNumArgs() == 0) @@ -183,6 +195,22 @@ class UncountedCallArgsChecker Report->addRange(CallArg->getSourceRange()); BR->emitReport(std::move(Report)); } + + void reportBugOnThis(const Expr *CallArg) const { +assert(CallArg); + +SmallString<100> Buf; +llvm::raw_svector_ostream Os(Buf); + +Os << "Call argument for 'this' parameter is uncounted and unsafe."; + +const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin(); + +PathDiagnosticLocation