@@ -50,7 +50,9 @@ class RawPtrRefLambdaCapturesChecker
5050 llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore;
5151 llvm::DenseSet<const LambdaExpr *> LambdasToIgnore;
5252 llvm::DenseSet<const ValueDecl *> ProtectedThisDecls;
53+ llvm::DenseSet<const CallExpr *> CallToIgnore;
5354 llvm::DenseSet<const CXXConstructExpr *> ConstructToIgnore;
55+ llvm::DenseMap<const VarDecl *, const LambdaExpr *> LambdaOwnerMap;
5456
5557 QualType ClsType;
5658
@@ -101,10 +103,60 @@ class RawPtrRefLambdaCapturesChecker
101103 auto *Init = VD->getInit ();
102104 if (!Init)
103105 return true ;
104- auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts ());
105- if (!L)
106+ if (auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts ())) {
107+ LambdasToIgnore.insert (L); // Evaluate lambdas in VisitDeclRefExpr.
108+ return true ;
109+ }
110+ if (!VD->hasLocalStorage ())
106111 return true ;
107- LambdasToIgnore.insert (L); // Evaluate lambdas in VisitDeclRefExpr.
112+ if (auto *E = dyn_cast<ExprWithCleanups>(Init))
113+ Init = E->getSubExpr ();
114+ if (auto *E = dyn_cast<CXXBindTemporaryExpr>(Init))
115+ Init = E->getSubExpr ();
116+ if (auto *CE = dyn_cast<CallExpr>(Init)) {
117+ if (auto *Callee = CE->getDirectCallee ()) {
118+ auto FnName = safeGetName (Callee);
119+ unsigned ArgCnt = CE->getNumArgs ();
120+ if (FnName == " makeScopeExit" && ArgCnt == 1 ) {
121+ auto *Arg = CE->getArg (0 );
122+ if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
123+ Arg = E->getSubExpr ();
124+ if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
125+ LambdaOwnerMap.insert (std::make_pair (VD, L));
126+ CallToIgnore.insert (CE);
127+ LambdasToIgnore.insert (L);
128+ }
129+ } else if (FnName == " makeVisitor" ) {
130+ for (unsigned ArgIndex = 0 ; ArgIndex < ArgCnt; ++ArgIndex) {
131+ auto *Arg = CE->getArg (ArgIndex);
132+ if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
133+ Arg = E->getSubExpr ();
134+ if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
135+ LambdaOwnerMap.insert (std::make_pair (VD, L));
136+ CallToIgnore.insert (CE);
137+ LambdasToIgnore.insert (L);
138+ }
139+ }
140+ }
141+ }
142+ } else if (auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
143+ if (auto *Ctor = CE->getConstructor ()) {
144+ if (auto *Cls = Ctor->getParent ()) {
145+ auto FnName = safeGetName (Cls);
146+ unsigned ArgCnt = CE->getNumArgs ();
147+ if (FnName == " ScopeExit" && ArgCnt == 1 ) {
148+ auto *Arg = CE->getArg (0 );
149+ if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
150+ Arg = E->getSubExpr ();
151+ if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
152+ LambdaOwnerMap.insert (std::make_pair (VD, L));
153+ ConstructToIgnore.insert (CE);
154+ LambdasToIgnore.insert (L);
155+ }
156+ }
157+ }
158+ }
159+ }
108160 return true ;
109161 }
110162
@@ -114,6 +166,12 @@ class RawPtrRefLambdaCapturesChecker
114166 auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl ());
115167 if (!VD)
116168 return true ;
169+ if (auto It = LambdaOwnerMap.find (VD); It != LambdaOwnerMap.end ()) {
170+ auto *L = It->second ;
171+ Checker->visitLambdaExpr (L, shouldCheckThis () && !hasProtectedThis (L),
172+ ClsType);
173+ return true ;
174+ }
117175 auto *Init = VD->getInit ();
118176 if (!Init)
119177 return true ;
@@ -167,10 +225,14 @@ class RawPtrRefLambdaCapturesChecker
167225 }
168226
169227 bool VisitCallExpr (CallExpr *CE) override {
228+ if (CallToIgnore.contains (CE))
229+ return true ;
170230 checkCalleeLambda (CE);
171- if (auto *Callee = CE->getDirectCallee ())
231+ if (auto *Callee = CE->getDirectCallee ()) {
232+ if (isVisitFunction (CE, Callee))
233+ return true ;
172234 checkParameters (CE, Callee);
173- else if (auto *CalleeE = CE->getCallee ()) {
235+ } else if (auto *CalleeE = CE->getCallee ()) {
174236 if (auto *DRE = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts ())) {
175237 if (auto *Callee = dyn_cast_or_null<FunctionDecl>(DRE->getDecl ()))
176238 checkParameters (CE, Callee);
@@ -179,6 +241,34 @@ class RawPtrRefLambdaCapturesChecker
179241 return true ;
180242 }
181243
244+ bool isVisitFunction (CallExpr *CallExpr, FunctionDecl *FnDecl) {
245+ bool IsVisitFn = safeGetName (FnDecl) == " visit" ;
246+ if (!IsVisitFn)
247+ return false ;
248+ bool ArgCnt = CallExpr->getNumArgs ();
249+ if (!ArgCnt)
250+ return false ;
251+ auto *Ns = FnDecl->getParent ();
252+ if (!Ns)
253+ return false ;
254+ auto NsName = safeGetName (Ns);
255+ if (NsName != " WTF" && NsName != " std" )
256+ return false ;
257+ auto *Arg = CallExpr->getArg (0 );
258+ if (!Arg)
259+ return false ;
260+ auto *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenCasts ());
261+ if (!DRE)
262+ return false ;
263+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl ());
264+ if (!VD)
265+ return false ;
266+ if (!LambdaOwnerMap.contains (VD))
267+ return false ;
268+ DeclRefExprsToIgnore.insert (DRE);
269+ return true ;
270+ }
271+
182272 void checkParameters (CallExpr *CE, FunctionDecl *Callee) {
183273 unsigned ArgIndex = isa<CXXOperatorCallExpr>(CE);
184274 bool TreatAllArgsAsNoEscape = shouldTreatAllArgAsNoEscape (Callee);
@@ -280,7 +370,7 @@ class RawPtrRefLambdaCapturesChecker
280370 LambdasToIgnore.insert (L);
281371 }
282372
283- bool hasProtectedThis (LambdaExpr *L) {
373+ bool hasProtectedThis (const LambdaExpr *L) {
284374 for (const LambdaCapture &OtherCapture : L->captures ()) {
285375 if (!OtherCapture.capturesVariable ())
286376 continue ;
@@ -378,7 +468,8 @@ class RawPtrRefLambdaCapturesChecker
378468 visitor.TraverseDecl (const_cast <TranslationUnitDecl *>(TUD));
379469 }
380470
381- void visitLambdaExpr (LambdaExpr *L, bool shouldCheckThis, const QualType T,
471+ void visitLambdaExpr (const LambdaExpr *L, bool shouldCheckThis,
472+ const QualType T,
382473 bool ignoreParamVarDecl = false ) const {
383474 if (TFA.isTrivial (L->getBody ()))
384475 return ;
@@ -410,7 +501,7 @@ class RawPtrRefLambdaCapturesChecker
410501 }
411502
412503 void reportBug (const LambdaCapture &Capture, ValueDecl *CapturedVar,
413- const QualType T, LambdaExpr *L) const {
504+ const QualType T, const LambdaExpr *L) const {
414505 assert (CapturedVar);
415506
416507 auto Location = Capture.getLocation ();
0 commit comments