Skip to content

Commit af17cbe

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 c6c08e7 commit af17cbe

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
@@ -162,6 +162,24 @@ bool tryToFindPtrOrigin(
162162
Name == "NSClassFromString")
163163
return callback(E, true);
164164
}
165+
166+
// Sometimes, canonical type erroneously turns Ref<T> into T.
167+
// Workaround this problem by checking again if the original type was
168+
// a SubstTemplateTypeParmType of a safe smart pointer type (e.g. Ref).
169+
if (auto *CalleeDecl = call->getCalleeDecl()) {
170+
if (auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
171+
auto RetType = FD->getReturnType();
172+
if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(RetType)) {
173+
if (auto *SubstType = Subst->desugar().getTypePtr()) {
174+
if (auto *RD = dyn_cast<RecordType>(SubstType)) {
175+
if (auto *CXX = dyn_cast<CXXRecordDecl>(RD->getOriginalDecl()))
176+
if (isSafePtr(CXX))
177+
return callback(E, true);
178+
}
179+
}
180+
}
181+
}
182+
}
165183
}
166184
if (auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
167185
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)