Skip to content

Commit 24fc757

Browse files
committed
[alpha.webkit.UncountedCallArgsChecker] Detect a return value of Ref<T> & RefPtr<T>
This PR makes the checker not emit warning when a function is called with a return value of another function when the return value is of type `Ref<T>` or `RefPtr<T>`.
1 parent 535da10 commit 24fc757

File tree

5 files changed

+53
-0
lines changed

5 files changed

+53
-0
lines changed

clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ namespace clang {
1919
std::pair<const Expr *, bool>
2020
tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj) {
2121
while (E) {
22+
if (auto *tempExpr = dyn_cast<MaterializeTemporaryExpr>(E)) {
23+
E = tempExpr->getSubExpr();
24+
continue;
25+
}
2226
if (auto *cast = dyn_cast<CastExpr>(E)) {
2327
if (StopAtFirstRefCountedObj) {
2428
if (auto *ConversionFunc =
@@ -62,6 +66,8 @@ tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj) {
6266
E = call->getArg(0);
6367
continue;
6468
}
69+
if (isReturnValueRefCounted(callee))
70+
return {E, true};
6571

6672
if (isPtrConversion(callee)) {
6773
E = call->getArg(0);

clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,26 @@ bool isCtorOfRefCounted(const clang::FunctionDecl *F) {
118118
|| FunctionName == "Identifier";
119119
}
120120

121+
bool isReturnValueRefCounted(const clang::FunctionDecl *F) {
122+
assert(F);
123+
auto *type = F->getReturnType().getTypePtrOrNull();
124+
while (type) {
125+
if (auto *elaboratedT = dyn_cast<ElaboratedType>(type)) {
126+
type = elaboratedT->desugar().getTypePtrOrNull();
127+
continue;
128+
}
129+
if (auto *specialT = dyn_cast<TemplateSpecializationType>(type)) {
130+
if (auto *decl = specialT->getTemplateName().getAsTemplateDecl()) {
131+
auto name = decl->getNameAsString();
132+
return name == "Ref" || name == "RefPtr";
133+
}
134+
return false;
135+
}
136+
return false;
137+
}
138+
return false;
139+
}
140+
121141
std::optional<bool> isUncounted(const CXXRecordDecl* Class)
122142
{
123143
// Keep isRefCounted first as it's cheaper.

clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ std::optional<bool> isUncountedPtr(const clang::Type* T);
5050
/// false if not.
5151
bool isCtorOfRefCounted(const clang::FunctionDecl *F);
5252

53+
/// \returns true if \p F returns a ref-counted object, false if not.
54+
bool isReturnValueRefCounted(const clang::FunctionDecl *F);
55+
5356
/// \returns true if \p M is getter of a ref-counted class, false if not.
5457
std::optional<bool> isGetterOfRefCounted(const clang::CXXMethodDecl* Method);
5558

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "mock-types.h"
5+
6+
class RefCounted {
7+
public:
8+
void ref();
9+
void deref();
10+
};
11+
12+
class Object {
13+
public:
14+
void someFunction(RefCounted&);
15+
};
16+
17+
RefPtr<Object> object();
18+
RefPtr<RefCounted> protectedTargetObject();
19+
20+
void testFunction() {
21+
if (RefPtr obj = object())
22+
obj->someFunction(*protectedTargetObject());
23+
}

clang/test/Analysis/Checkers/WebKit/mock-types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ template <typename T> struct RefPtr {
2020
T *operator->() { return t; }
2121
T &operator*() { return *t; }
2222
RefPtr &operator=(T *) { return *this; }
23+
operator bool() { return t; }
2324
};
2425

2526
template <typename T> bool operator==(const RefPtr<T> &, const RefPtr<T> &) {

0 commit comments

Comments
 (0)