@@ -36,6 +36,7 @@ class RawPtrRefLambdaCapturesChecker
3636 : Bug(this , description, " WebKit coding guidelines" ) {}
3737
3838 virtual std::optional<bool > isUnsafePtr (QualType) const = 0;
39+ virtual bool isPtrType (const std::string &) const = 0;
3940 virtual const char *ptrKind (QualType QT) const = 0;
4041
4142 void checkASTDecl (const TranslationUnitDecl *TUD, AnalysisManager &MGR,
@@ -68,6 +69,15 @@ class RawPtrRefLambdaCapturesChecker
6869 return DynamicRecursiveASTVisitor::TraverseCXXMethodDecl (CXXMD);
6970 }
7071
72+ bool TraverseObjCMethodDecl (ObjCMethodDecl *OCMD) override {
73+ llvm::SaveAndRestore SavedDecl (ClsType);
74+ if (OCMD && OCMD->isInstanceMethod ()) {
75+ if (auto *ImplParamDecl = OCMD->getSelfDecl ())
76+ ClsType = ImplParamDecl->getType ();
77+ }
78+ return DynamicRecursiveASTVisitor::TraverseObjCMethodDecl (OCMD);
79+ }
80+
7181 bool VisitTypedefDecl (TypedefDecl *TD) override {
7282 if (Checker->RTC )
7383 Checker->RTC ->visitTypedef (TD);
@@ -275,10 +285,10 @@ class RawPtrRefLambdaCapturesChecker
275285 auto *VD = dyn_cast<VarDecl>(ValueDecl);
276286 if (!VD)
277287 return false ;
278- auto *Init = VD->getInit ()-> IgnoreParenCasts () ;
288+ auto *Init = VD->getInit ();
279289 if (!Init)
280290 return false ;
281- const Expr *Arg = Init;
291+ const Expr *Arg = Init-> IgnoreParenCasts () ;
282292 do {
283293 if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg))
284294 Arg = BTE->getSubExpr ()->IgnoreParenCasts ();
@@ -287,7 +297,7 @@ class RawPtrRefLambdaCapturesChecker
287297 if (!Ctor)
288298 return false ;
289299 auto clsName = safeGetName (Ctor->getParent ());
290- if (isRefType (clsName) && CE->getNumArgs ()) {
300+ if (Checker-> isPtrType (clsName) && CE->getNumArgs ()) {
291301 Arg = CE->getArg (0 )->IgnoreParenCasts ();
292302 continue ;
293303 }
@@ -307,6 +317,12 @@ class RawPtrRefLambdaCapturesChecker
307317 Arg = CE->getArg (0 )->IgnoreParenCasts ();
308318 continue ;
309319 }
320+ if (auto *Callee = CE->getDirectCallee ()) {
321+ if (isCtorOfSafePtr (Callee) && CE->getNumArgs () == 1 ) {
322+ Arg = CE->getArg (0 )->IgnoreParenCasts ();
323+ continue ;
324+ }
325+ }
310326 }
311327 if (auto *OpCE = dyn_cast<CXXOperatorCallExpr>(Arg)) {
312328 auto OpCode = OpCE->getOperator ();
@@ -315,7 +331,7 @@ class RawPtrRefLambdaCapturesChecker
315331 if (!Callee)
316332 return false ;
317333 auto clsName = safeGetName (Callee->getParent ());
318- if (!isRefType (clsName) || !OpCE->getNumArgs ())
334+ if (!Checker-> isPtrType (clsName) || !OpCE->getNumArgs ())
319335 return false ;
320336 Arg = OpCE->getArg (0 )->IgnoreParenCasts ();
321337 continue ;
@@ -330,8 +346,15 @@ class RawPtrRefLambdaCapturesChecker
330346 }
331347 break ;
332348 } while (Arg);
333- if (auto *DRE = dyn_cast<DeclRefExpr>(Arg))
334- return ProtectedThisDecls.contains (DRE->getDecl ());
349+ if (auto *DRE = dyn_cast<DeclRefExpr>(Arg)) {
350+ auto *Decl = DRE->getDecl ();
351+ if (auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(Decl)) {
352+ auto kind = ImplicitParam->getParameterKind ();
353+ return kind == ImplicitParamKind::ObjCSelf ||
354+ kind == ImplicitParamKind::CXXThis;
355+ }
356+ return ProtectedThisDecls.contains (Decl);
357+ }
335358 return isa<CXXThisExpr>(Arg);
336359 }
337360 };
@@ -351,10 +374,17 @@ class RawPtrRefLambdaCapturesChecker
351374 ValueDecl *CapturedVar = C.getCapturedVar ();
352375 if (ignoreParamVarDecl && isa<ParmVarDecl>(CapturedVar))
353376 continue ;
377+ if (auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(CapturedVar)) {
378+ auto kind = ImplicitParam->getParameterKind ();
379+ if ((kind == ImplicitParamKind::ObjCSelf ||
380+ kind == ImplicitParamKind::CXXThis) &&
381+ !shouldCheckThis)
382+ continue ;
383+ }
354384 QualType CapturedVarQualType = CapturedVar->getType ();
355385 auto IsUncountedPtr = isUnsafePtr (CapturedVar->getType ());
356386 if (IsUncountedPtr && *IsUncountedPtr)
357- reportBug (C, CapturedVar, CapturedVarQualType);
387+ reportBug (C, CapturedVar, CapturedVarQualType, L );
358388 } else if (C.capturesThis () && shouldCheckThis) {
359389 if (ignoreParamVarDecl) // this is always a parameter to this function.
360390 continue ;
@@ -364,11 +394,12 @@ class RawPtrRefLambdaCapturesChecker
364394 }
365395
366396 void reportBug (const LambdaCapture &Capture, ValueDecl *CapturedVar,
367- const QualType T) const {
397+ const QualType T, LambdaExpr *L ) const {
368398 assert (CapturedVar);
369399
370- if (isa<ImplicitParamDecl>(CapturedVar) && !Capture.getLocation ().isValid ())
371- return ; // Ignore implicit captruing of self.
400+ auto Location = Capture.getLocation ();
401+ if (isa<ImplicitParamDecl>(CapturedVar) && !Location.isValid ())
402+ Location = L->getBeginLoc ();
372403
373404 SmallString<100 > Buf;
374405 llvm::raw_svector_ostream Os (Buf);
@@ -387,7 +418,7 @@ class RawPtrRefLambdaCapturesChecker
387418 printQuotedQualifiedName (Os, CapturedVar);
388419 Os << " to " << ptrKind (T) << " type is unsafe." ;
389420
390- PathDiagnosticLocation BSLoc (Capture. getLocation () , BR->getSourceManager ());
421+ PathDiagnosticLocation BSLoc (Location , BR->getSourceManager ());
391422 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
392423 BR->emitReport (std::move (Report));
393424 }
@@ -429,6 +460,10 @@ class UncountedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
429460 return result2;
430461 }
431462
463+ virtual bool isPtrType (const std::string &Name) const final {
464+ return isRefType (Name) || isCheckedPtr (Name);
465+ }
466+
432467 const char *ptrKind (QualType QT) const final {
433468 if (isUncounted (QT))
434469 return " uncounted" ;
@@ -448,6 +483,10 @@ class UnretainedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
448483 return RTC->isUnretained (QT);
449484 }
450485
486+ virtual bool isPtrType (const std::string &Name) const final {
487+ return isRetainPtr (Name);
488+ }
489+
451490 const char *ptrKind (QualType QT) const final { return " unretained" ; }
452491};
453492
0 commit comments