Skip to content

Commit da6ac95

Browse files
authored
[webkit.UncountedLambdaCapturesChecker] Support [[clang::noescape]] on a constructor (#126869)
Added the support for annotating a constructor's argument with [[clang::noescape]]. We explicitly ignore CXXConstructExpr which is visited as a part of CallExpr so that construction of closures like Function, CompletionHandler, etc... don't result in a warning.
1 parent 18f60bc commit da6ac95

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class UncountedLambdaCapturesChecker
4141
const UncountedLambdaCapturesChecker *Checker;
4242
llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore;
4343
llvm::DenseSet<const LambdaExpr *> LambdasToIgnore;
44+
llvm::DenseSet<const CXXConstructExpr *> ConstructToIgnore;
4445
QualType ClsType;
4546

4647
explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker)
@@ -106,6 +107,26 @@ class UncountedLambdaCapturesChecker
106107
return safeGetName(NsDecl) == "WTF" && safeGetName(Decl) == "switchOn";
107108
}
108109

110+
bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
111+
if (ConstructToIgnore.contains(CE))
112+
return true;
113+
if (auto *Callee = CE->getConstructor()) {
114+
unsigned ArgIndex = 0;
115+
for (auto *Param : Callee->parameters()) {
116+
if (ArgIndex >= CE->getNumArgs())
117+
return true;
118+
auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts();
119+
if (auto *L = findLambdaInArg(Arg)) {
120+
LambdasToIgnore.insert(L);
121+
if (!Param->hasAttr<NoEscapeAttr>())
122+
Checker->visitLambdaExpr(L, shouldCheckThis());
123+
}
124+
++ArgIndex;
125+
}
126+
}
127+
return true;
128+
}
129+
109130
bool VisitCallExpr(CallExpr *CE) override {
110131
checkCalleeLambda(CE);
111132
if (auto *Callee = CE->getDirectCallee()) {
@@ -143,8 +164,10 @@ class UncountedLambdaCapturesChecker
143164
auto *CtorArg = CE->getArg(0)->IgnoreParenCasts();
144165
if (!CtorArg)
145166
return nullptr;
146-
if (auto *Lambda = dyn_cast<LambdaExpr>(CtorArg))
167+
if (auto *Lambda = dyn_cast<LambdaExpr>(CtorArg)) {
168+
ConstructToIgnore.insert(CE);
147169
return Lambda;
170+
}
148171
auto *DRE = dyn_cast<DeclRefExpr>(CtorArg);
149172
if (!DRE)
150173
return nullptr;
@@ -157,6 +180,7 @@ class UncountedLambdaCapturesChecker
157180
TempExpr = dyn_cast<CXXBindTemporaryExpr>(Init->IgnoreParenCasts());
158181
if (!TempExpr)
159182
return nullptr;
183+
ConstructToIgnore.insert(CE);
160184
return dyn_cast_or_null<LambdaExpr>(TempExpr->getSubExpr());
161185
}
162186

clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,11 @@ struct RefCountableWithLambdaCapturingThis {
298298
callLambda([&]() -> RefPtr<RefCountable> {
299299
return obj->next();
300300
});
301+
WTF::HashMap<int, RefPtr<RefCountable>> anotherMap([&] {
302+
return obj->next();
303+
});
301304
}
305+
302306
};
303307

304308
struct NonRefCountableWithLambdaCapturingThis {

0 commit comments

Comments
 (0)