@@ -36,6 +36,7 @@ class RawPtrRefLambdaCapturesChecker
36
36
: Bug(this , description, " WebKit coding guidelines" ) {}
37
37
38
38
virtual std::optional<bool > isUnsafePtr (QualType) const = 0;
39
+ virtual bool isPtrType (const std::string &) const = 0;
39
40
virtual const char *ptrKind (QualType QT) const = 0;
40
41
41
42
void checkASTDecl (const TranslationUnitDecl *TUD, AnalysisManager &MGR,
@@ -71,6 +72,15 @@ class RawPtrRefLambdaCapturesChecker
71
72
return Base::TraverseCXXMethodDecl (CXXMD);
72
73
}
73
74
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
+
74
84
bool VisitTypedefDecl (TypedefDecl *TD) {
75
85
if (Checker->RTC )
76
86
Checker->RTC ->visitTypedef (TD);
@@ -278,10 +288,10 @@ class RawPtrRefLambdaCapturesChecker
278
288
auto *VD = dyn_cast<VarDecl>(ValueDecl);
279
289
if (!VD)
280
290
return false ;
281
- auto *Init = VD->getInit ()-> IgnoreParenCasts () ;
291
+ auto *Init = VD->getInit ();
282
292
if (!Init)
283
293
return false ;
284
- const Expr *Arg = Init;
294
+ const Expr *Arg = Init-> IgnoreParenCasts () ;
285
295
do {
286
296
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg))
287
297
Arg = BTE->getSubExpr ()->IgnoreParenCasts ();
@@ -290,7 +300,7 @@ class RawPtrRefLambdaCapturesChecker
290
300
if (!Ctor)
291
301
return false ;
292
302
auto clsName = safeGetName (Ctor->getParent ());
293
- if (isRefType (clsName) && CE->getNumArgs ()) {
303
+ if (Checker-> isPtrType (clsName) && CE->getNumArgs ()) {
294
304
Arg = CE->getArg (0 )->IgnoreParenCasts ();
295
305
continue ;
296
306
}
@@ -310,6 +320,12 @@ class RawPtrRefLambdaCapturesChecker
310
320
Arg = CE->getArg (0 )->IgnoreParenCasts ();
311
321
continue ;
312
322
}
323
+ if (auto *Callee = CE->getDirectCallee ()) {
324
+ if (isCtorOfSafePtr (Callee) && CE->getNumArgs () == 1 ) {
325
+ Arg = CE->getArg (0 )->IgnoreParenCasts ();
326
+ continue ;
327
+ }
328
+ }
313
329
}
314
330
if (auto *OpCE = dyn_cast<CXXOperatorCallExpr>(Arg)) {
315
331
auto OpCode = OpCE->getOperator ();
@@ -318,7 +334,7 @@ class RawPtrRefLambdaCapturesChecker
318
334
if (!Callee)
319
335
return false ;
320
336
auto clsName = safeGetName (Callee->getParent ());
321
- if (!isRefType (clsName) || !OpCE->getNumArgs ())
337
+ if (!Checker-> isPtrType (clsName) || !OpCE->getNumArgs ())
322
338
return false ;
323
339
Arg = OpCE->getArg (0 )->IgnoreParenCasts ();
324
340
continue ;
@@ -333,8 +349,15 @@ class RawPtrRefLambdaCapturesChecker
333
349
}
334
350
break ;
335
351
} 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
+ }
338
361
return isa<CXXThisExpr>(Arg);
339
362
}
340
363
};
@@ -354,10 +377,17 @@ class RawPtrRefLambdaCapturesChecker
354
377
ValueDecl *CapturedVar = C.getCapturedVar ();
355
378
if (ignoreParamVarDecl && isa<ParmVarDecl>(CapturedVar))
356
379
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
+ }
357
387
QualType CapturedVarQualType = CapturedVar->getType ();
358
388
auto IsUncountedPtr = isUnsafePtr (CapturedVar->getType ());
359
389
if (IsUncountedPtr && *IsUncountedPtr)
360
- reportBug (C, CapturedVar, CapturedVarQualType);
390
+ reportBug (C, CapturedVar, CapturedVarQualType, L );
361
391
} else if (C.capturesThis () && shouldCheckThis) {
362
392
if (ignoreParamVarDecl) // this is always a parameter to this function.
363
393
continue ;
@@ -367,11 +397,12 @@ class RawPtrRefLambdaCapturesChecker
367
397
}
368
398
369
399
void reportBug (const LambdaCapture &Capture, ValueDecl *CapturedVar,
370
- const QualType T) const {
400
+ const QualType T, LambdaExpr *L ) const {
371
401
assert (CapturedVar);
372
402
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 ();
375
406
376
407
SmallString<100 > Buf;
377
408
llvm::raw_svector_ostream Os (Buf);
@@ -390,7 +421,7 @@ class RawPtrRefLambdaCapturesChecker
390
421
printQuotedQualifiedName (Os, CapturedVar);
391
422
Os << " to " << ptrKind (T) << " type is unsafe." ;
392
423
393
- PathDiagnosticLocation BSLoc (Capture. getLocation () , BR->getSourceManager ());
424
+ PathDiagnosticLocation BSLoc (Location , BR->getSourceManager ());
394
425
auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
395
426
BR->emitReport (std::move (Report));
396
427
}
@@ -432,6 +463,10 @@ class UncountedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
432
463
return result2;
433
464
}
434
465
466
+ virtual bool isPtrType (const std::string &Name) const final {
467
+ return isRefType (Name) || isCheckedPtr (Name);
468
+ }
469
+
435
470
const char *ptrKind (QualType QT) const final {
436
471
if (isUncounted (QT))
437
472
return " uncounted" ;
@@ -451,6 +486,10 @@ class UnretainedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
451
486
return RTC->isUnretained (QT);
452
487
}
453
488
489
+ virtual bool isPtrType (const std::string &Name) const final {
490
+ return isRetainPtr (Name);
491
+ }
492
+
454
493
const char *ptrKind (QualType QT) const final { return " unretained" ; }
455
494
};
456
495
0 commit comments