@@ -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,34 @@ 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
+ };
461
431
462
432
bool CheckCoroCall = false ;
463
433
if (const auto *RD = Callee->getReturnType ()->getAsRecordDecl ()) {
@@ -478,13 +448,30 @@ static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
478
448
CheckCoroObjArg = false ;
479
449
if (implicitObjectParamIsLifetimeBound (Callee) || CheckCoroObjArg)
480
450
VisitLifetimeBoundArg (Callee, ObjectArg);
451
+ else if (EnableLifetimeWarnings) {
452
+ if (auto *CME = dyn_cast<CXXMethodDecl>(Callee);
453
+ CME && shouldTrackImplicitObjectArg (CME))
454
+ VisitGSLPointerArg (Callee, ObjectArg,
455
+ !Callee->getReturnType ()->isReferenceType ());
456
+ }
481
457
}
482
458
483
459
for (unsigned I = 0 ,
484
460
N = std::min<unsigned >(Callee->getNumParams (), Args.size ());
485
461
I != N; ++I) {
486
462
if (CheckCoroCall || Callee->getParamDecl (I)->hasAttr <LifetimeBoundAttr>())
487
463
VisitLifetimeBoundArg (Callee->getParamDecl (I), Args[I]);
464
+ else if (EnableLifetimeWarnings && I == 0 ) {
465
+ if (shouldTrackFirstArgument (Callee)) {
466
+ VisitGSLPointerArg (Callee, Args[0 ],
467
+ !Callee->getReturnType ()->isReferenceType ());
468
+ } else {
469
+ if (auto *CCE = dyn_cast<CXXConstructExpr>(Call);
470
+ CCE && CCE->getConstructor ()->getParent ()->hasAttr <PointerAttr>())
471
+ VisitGSLPointerArg (CCE->getConstructor ()->getParamDecl (0 ), Args[0 ],
472
+ true );
473
+ }
474
+ }
488
475
}
489
476
}
490
477
@@ -557,11 +544,9 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
557
544
EnableLifetimeWarnings);
558
545
}
559
546
560
- if (isa<CallExpr>(Init)) {
561
- if (EnableLifetimeWarnings)
562
- handleGslAnnotatedTypes (Path, Init, Visit);
563
- return visitLifetimeBoundArguments (Path, Init, Visit);
564
- }
547
+ if (isa<CallExpr>(Init))
548
+ return visitFunctionCallArguments (Path, Init, Visit,
549
+ EnableLifetimeWarnings);
565
550
566
551
switch (Init->getStmtClass ()) {
567
552
case Stmt::DeclRefExprClass: {
@@ -835,11 +820,9 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
835
820
}
836
821
}
837
822
838
- if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {
839
- if (EnableLifetimeWarnings)
840
- handleGslAnnotatedTypes (Path, Init, Visit);
841
- return visitLifetimeBoundArguments (Path, Init, Visit);
842
- }
823
+ if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init))
824
+ return visitFunctionCallArguments (Path, Init, Visit,
825
+ EnableLifetimeWarnings);
843
826
844
827
switch (Init->getStmtClass ()) {
845
828
case Stmt::UnaryOperatorClass: {
0 commit comments