@@ -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,
@@ -68,6 +69,15 @@ class RawPtrRefLambdaCapturesChecker
68
69
return DynamicRecursiveASTVisitor::TraverseCXXMethodDecl (CXXMD);
69
70
}
70
71
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
+
71
81
bool VisitTypedefDecl (TypedefDecl *TD) override {
72
82
if (Checker->RTC )
73
83
Checker->RTC ->visitTypedef (TD);
@@ -275,10 +285,10 @@ class RawPtrRefLambdaCapturesChecker
275
285
auto *VD = dyn_cast<VarDecl>(ValueDecl);
276
286
if (!VD)
277
287
return false ;
278
- auto *Init = VD->getInit ()-> IgnoreParenCasts () ;
288
+ auto *Init = VD->getInit ();
279
289
if (!Init)
280
290
return false ;
281
- const Expr *Arg = Init;
291
+ const Expr *Arg = Init-> IgnoreParenCasts () ;
282
292
do {
283
293
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg))
284
294
Arg = BTE->getSubExpr ()->IgnoreParenCasts ();
@@ -287,7 +297,7 @@ class RawPtrRefLambdaCapturesChecker
287
297
if (!Ctor)
288
298
return false ;
289
299
auto clsName = safeGetName (Ctor->getParent ());
290
- if (isRefType (clsName) && CE->getNumArgs ()) {
300
+ if (Checker-> isPtrType (clsName) && CE->getNumArgs ()) {
291
301
Arg = CE->getArg (0 )->IgnoreParenCasts ();
292
302
continue ;
293
303
}
@@ -307,6 +317,12 @@ class RawPtrRefLambdaCapturesChecker
307
317
Arg = CE->getArg (0 )->IgnoreParenCasts ();
308
318
continue ;
309
319
}
320
+ if (auto *Callee = CE->getDirectCallee ()) {
321
+ if (isCtorOfSafePtr (Callee) && CE->getNumArgs () == 1 ) {
322
+ Arg = CE->getArg (0 )->IgnoreParenCasts ();
323
+ continue ;
324
+ }
325
+ }
310
326
}
311
327
if (auto *OpCE = dyn_cast<CXXOperatorCallExpr>(Arg)) {
312
328
auto OpCode = OpCE->getOperator ();
@@ -315,7 +331,7 @@ class RawPtrRefLambdaCapturesChecker
315
331
if (!Callee)
316
332
return false ;
317
333
auto clsName = safeGetName (Callee->getParent ());
318
- if (!isRefType (clsName) || !OpCE->getNumArgs ())
334
+ if (!Checker-> isPtrType (clsName) || !OpCE->getNumArgs ())
319
335
return false ;
320
336
Arg = OpCE->getArg (0 )->IgnoreParenCasts ();
321
337
continue ;
@@ -330,8 +346,15 @@ class RawPtrRefLambdaCapturesChecker
330
346
}
331
347
break ;
332
348
} 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
+ }
335
358
return isa<CXXThisExpr>(Arg);
336
359
}
337
360
};
@@ -351,10 +374,17 @@ class RawPtrRefLambdaCapturesChecker
351
374
ValueDecl *CapturedVar = C.getCapturedVar ();
352
375
if (ignoreParamVarDecl && isa<ParmVarDecl>(CapturedVar))
353
376
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
+ }
354
384
QualType CapturedVarQualType = CapturedVar->getType ();
355
385
auto IsUncountedPtr = isUnsafePtr (CapturedVar->getType ());
356
386
if (IsUncountedPtr && *IsUncountedPtr)
357
- reportBug (C, CapturedVar, CapturedVarQualType);
387
+ reportBug (C, CapturedVar, CapturedVarQualType, L );
358
388
} else if (C.capturesThis () && shouldCheckThis) {
359
389
if (ignoreParamVarDecl) // this is always a parameter to this function.
360
390
continue ;
@@ -364,11 +394,12 @@ class RawPtrRefLambdaCapturesChecker
364
394
}
365
395
366
396
void reportBug (const LambdaCapture &Capture, ValueDecl *CapturedVar,
367
- const QualType T) const {
397
+ const QualType T, LambdaExpr *L ) const {
368
398
assert (CapturedVar);
369
399
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 ();
372
403
373
404
SmallString<100 > Buf;
374
405
llvm::raw_svector_ostream Os (Buf);
@@ -387,7 +418,7 @@ class RawPtrRefLambdaCapturesChecker
387
418
printQuotedQualifiedName (Os, CapturedVar);
388
419
Os << " to " << ptrKind (T) << " type is unsafe." ;
389
420
390
- PathDiagnosticLocation BSLoc (Capture. getLocation () , BR->getSourceManager ());
421
+ PathDiagnosticLocation BSLoc (Location , BR->getSourceManager ());
391
422
auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
392
423
BR->emitReport (std::move (Report));
393
424
}
@@ -429,6 +460,10 @@ class UncountedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
429
460
return result2;
430
461
}
431
462
463
+ virtual bool isPtrType (const std::string &Name) const final {
464
+ return isRefType (Name) || isCheckedPtr (Name);
465
+ }
466
+
432
467
const char *ptrKind (QualType QT) const final {
433
468
if (isUncounted (QT))
434
469
return " uncounted" ;
@@ -448,6 +483,10 @@ class UnretainedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
448
483
return RTC->isUnretained (QT);
449
484
}
450
485
486
+ virtual bool isPtrType (const std::string &Name) const final {
487
+ return isRetainPtr (Name);
488
+ }
489
+
451
490
const char *ptrKind (QualType QT) const final { return " unretained" ; }
452
491
};
453
492
0 commit comments