@@ -326,66 +326,6 @@ static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
326
326
return false ;
327
327
}
328
328
329
- static void handleGslAnnotatedTypes (IndirectLocalPath &Path, Expr *Call,
330
- LocalVisitor Visit) {
331
- auto VisitPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {
332
- // We are not interested in the temporary base objects of gsl Pointers:
333
- // Temp().ptr; // Here ptr might not dangle.
334
- if (isa<MemberExpr>(Arg->IgnoreImpCasts ()))
335
- return ;
336
- // Once we initialized a value with a reference, it can no longer dangle.
337
- if (!Value) {
338
- for (const IndirectLocalPathEntry &PE : llvm::reverse (Path)) {
339
- if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)
340
- continue ;
341
- if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
342
- PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
343
- return ;
344
- break ;
345
- }
346
- }
347
- Path.push_back ({Value ? IndirectLocalPathEntry::GslPointerInit
348
- : IndirectLocalPathEntry::GslReferenceInit,
349
- Arg, D});
350
- if (Arg->isGLValue ())
351
- visitLocalsRetainedByReferenceBinding (Path, Arg, RK_ReferenceBinding,
352
- Visit,
353
- /* EnableLifetimeWarnings=*/ true );
354
- else
355
- visitLocalsRetainedByInitializer (Path, Arg, Visit, true ,
356
- /* EnableLifetimeWarnings=*/ true );
357
- Path.pop_back ();
358
- };
359
-
360
- if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
361
- const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee ());
362
- if (MD && shouldTrackImplicitObjectArg (MD))
363
- VisitPointerArg (MD, MCE->getImplicitObjectArgument (),
364
- !MD->getReturnType ()->isReferenceType ());
365
- return ;
366
- } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
367
- FunctionDecl *Callee = OCE->getDirectCallee ();
368
- if (Callee && Callee->isCXXInstanceMember () &&
369
- shouldTrackImplicitObjectArg (cast<CXXMethodDecl>(Callee)))
370
- VisitPointerArg (Callee, OCE->getArg (0 ),
371
- !Callee->getReturnType ()->isReferenceType ());
372
- return ;
373
- } else if (auto *CE = dyn_cast<CallExpr>(Call)) {
374
- FunctionDecl *Callee = CE->getDirectCallee ();
375
- if (Callee && shouldTrackFirstArgument (Callee))
376
- VisitPointerArg (Callee, CE->getArg (0 ),
377
- !Callee->getReturnType ()->isReferenceType ());
378
- return ;
379
- }
380
-
381
- if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
382
- const auto *Ctor = CCE->getConstructor ();
383
- const CXXRecordDecl *RD = Ctor->getParent ();
384
- if (CCE->getNumArgs () > 0 && RD->hasAttr <PointerAttr>())
385
- VisitPointerArg (Ctor->getParamDecl (0 ), CCE->getArgs ()[0 ], true );
386
- }
387
- }
388
-
389
329
static bool implicitObjectParamIsLifetimeBound (const FunctionDecl *FD) {
390
330
const TypeSourceInfo *TSI = FD->getTypeSourceInfo ();
391
331
if (!TSI)
@@ -423,8 +363,10 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
423
363
return false ;
424
364
}
425
365
426
- static void visitLifetimeBoundArguments (IndirectLocalPath &Path, Expr *Call,
427
- LocalVisitor Visit) {
366
+ // Visit lifetimebound or gsl-pointer arguments.
367
+ static void visitFunctionCallArguments (IndirectLocalPath &Path, Expr *Call,
368
+ LocalVisitor Visit,
369
+ bool EnableLifetimeWarnings) {
428
370
const FunctionDecl *Callee;
429
371
ArrayRef<Expr *> Args;
430
372
@@ -458,6 +400,35 @@ static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
458
400
/* EnableLifetimeWarnings=*/ false );
459
401
Path.pop_back ();
460
402
};
403
+ auto VisitGSLPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {
404
+ // We are not interested in the temporary base objects of gsl Pointers:
405
+ // Temp().ptr; // Here ptr might not dangle.
406
+ if (isa<MemberExpr>(Arg->IgnoreImpCasts ()))
407
+ return ;
408
+ // Once we initialized a value with a reference, it can no longer dangle.
409
+ if (!Value) {
410
+ for (const IndirectLocalPathEntry &PE : llvm::reverse (Path)) {
411
+ if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)
412
+ continue ;
413
+ if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
414
+ PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
415
+ return ;
416
+ break ;
417
+ }
418
+ }
419
+ Path.push_back ({Value ? IndirectLocalPathEntry::GslPointerInit
420
+ : IndirectLocalPathEntry::GslReferenceInit,
421
+ Arg, D});
422
+ if (Arg->isGLValue ())
423
+ visitLocalsRetainedByReferenceBinding (Path, Arg, RK_ReferenceBinding,
424
+ Visit,
425
+ /* EnableLifetimeWarnings=*/ true );
426
+ else
427
+ visitLocalsRetainedByInitializer (Path, Arg, Visit, true ,
428
+ /* EnableLifetimeWarnings=*/ true );
429
+ Path.pop_back ();
430
+ };
431
+
461
432
462
433
bool CheckCoroCall = false ;
463
434
if (const auto *RD = Callee->getReturnType ()->getAsRecordDecl ()) {
@@ -478,13 +449,32 @@ static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
478
449
CheckCoroObjArg = false ;
479
450
if (implicitObjectParamIsLifetimeBound (Callee) || CheckCoroObjArg)
480
451
VisitLifetimeBoundArg (Callee, ObjectArg);
452
+ else if (EnableLifetimeWarnings) {
453
+ if (auto *CME = dyn_cast<CXXMethodDecl>(Callee);
454
+ CME && shouldTrackImplicitObjectArg (CME))
455
+ VisitGSLPointerArg (Callee, ObjectArg,
456
+ !Callee->getReturnType ()->isReferenceType ());
457
+ }
481
458
}
482
459
483
460
for (unsigned I = 0 ,
484
461
N = std::min<unsigned >(Callee->getNumParams (), Args.size ());
485
462
I != N; ++I) {
486
463
if (CheckCoroCall || Callee->getParamDecl (I)->hasAttr <LifetimeBoundAttr>())
487
464
VisitLifetimeBoundArg (Callee->getParamDecl (I), Args[I]);
465
+ else if (EnableLifetimeWarnings) {
466
+ if (I == 0 ) {
467
+ if (shouldTrackFirstArgument (Callee)) { // gsl
468
+ VisitGSLPointerArg (Callee, Args[0 ],
469
+ !Callee->getReturnType ()->isReferenceType ());
470
+ } else {
471
+ if (auto *CCE = dyn_cast<CXXConstructExpr>(Call);
472
+ CCE && CCE->getConstructor ()->getParent ()->hasAttr <PointerAttr>())
473
+ VisitGSLPointerArg (CCE->getConstructor ()->getParamDecl (0 ), Args[0 ],
474
+ true );
475
+ }
476
+ }
477
+ }
488
478
}
489
479
}
490
480
@@ -557,11 +547,9 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
557
547
EnableLifetimeWarnings);
558
548
}
559
549
560
- if (isa<CallExpr>(Init)) {
561
- if (EnableLifetimeWarnings)
562
- handleGslAnnotatedTypes (Path, Init, Visit);
563
- return visitLifetimeBoundArguments (Path, Init, Visit);
564
- }
550
+ if (isa<CallExpr>(Init))
551
+ return visitFunctionCallArguments (Path, Init, Visit,
552
+ EnableLifetimeWarnings);
565
553
566
554
switch (Init->getStmtClass ()) {
567
555
case Stmt::DeclRefExprClass: {
@@ -835,11 +823,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
835
823
}
836
824
}
837
825
838
- if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {
839
- if (EnableLifetimeWarnings)
840
- handleGslAnnotatedTypes (Path, Init, Visit);
841
- return visitLifetimeBoundArguments (Path, Init, Visit);
842
- }
826
+ if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init))
827
+ return visitFunctionCallArguments (Path, Init, Visit, EnableLifetimeWarnings);
843
828
844
829
switch (Init->getStmtClass ()) {
845
830
case Stmt::UnaryOperatorClass: {
0 commit comments