Skip to content

Commit 3d5e9ab

Browse files
authored
[alpha.webkit.UncountedCallArgsChecker] Avoid emitting warnings for Ref, RefPtr, and their variants. (#90153)
Skip the analysis of Ref, RefPtr, and their variant classes in UncountedCallArgsChecker since these classes are "trusted" to not do anything dangerous.
1 parent 12d322d commit 3d5e9ab

File tree

4 files changed

+62
-16
lines changed

4 files changed

+62
-16
lines changed

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> isUncounted(const clang::CXXRecordDecl* Class);
5050
/// class, false if not, std::nullopt if inconclusive.
5151
std::optional<bool> isUncountedPtr(const clang::Type* T);
5252

53+
/// \returns true if Name is a RefPtr, Ref, or its variant, false if not.
54+
bool isRefType(const std::string &Name);
55+
5356
/// \returns true if \p F creates ref-countable object from uncounted parameter,
5457
/// false if not.
5558
bool isCtorOfRefCounted(const clang::FunctionDecl *F);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ class UncountedCallArgsChecker
5353
bool shouldVisitTemplateInstantiations() const { return true; }
5454
bool shouldVisitImplicitCode() const { return false; }
5555

56+
bool TraverseDecl(Decl *D) {
57+
if (isa<ClassTemplateDecl>(D) && isRefType(safeGetName(D)))
58+
return true;
59+
return RecursiveASTVisitor<LocalVisitor>::TraverseDecl(D);
60+
}
61+
5662
bool VisitCallExpr(const CallExpr *CE) {
5763
Checker->visitCallExpr(CE);
5864
return true;

clang/test/Analysis/Checkers/WebKit/call-args.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace ref_counted {
3232
void consume_ref_counted(Ref<RefCountable>) {}
3333

3434
void foo() {
35-
consume_refcntbl(provide_ref_counted().get());
35+
consume_refcntbl(provide_ref_counted().ptr());
3636
// no warning
3737
}
3838
}

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

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,61 @@
11
#ifndef mock_types_1103988513531
22
#define mock_types_1103988513531
33

4-
template <typename T> struct Ref {
5-
T *t;
4+
template<typename T>
5+
struct RawPtrTraits {
6+
using StorageType = T*;
67

7-
Ref() : t{} {};
8-
Ref(T &t)
9-
: t(t) {
10-
if (t)
11-
t->ref();
8+
template<typename U>
9+
static T* exchange(StorageType& ptr, U&& newValue)
10+
{
11+
StorageType oldValue = static_cast<StorageType&&>(ptr);
12+
ptr = static_cast<U&&>(newValue);
13+
return oldValue;
1214
}
13-
~Ref() {
14-
if (t)
15-
t->deref();
15+
16+
static void swap(StorageType& a, StorageType& b)
17+
{
18+
StorageType temp = static_cast<StorageType&&>(a);
19+
a = static_cast<StorageType&&>(b);
20+
b = static_cast<StorageType&&>(temp);
1621
}
17-
T *get() { return t; }
18-
T *ptr() { return t; }
19-
T *operator->() { return t; }
20-
operator const T &() const { return *t; }
21-
operator T &() { return *t; }
22+
static T* unwrap(const StorageType& ptr) { return ptr; }
23+
};
24+
25+
template<typename T> struct DefaultRefDerefTraits {
26+
static T* refIfNotNull(T* ptr)
27+
{
28+
if (ptr)
29+
ptr->ref();
30+
return ptr;
31+
}
32+
33+
static T& ref(T& ref)
34+
{
35+
ref.ref();
36+
return ref;
37+
}
38+
39+
static void derefIfNotNull(T* ptr)
40+
{
41+
if (ptr)
42+
ptr->deref();
43+
}
44+
};
45+
46+
template <typename T, typename PtrTraits = RawPtrTraits<T>, typename RefDerefTraits = DefaultRefDerefTraits<T>> struct Ref {
47+
typename PtrTraits::StorageType t;
48+
49+
Ref() : t{} {};
50+
Ref(T &t) : t(RefDerefTraits::refIfNotNull(t)) { }
51+
Ref(const Ref& o) : t(RefDerefTraits::refIfNotNull(PtrTraits::unwrap(o.t))) { }
52+
~Ref() { RefDerefTraits::derefIfNotNull(PtrTraits::exchange(t, nullptr)); }
53+
T &get() { return *PtrTraits::unwrap(t); }
54+
T *ptr() { return PtrTraits::unwrap(t); }
55+
T *operator->() { return PtrTraits::unwrap(t); }
56+
operator const T &() const { return *PtrTraits::unwrap(t); }
57+
operator T &() { return *PtrTraits::unwrap(t); }
58+
T* leakRef() { PtrTraits::exchange(t, nullptr); }
2259
};
2360

2461
template <typename T> struct RefPtr {

0 commit comments

Comments
 (0)