[clang] [llvm] Introduce a new WebKit checker for a unchecked call arguments (#113708) (PR #114522)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 1 01:56:18 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Ryosuke Niwa (rniwa)
<details>
<summary>Changes</summary>
This PR introduces alpha.webkit.UncheckedCallArgsChecker which detects a function argument which is a raw reference or a raw pointer to a CheckedPtr capable object.
---
Patch is 20.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/114522.diff
8 Files Affected:
- (modified) clang/include/clang/StaticAnalyzer/Checkers/Checkers.td (+4)
- (modified) clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt (+1-1)
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp (+11-1)
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h (+8)
- (renamed) clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp (+64-14)
- (added) clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp (+367)
- (added) clang/test/Analysis/Checkers/WebKit/call-args-checked-return-value.cpp (+25)
- (modified) llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn (+1-1)
``````````diff
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 86d62b58cac0fb..bc172c7d2fe348 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1760,6 +1760,10 @@ def UncountedCallArgsChecker : Checker<"UncountedCallArgsChecker">,
HelpText<"Check uncounted call arguments.">,
Documentation<HasDocumentation>;
+def UncheckedCallArgsChecker : Checker<"UncheckedCallArgsChecker">,
+ HelpText<"Check unchecked call arguments.">,
+ Documentation<NotDocumented>;
+
def UncountedLocalVarsChecker : Checker<"UncountedLocalVarsChecker">,
HelpText<"Check uncounted local variables.">,
Documentation<HasDocumentation>;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index c6e5afdc42424c..f40318f46dea1a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -134,7 +134,7 @@ add_clang_library(clangStaticAnalyzerCheckers
WebKit/ASTUtils.cpp
WebKit/PtrTypesSemantics.cpp
WebKit/RefCntblBaseVirtualDtorChecker.cpp
- WebKit/UncountedCallArgsChecker.cpp
+ WebKit/RawPtrRefCallArgsChecker.cpp
WebKit/UncountedLambdaCapturesChecker.cpp
WebKit/RawPtrRefLocalVarsChecker.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 46819d5ca12058..2c80bd86375431 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -173,6 +173,16 @@ std::optional<bool> isUncounted(const QualType T) {
return isUncounted(T->getAsCXXRecordDecl());
}
+std::optional<bool> isUnchecked(const QualType T) {
+ if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
+ if (auto *Decl = Subst->getAssociatedDecl()) {
+ if (isCheckedPtr(safeGetName(Decl)))
+ return false;
+ }
+ }
+ return isUnchecked(T->getAsCXXRecordDecl());
+}
+
std::optional<bool> isUncounted(const CXXRecordDecl* Class)
{
// Keep isRefCounted first as it's cheaper.
@@ -187,7 +197,7 @@ std::optional<bool> isUncounted(const CXXRecordDecl* Class)
}
std::optional<bool> isUnchecked(const CXXRecordDecl *Class) {
- if (isCheckedPtr(Class))
+ if (!Class || isCheckedPtr(Class))
return false; // Cheaper than below
return isCheckedPtrCapable(Class);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index 30bdaed706bb53..54c4872ad57d8c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -55,10 +55,18 @@ bool isCheckedPtr(const clang::CXXRecordDecl *Class);
/// not, std::nullopt if inconclusive.
std::optional<bool> isUncounted(const clang::QualType T);
+/// \returns true if \p Class is CheckedPtr capable AND not checked, false if
+/// not, std::nullopt if inconclusive.
+std::optional<bool> isUnchecked(const clang::QualType T);
+
/// \returns true if \p Class is ref-countable AND not ref-counted, false if
/// not, std::nullopt if inconclusive.
std::optional<bool> isUncounted(const clang::CXXRecordDecl* Class);
+/// \returns true if \p Class is CheckedPtr capable AND not checked, false if
+/// not, std::nullopt if inconclusive.
+std::optional<bool> isUnchecked(const clang::CXXRecordDecl* Class);
+
/// \returns true if \p T is either a raw pointer or reference to an uncounted
/// class, false if not, std::nullopt if inconclusive.
std::optional<bool> isUncountedPtr(const clang::QualType T);
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
similarity index 82%
rename from clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
rename to clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
index 1a5a7309a54f16..f1fbe61c421f88 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
@@ -1,4 +1,4 @@
-//=======- UncountedCallArgsChecker.cpp --------------------------*- C++ -*-==//
+//=======- RawPtrRefCallArgsChecker.cpp --------------------------*- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -27,16 +27,20 @@ using namespace ento;
namespace {
-class UncountedCallArgsChecker
+class RawPtrRefCallArgsChecker
: public Checker<check::ASTDecl<TranslationUnitDecl>> {
- BugType Bug{this,
- "Uncounted call argument for a raw pointer/reference parameter",
- "WebKit coding guidelines"};
+ BugType Bug;
mutable BugReporter *BR;
TrivialFunctionAnalysis TFA;
public:
+ RawPtrRefCallArgsChecker(const char* description)
+ : Bug(this, description, "WebKit coding guidelines") {}
+
+ virtual std::optional<bool> isUnsafeType(QualType) const = 0;
+ virtual std::optional<bool> isUnsafePtr(QualType) const = 0;
+ virtual const char *ptrKind() const = 0;
void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
BugReporter &BRArg) const {
@@ -48,10 +52,10 @@ class UncountedCallArgsChecker
struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
using Base = RecursiveASTVisitor<LocalVisitor>;
- const UncountedCallArgsChecker *Checker;
+ const RawPtrRefCallArgsChecker *Checker;
Decl *DeclWithIssue{nullptr};
- explicit LocalVisitor(const UncountedCallArgsChecker *Checker)
+ explicit LocalVisitor(const RawPtrRefCallArgsChecker *Checker)
: Checker(Checker) {
assert(Checker);
}
@@ -101,8 +105,8 @@ class UncountedCallArgsChecker
}
auto *E = MemberCallExpr->getImplicitObjectArgument();
QualType ArgType = MemberCallExpr->getObjectType().getCanonicalType();
- std::optional<bool> IsUncounted = isUncounted(ArgType);
- if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E))
+ std::optional<bool> IsUnsafe = isUnsafeType(ArgType);
+ if (IsUnsafe && *IsUnsafe && !isPtrOriginSafe(E))
reportBugOnThis(E, D);
}
@@ -118,7 +122,7 @@ class UncountedCallArgsChecker
QualType ArgType = (*P)->getType().getCanonicalType();
// FIXME: more complex types (arrays, references to raw pointers, etc)
- std::optional<bool> IsUncounted = isUncountedPtr(ArgType);
+ std::optional<bool> IsUncounted = isUnsafePtr(ArgType);
if (!IsUncounted || !(*IsUncounted))
continue;
@@ -264,7 +268,7 @@ class UncountedCallArgsChecker
Os << " for parameter ";
printQuotedQualifiedName(Os, Param);
}
- Os << " is uncounted and unsafe.";
+ Os << " is " << ptrKind() << " and unsafe.";
const SourceLocation SrcLocToReport =
isa<CXXDefaultArgExpr>(CallArg) ? Param->getDefaultArg()->getExprLoc()
@@ -282,15 +286,53 @@ class UncountedCallArgsChecker
const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin();
+ SmallString<100> Buf;
+ llvm::raw_svector_ostream Os(Buf);
+ Os << "Call argument for 'this' parameter is " << ptrKind();
+ Os << " and unsafe.";
+
PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
- auto Report = std::make_unique<BasicBugReport>(
- Bug, "Call argument for 'this' parameter is uncounted and unsafe.",
- BSLoc);
+ auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
Report->addRange(CallArg->getSourceRange());
Report->setDeclWithIssue(DeclWithIssue);
BR->emitReport(std::move(Report));
}
};
+
+class UncountedCallArgsChecker final : public RawPtrRefCallArgsChecker {
+public:
+ UncountedCallArgsChecker()
+ : RawPtrRefCallArgsChecker("Uncounted call argument for a raw "
+ "pointer/reference parameter") {}
+
+ std::optional<bool> isUnsafeType(QualType QT) const final {
+ return isUncounted(QT);
+ }
+
+ std::optional<bool> isUnsafePtr(QualType QT) const final {
+ return isUncountedPtr(QT);
+ }
+
+ const char *ptrKind() const final { return "uncounted"; }
+};
+
+class UncheckedCallArgsChecker final : public RawPtrRefCallArgsChecker {
+public:
+ UncheckedCallArgsChecker()
+ : RawPtrRefCallArgsChecker("Unchecked call argument for a raw "
+ "pointer/reference parameter") {}
+
+ std::optional<bool> isUnsafeType(QualType QT) const final {
+ return isUnchecked(QT);
+ }
+
+ std::optional<bool> isUnsafePtr(QualType QT) const final {
+ return isUncheckedPtr(QT);
+ }
+
+ const char *ptrKind() const final { return "unchecked"; }
+};
+
} // namespace
void ento::registerUncountedCallArgsChecker(CheckerManager &Mgr) {
@@ -300,3 +342,11 @@ void ento::registerUncountedCallArgsChecker(CheckerManager &Mgr) {
bool ento::shouldRegisterUncountedCallArgsChecker(const CheckerManager &) {
return true;
}
+
+void ento::registerUncheckedCallArgsChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<UncheckedCallArgsChecker>();
+}
+
+bool ento::shouldRegisterUncheckedCallArgsChecker(const CheckerManager &) {
+ return true;
+}
diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp
new file mode 100644
index 00000000000000..34ff0c70e230ea
--- /dev/null
+++ b/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp
@@ -0,0 +1,367 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedCallArgsChecker -verify %s
+
+#include "mock-types.h"
+
+CheckedObj* provide();
+void consume_refcntbl(CheckedObj*);
+void some_function();
+
+namespace simple {
+ void foo() {
+ consume_refcntbl(provide());
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+ }
+
+ // Test that the checker works with [[clang::suppress]].
+ void foo_suppressed() {
+ [[clang::suppress]]
+ consume_refcntbl(provide()); // no-warning
+ }
+}
+
+namespace multi_arg {
+ void consume_refcntbl(int, CheckedObj* foo, bool);
+ void foo() {
+ consume_refcntbl(42, provide(), true);
+ // expected-warning at -1{{Call argument for parameter 'foo' is unchecked and unsafe}}
+ }
+}
+
+namespace ref_counted {
+ CheckedRef<CheckedObj> provide_ref_counted() { return CheckedRef<CheckedObj>{}; }
+ void consume_ref_counted(CheckedRef<CheckedObj>) {}
+
+ void foo() {
+ consume_refcntbl(provide_ref_counted().ptr());
+ // no warning
+ }
+}
+
+namespace methods {
+ struct Consumer {
+ void consume_ptr(CheckedObj* ptr);
+ void consume_ref(const CheckedObj& ref);
+ };
+
+ void foo() {
+ Consumer c;
+
+ c.consume_ptr(provide());
+ // expected-warning at -1{{Call argument for parameter 'ptr' is unchecked and unsafe}}
+ c.consume_ref(*provide());
+ // expected-warning at -1{{Call argument for parameter 'ref' is unchecked and unsafe}}
+ }
+
+ void foo2() {
+ struct Consumer {
+ void consume(CheckedObj*) { some_function(); }
+ void whatever() {
+ consume(provide());
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+ }
+ };
+ }
+
+ void foo3() {
+ struct Consumer {
+ void consume(CheckedObj*) { some_function(); }
+ void whatever() {
+ this->consume(provide());
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+ }
+ };
+ }
+}
+
+namespace casts {
+ CheckedObj* downcast(CheckedObj*);
+
+ void foo() {
+ consume_refcntbl(provide());
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+
+ consume_refcntbl(static_cast<CheckedObj*>(provide()));
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+
+ consume_refcntbl(dynamic_cast<CheckedObj*>(provide()));
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+
+ consume_refcntbl(const_cast<CheckedObj*>(provide()));
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+
+ consume_refcntbl(reinterpret_cast<CheckedObj*>(provide()));
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+
+ consume_refcntbl(downcast(provide()));
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+
+ consume_refcntbl(
+ static_cast<CheckedObj*>(
+ downcast(
+ static_cast<CheckedObj*>(
+ provide()
+ )
+ )
+ )
+ );
+ // expected-warning at -8{{Call argument is unchecked and unsafe}}
+ }
+}
+
+namespace null_ptr {
+ void foo_ref() {
+ consume_refcntbl(nullptr);
+ consume_refcntbl(0);
+ }
+}
+
+namespace ref_counted_lookalike {
+ struct Decoy {
+ CheckedObj* get() { return nullptr; }
+ };
+
+ void foo() {
+ Decoy D;
+
+ consume_refcntbl(D.get());
+ // expected-warning at -1{{Call argument is unchecked and unsafe}}
+ }
+}
+
+namespace Ref_to_reference_conversion_operator {
+ template<typename T> struct Ref {
+ Ref() = default;
+ Ref(T*) { }
+ T* get() { return nullptr; }
+ operator T& () { return t; }
+ T t;
+ };
+
+ void consume_ref(CheckedObj&) {}
+
+ void foo() {
+ CheckedRef<CheckedObj> bar;
+ consume_ref(bar);
+ }
+}
+
+namespace param_formarding_function {
+ void consume_ref_countable_ref(CheckedObj&);
+ void consume_ref_countable_ptr(CheckedObj*);
+
+ namespace ptr {
+ void foo(CheckedObj* param) {
+ consume_ref_countable_ptr(param);
+ }
+ }
+
+ namespace ref {
+ void foo(CheckedObj& param) {
+ consume_ref_countable_ref(param);
+ }
+ }
+
+ namespace ref_deref_operators {
+ void foo_ref(CheckedObj& param) {
+ consume_ref_countable_ptr(¶m);
+ }
+
+ void foo_ptr(CheckedObj* param) {
+ consume_ref_countable_ref(*param);
+ }
+ }
+
+ namespace casts {
+
+ CheckedObj* downcast(CheckedObj*) { return nullptr; }
+
+ template<class T>
+ T* bitwise_cast(T*) { return nullptr; }
+
+ void foo(CheckedObj* param) {
+ consume_ref_countable_ptr(downcast(param));
+ consume_ref_countable_ptr(bitwise_cast(param));
+ }
+ }
+}
+
+namespace param_formarding_lambda {
+ auto consume_ref_countable_ref = [](CheckedObj&) { some_function(); };
+ auto consume_ref_countable_ptr = [](CheckedObj*) { some_function(); };
+
+ namespace ptr {
+ void foo(CheckedObj* param) {
+ consume_ref_countable_ptr(param);
+ }
+ }
+
+ namespace ref {
+ void foo(CheckedObj& param) {
+ consume_ref_countable_ref(param);
+ }
+ }
+
+ namespace ref_deref_operators {
+ void foo_ref(CheckedObj& param) {
+ consume_ref_countable_ptr(¶m);
+ }
+
+ void foo_ptr(CheckedObj* param) {
+ consume_ref_countable_ref(*param);
+ }
+ }
+
+ namespace casts {
+
+ CheckedObj* downcast(CheckedObj*) { return nullptr; }
+
+ template<class T>
+ T* bitwise_cast(T*) { return nullptr; }
+
+ void foo(CheckedObj* param) {
+ consume_ref_countable_ptr(downcast(param));
+ consume_ref_countable_ptr(bitwise_cast(param));
+ }
+ }
+}
+
+namespace param_forwarding_method {
+ struct methodclass {
+ void consume_ref_countable_ref(CheckedObj&) {};
+ static void consume_ref_countable_ptr(CheckedObj*) {};
+ };
+
+ namespace ptr {
+ void foo(CheckedObj* param) {
+ methodclass::consume_ref_countable_ptr(param);
+ }
+ }
+
+ namespace ref {
+ void foo(CheckedObj& param) {
+ methodclass mc;
+ mc.consume_ref_countable_ref(param);
+ }
+ }
+
+ namespace ref_deref_operators {
+ void foo_ref(CheckedObj& param) {
+ methodclass::consume_ref_countable_ptr(¶m);
+ }
+
+ void foo_ptr(CheckedObj* param) {
+ methodclass mc;
+ mc.consume_ref_countable_ref(*param);
+ }
+ }
+
+ namespace casts {
+
+ CheckedObj* downcast(CheckedObj*) { return nullptr; }
+
+ template<class T>
+ T* bitwise_cast(T*) { return nullptr; }
+
+ void foo(CheckedObj* param) {
+ methodclass::consume_ref_countable_ptr(downcast(param));
+ methodclass::consume_ref_countable_ptr(bitwise_cast(param));
+ }
+ }
+}
+
+namespace downcast {
+ void consume_ref_countable(CheckedObj*) {}
+ CheckedObj* downcast(CheckedObj*) { return nullptr; }
+
+ void foo() {
+ CheckedPtr<CheckedObj> bar;
+ consume_ref_countable( downcast(bar.get()) );
+ }
+}
+
+namespace string_impl {
+ struct String {
+ CheckedObj* impl() { return nullptr; }
+ };
+
+ struct AtomString {
+ CheckedObj rc;
+ CheckedObj& impl() { return rc; }
+ };
+
+ void consume_ptr(CheckedObj*) {}
+ void consume_ref(CheckedObj&) {}
+
+ namespace simple {
+ void foo() {
+ String s;
+ AtomString as;
+ consume_ptr(s.impl());
+ consume_ref(as.impl());
+ }
+ }
+}
+
+namespace default_arg {
+ CheckedObj* global;
+
+ void function_with_default_arg(CheckedObj* param = global);
+ // expected-warning at -1{{Call argument for parameter 'param' is unchecked and unsafe}}
+
+ void foo() {
+ function_with_default_arg();
+ }
+}
+
+namespace cxx_member_func {
+ CheckedRef<CheckedObj> provideProtected();
+ void foo() {
+ provide()->trivial();
+ provide()->method();
+ // expected-warning at -1{{Call argument for 'this' parameter is unchecked and unsafe}}
+ provideProtected()->method();
+ (provideProtected())->method();
+ };
+}
+
+namespace cxx_member_operator_call {
+ // The hidden this-pointer argument without a corresponding parameter caused couple bugs in parameter <-> argument attribution.
+ struct Foo {
+ Foo& operator+(CheckedObj* bad);
+ friend Foo& operator-(Foo& lhs, CheckedObj* bad);
+ void operator()(CheckedObj* bad);
+ };
+
+ CheckedObj* global;
+
+ void foo() {
+ Foo f;
+ f + global;
+ // expected-warning at -1{{Call argument for parameter 'bad' is unchecked and unsafe}}
+ f - global;
+ // expected-warning at -1{{Call argument for parameter 'bad' is unchecked and unsafe}}
+ f(global);
+ // expected-warning at -1{{Call argument for parameter 'bad' is unchecked and unsafe}}
+ }
+}
+
+namespace call_with_ptr_on_ref {
+ CheckedRef<CheckedObj> provideProtected();
+ void bar(CheckedObj* bad);
+ bool baz();
+ void foo(bool v) {
+ bar(v ? nullptr : provideProtected().ptr());
+ bar(baz() ? provideProtected().ptr() : nullptr);
+ bar(v ? provide() : provideProtected().ptr());
+ // expected-warning at -1{{Call argument for parameter 'bad' is unchecked and unsafe}}
+ bar(v ? provideProtected().ptr() : provide());
+ // expected-warning at -1{{Call argument for parameter 'bad' is unchecked and unsafe}}
+ }
+}
+
+namespace call_with_explicit_temporary_obj {
+ void foo() {
+ CheckedRef { *provide() }->method();
+ CheckedPtr { provide() }->method();
+ }
+}
diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-checked-return-value.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-checked-return-value.cpp
new file mode 100644
index 00000000000000..33f7f8272a2560
--- /dev/null
+++ b/clang/test/Analysis/Checkers/WebKit/call-args-checked-return-value.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedCallArgsChecker -verify %s
+// expected-no-diagnostics
+
+#include "mock-types.h"
+
+class Checkable {
+public:
+ void ref() const;
+ void deref() const;
+};
+
+class Object {
+public:
+ void ref() const;
+ void deref() const;
+ void someFunction(Checkable&);
+};
+
+RefPtr<Object> object();
+RefPtr<Checkable> protectedTargetObject();
+
+void testFunction() {
+ if (RefPtr obj = object())
+ obj->someFunction(*protectedTargetObject());
+}
diff --git a/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
index 6a4c92390d773b..8579141aa7f99c 100644
--- a/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn
@@ -142,7 +142,7 @@ static_library("Checkers") {
"WebKit/PtrTypesSemantics.cpp",
"WebKit/RawPtrRefMemberChecker.cpp",
"WebKit/RefCntblBaseVirtualDtorChecker.cpp",
- "WebKit/UncountedCallArgsChecker.cpp",
+ "WebKit/RawPtrRefCallArgsChecker.cpp",
"WebKit/Unco...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/114522
More information about the cfe-commits
mailing list