@@ -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,
@@ -71,6 +72,15 @@ class RawPtrRefLambdaCapturesChecker
7172 return Base::TraverseCXXMethodDecl (CXXMD);
7273 }
7374
75+ bool TraverseObjCMethodDecl (ObjCMethodDecl *OCMD) {
76+ llvm::SaveAndRestore SavedDecl (ClsType);
77+ if (OCMD && OCMD->isInstanceMethod ()) {
78+ if (auto *ImplParamDecl = OCMD->getSelfDecl ())
79+ ClsType = ImplParamDecl->getType ();
80+ }
81+ return Base::TraverseObjCMethodDecl (OCMD);
82+ }
83+
7484 bool VisitTypedefDecl (TypedefDecl *TD) {
7585 if (Checker->RTC )
7686 Checker->RTC ->visitTypedef (TD);
@@ -278,10 +288,10 @@ class RawPtrRefLambdaCapturesChecker
278288 auto *VD = dyn_cast<VarDecl>(ValueDecl);
279289 if (!VD)
280290 return false ;
281- auto *Init = VD->getInit ()-> IgnoreParenCasts () ;
291+ auto *Init = VD->getInit ();
282292 if (!Init)
283293 return false ;
284- const Expr *Arg = Init;
294+ const Expr *Arg = Init-> IgnoreParenCasts () ;
285295 do {
286296 if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg))
287297 Arg = BTE->getSubExpr ()->IgnoreParenCasts ();
@@ -290,7 +300,7 @@ class RawPtrRefLambdaCapturesChecker
290300 if (!Ctor)
291301 return false ;
292302 auto clsName = safeGetName (Ctor->getParent ());
293- if (isRefType (clsName) && CE->getNumArgs ()) {
303+ if (Checker-> isPtrType (clsName) && CE->getNumArgs ()) {
294304 Arg = CE->getArg (0 )->IgnoreParenCasts ();
295305 continue ;
296306 }
@@ -310,6 +320,12 @@ class RawPtrRefLambdaCapturesChecker
310320 Arg = CE->getArg (0 )->IgnoreParenCasts ();
311321 continue ;
312322 }
323+ if (auto *Callee = CE->getDirectCallee ()) {
324+ if (isCtorOfSafePtr (Callee) && CE->getNumArgs () == 1 ) {
325+ Arg = CE->getArg (0 )->IgnoreParenCasts ();
326+ continue ;
327+ }
328+ }
313329 }
314330 if (auto *OpCE = dyn_cast<CXXOperatorCallExpr>(Arg)) {
315331 auto OpCode = OpCE->getOperator ();
@@ -318,7 +334,7 @@ class RawPtrRefLambdaCapturesChecker
318334 if (!Callee)
319335 return false ;
320336 auto clsName = safeGetName (Callee->getParent ());
321- if (!isRefType (clsName) || !OpCE->getNumArgs ())
337+ if (!Checker-> isPtrType (clsName) || !OpCE->getNumArgs ())
322338 return false ;
323339 Arg = OpCE->getArg (0 )->IgnoreParenCasts ();
324340 continue ;
@@ -333,8 +349,15 @@ class RawPtrRefLambdaCapturesChecker
333349 }
334350 break ;
335351 } while (Arg);
336- if (auto *DRE = dyn_cast<DeclRefExpr>(Arg))
337- return ProtectedThisDecls.contains (DRE->getDecl ());
352+ if (auto *DRE = dyn_cast<DeclRefExpr>(Arg)) {
353+ auto *Decl = DRE->getDecl ();
354+ if (auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(Decl)) {
355+ auto kind = ImplicitParam->getParameterKind ();
356+ return kind == ImplicitParamKind::ObjCSelf ||
357+ kind == ImplicitParamKind::CXXThis;
358+ }
359+ return ProtectedThisDecls.contains (Decl);
360+ }
338361 return isa<CXXThisExpr>(Arg);
339362 }
340363 };
@@ -354,10 +377,17 @@ class RawPtrRefLambdaCapturesChecker
354377 ValueDecl *CapturedVar = C.getCapturedVar ();
355378 if (ignoreParamVarDecl && isa<ParmVarDecl>(CapturedVar))
356379 continue ;
380+ if (auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(CapturedVar)) {
381+ auto kind = ImplicitParam->getParameterKind ();
382+ if ((kind == ImplicitParamKind::ObjCSelf ||
383+ kind == ImplicitParamKind::CXXThis) &&
384+ !shouldCheckThis)
385+ continue ;
386+ }
357387 QualType CapturedVarQualType = CapturedVar->getType ();
358388 auto IsUncountedPtr = isUnsafePtr (CapturedVar->getType ());
359389 if (IsUncountedPtr && *IsUncountedPtr)
360- reportBug (C, CapturedVar, CapturedVarQualType);
390+ reportBug (C, CapturedVar, CapturedVarQualType, L );
361391 } else if (C.capturesThis () && shouldCheckThis) {
362392 if (ignoreParamVarDecl) // this is always a parameter to this function.
363393 continue ;
@@ -367,11 +397,12 @@ class RawPtrRefLambdaCapturesChecker
367397 }
368398
369399 void reportBug (const LambdaCapture &Capture, ValueDecl *CapturedVar,
370- const QualType T) const {
400+ const QualType T, LambdaExpr *L ) const {
371401 assert (CapturedVar);
372402
373- if (isa<ImplicitParamDecl>(CapturedVar) && !Capture.getLocation ().isValid ())
374- return ; // Ignore implicit captruing of self.
403+ auto Location = Capture.getLocation ();
404+ if (isa<ImplicitParamDecl>(CapturedVar) && !Location.isValid ())
405+ Location = L->getBeginLoc ();
375406
376407 SmallString<100 > Buf;
377408 llvm::raw_svector_ostream Os (Buf);
@@ -390,7 +421,7 @@ class RawPtrRefLambdaCapturesChecker
390421 printQuotedQualifiedName (Os, CapturedVar);
391422 Os << " to " << ptrKind (T) << " type is unsafe." ;
392423
393- PathDiagnosticLocation BSLoc (Capture. getLocation () , BR->getSourceManager ());
424+ PathDiagnosticLocation BSLoc (Location , BR->getSourceManager ());
394425 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
395426 BR->emitReport (std::move (Report));
396427 }
@@ -432,6 +463,10 @@ class UncountedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
432463 return result2;
433464 }
434465
466+ virtual bool isPtrType (const std::string &Name) const final {
467+ return isRefType (Name) || isCheckedPtr (Name);
468+ }
469+
435470 const char *ptrKind (QualType QT) const final {
436471 if (isUncounted (QT))
437472 return " uncounted" ;
@@ -451,6 +486,10 @@ class UnretainedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
451486 return RTC->isUnretained (QT);
452487 }
453488
489+ virtual bool isPtrType (const std::string &Name) const final {
490+ return isRetainPtr (Name);
491+ }
492+
454493 const char *ptrKind (QualType QT) const final { return " unretained" ; }
455494};
456495
0 commit comments