-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[webkit.UncountedLambdaCapturesChecker] Support [[clang::noescape]] on a constructor #126869
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…n a constructor 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.
@llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) ChangesAdded 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. Full diff: https://github.com/llvm/llvm-project/pull/126869.diff 2 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
index a56f48c83c660..972364a855eb4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
@@ -41,6 +41,7 @@ class UncountedLambdaCapturesChecker
const UncountedLambdaCapturesChecker *Checker;
llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore;
llvm::DenseSet<const LambdaExpr *> LambdasToIgnore;
+ llvm::DenseSet<const CXXConstructExpr *> ConstructToIgnore;
QualType ClsType;
explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker)
@@ -106,6 +107,26 @@ class UncountedLambdaCapturesChecker
return safeGetName(NsDecl) == "WTF" && safeGetName(Decl) == "switchOn";
}
+ bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
+ if (ConstructToIgnore.contains(CE))
+ return true;
+ if (auto *Callee = CE->getConstructor()) {
+ unsigned ArgIndex = 0;
+ for (auto *Param : Callee->parameters()) {
+ if (ArgIndex >= CE->getNumArgs())
+ return true;
+ auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts();
+ if (auto *L = findLambdaInArg(Arg)) {
+ LambdasToIgnore.insert(L);
+ if (!Param->hasAttr<NoEscapeAttr>())
+ Checker->visitLambdaExpr(L, shouldCheckThis());
+ }
+ ++ArgIndex;
+ }
+ }
+ return true;
+ }
+
bool VisitCallExpr(CallExpr *CE) override {
checkCalleeLambda(CE);
if (auto *Callee = CE->getDirectCallee()) {
@@ -143,8 +164,10 @@ class UncountedLambdaCapturesChecker
auto *CtorArg = CE->getArg(0)->IgnoreParenCasts();
if (!CtorArg)
return nullptr;
- if (auto *Lambda = dyn_cast<LambdaExpr>(CtorArg))
+ if (auto *Lambda = dyn_cast<LambdaExpr>(CtorArg)) {
+ ConstructToIgnore.insert(CE);
return Lambda;
+ }
auto *DRE = dyn_cast<DeclRefExpr>(CtorArg);
if (!DRE)
return nullptr;
@@ -157,6 +180,7 @@ class UncountedLambdaCapturesChecker
TempExpr = dyn_cast<CXXBindTemporaryExpr>(Init->IgnoreParenCasts());
if (!TempExpr)
return nullptr;
+ ConstructToIgnore.insert(CE);
return dyn_cast_or_null<LambdaExpr>(TempExpr->getSubExpr());
}
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
index 4f4a960282253..62a8245db99b9 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
@@ -298,7 +298,11 @@ struct RefCountableWithLambdaCapturingThis {
callLambda([&]() -> RefPtr<RefCountable> {
return obj->next();
});
+ WTF::HashMap<int, RefPtr<RefCountable>> anotherMap([&] {
+ return obj->next();
+ });
}
+
};
struct NonRefCountableWithLambdaCapturingThis {
|
@llvm/pr-subscribers-clang-static-analyzer-1 Author: Ryosuke Niwa (rniwa) ChangesAdded 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. Full diff: https://github.com/llvm/llvm-project/pull/126869.diff 2 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
index a56f48c83c660..972364a855eb4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
@@ -41,6 +41,7 @@ class UncountedLambdaCapturesChecker
const UncountedLambdaCapturesChecker *Checker;
llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore;
llvm::DenseSet<const LambdaExpr *> LambdasToIgnore;
+ llvm::DenseSet<const CXXConstructExpr *> ConstructToIgnore;
QualType ClsType;
explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker)
@@ -106,6 +107,26 @@ class UncountedLambdaCapturesChecker
return safeGetName(NsDecl) == "WTF" && safeGetName(Decl) == "switchOn";
}
+ bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
+ if (ConstructToIgnore.contains(CE))
+ return true;
+ if (auto *Callee = CE->getConstructor()) {
+ unsigned ArgIndex = 0;
+ for (auto *Param : Callee->parameters()) {
+ if (ArgIndex >= CE->getNumArgs())
+ return true;
+ auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts();
+ if (auto *L = findLambdaInArg(Arg)) {
+ LambdasToIgnore.insert(L);
+ if (!Param->hasAttr<NoEscapeAttr>())
+ Checker->visitLambdaExpr(L, shouldCheckThis());
+ }
+ ++ArgIndex;
+ }
+ }
+ return true;
+ }
+
bool VisitCallExpr(CallExpr *CE) override {
checkCalleeLambda(CE);
if (auto *Callee = CE->getDirectCallee()) {
@@ -143,8 +164,10 @@ class UncountedLambdaCapturesChecker
auto *CtorArg = CE->getArg(0)->IgnoreParenCasts();
if (!CtorArg)
return nullptr;
- if (auto *Lambda = dyn_cast<LambdaExpr>(CtorArg))
+ if (auto *Lambda = dyn_cast<LambdaExpr>(CtorArg)) {
+ ConstructToIgnore.insert(CE);
return Lambda;
+ }
auto *DRE = dyn_cast<DeclRefExpr>(CtorArg);
if (!DRE)
return nullptr;
@@ -157,6 +180,7 @@ class UncountedLambdaCapturesChecker
TempExpr = dyn_cast<CXXBindTemporaryExpr>(Init->IgnoreParenCasts());
if (!TempExpr)
return nullptr;
+ ConstructToIgnore.insert(CE);
return dyn_cast_or_null<LambdaExpr>(TempExpr->getSubExpr());
}
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
index 4f4a960282253..62a8245db99b9 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
@@ -298,7 +298,11 @@ struct RefCountableWithLambdaCapturingThis {
callLambda([&]() -> RefPtr<RefCountable> {
return obj->next();
});
+ WTF::HashMap<int, RefPtr<RefCountable>> anotherMap([&] {
+ return obj->next();
+ });
}
+
};
struct NonRefCountableWithLambdaCapturingThis {
|
if (ArgIndex >= CE->getNumArgs()) | ||
return true; | ||
auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts(); | ||
if (auto *L = findLambdaInArg(Arg)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my understanding: Is the LambdaExpr not covered in VisitLambdaExpr
? What's special about the expression being an argument to a constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, so we wanna ignore lambda expressions that are passed to [[clang::noescape]]
argument. The code in VisitCallExpr
and now VisitCXXConstructExpr
is there to detect this specific case, and then ignore the argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Thanks for the review! |
…n a constructor (llvm#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.
…n a constructor (llvm#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.
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.