Skip to content

Commit 8d61928

Browse files
committed
[alpha.webkit.UncountedCallArgsChecker] A return value can be erroneously treated as unsafe if it's a template parameter (llvm#157993)
When a template class takes Ref<T> as a template parameter and this template parameter is used as the return value of a member function, the return value can be treated as unsafe (i.e. emits a false positive). The issue was caused by getCanonicalType sometimes converting Ref<T> to T. Workaround this problem by avoid emitting a warning when the original, non-canonical type is a safe pointer type.
1 parent cabdb22 commit 8d61928

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,24 @@ bool tryToFindPtrOrigin(
161161
Name == "NSClassFromString")
162162
return callback(E, true);
163163
}
164+
165+
// Sometimes, canonical type erroneously turns Ref<T> into T.
166+
// Workaround this problem by checking again if the original type was
167+
// a SubstTemplateTypeParmType of a safe smart pointer type (e.g. Ref).
168+
if (auto *CalleeDecl = call->getCalleeDecl()) {
169+
if (auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
170+
auto RetType = FD->getReturnType();
171+
if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(RetType)) {
172+
if (auto *SubstType = Subst->desugar().getTypePtr()) {
173+
if (auto *RD = dyn_cast<RecordType>(SubstType)) {
174+
if (auto *CXX = dyn_cast<CXXRecordDecl>(RD->getDecl()))
175+
if (isSafePtr(CXX))
176+
return callback(E, true);
177+
}
178+
}
179+
}
180+
}
181+
}
164182
}
165183
if (auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
166184
if (auto *Method = ObjCMsgExpr->getMethodDecl()) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "mock-types.h"
5+
6+
struct Obj {
7+
void ref() const;
8+
void deref() const;
9+
10+
void someFunction();
11+
};
12+
13+
template<typename T> class Wrapper {
14+
public:
15+
T obj();
16+
};
17+
18+
static void foo(Wrapper<Ref<Obj>>&& wrapper)
19+
{
20+
wrapper.obj()->someFunction();
21+
}

0 commit comments

Comments
 (0)