Skip to content

Commit 377f096

Browse files
committed
Fix an implicit cast to a base ref counted class generates a false positive.
The bug was caused by isRefCountable erroneously returning false for a class with both ref() and deref() functions defined because we were not resetting the base paths results between looking for "ref()" and "deref()"
1 parent 8ea7f1d commit 377f096

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ std::optional<bool> isRefCountable(const CXXRecordDecl* R)
8484
if (AnyInconclusiveBase)
8585
return std::nullopt;
8686

87+
Paths.clear();
8788
const auto hasPublicDerefInBase =
8889
[&AnyInconclusiveBase](const CXXBaseSpecifier *Base, CXXBasePath &) {
8990
auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref");
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
2+
// expected-no-diagnostics
3+
4+
template<typename T>
5+
class Ref {
6+
public:
7+
~Ref()
8+
{
9+
if (auto* ptr = m_ptr)
10+
ptr->deref();
11+
m_ptr = nullptr;
12+
}
13+
14+
Ref(T& object)
15+
: m_ptr(&object)
16+
{
17+
object.ref();
18+
}
19+
20+
operator T&() const { return *m_ptr; }
21+
bool operator!() const { return !*m_ptr; }
22+
23+
private:
24+
T* m_ptr;
25+
};
26+
27+
class Base {
28+
public:
29+
virtual ~Base();
30+
void ref() const;
31+
void deref() const;
32+
};
33+
34+
class Event : public Base {
35+
protected:
36+
explicit Event();
37+
};
38+
39+
class SubEvent : public Event {
40+
public:
41+
static Ref<SubEvent> create();
42+
private:
43+
SubEvent() = default;
44+
};
45+
46+
void someFunction(Base&);
47+
48+
static void test()
49+
{
50+
someFunction(SubEvent::create());
51+
}

0 commit comments

Comments
 (0)