diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6653,6 +6653,7 @@ VarInit, LValToRVal, LifetimeBoundCall, + GslReferenceInit, GslPointerInit } Kind; Expr *E; @@ -6783,12 +6784,24 @@ static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit) { - auto VisitPointerArg = [&](const Decl *D, Expr *Arg) { + auto VisitPointerArg = [&](const Decl *D, Expr *Arg, bool Value) { // We are not interested in the temporary base objects of gsl Pointers: // Temp().ptr; // Here ptr might not dangle. if (isa(Arg->IgnoreImpCasts())) return; - Path.push_back({IndirectLocalPathEntry::GslPointerInit, Arg, D}); + // Once we initialized a value with a reference, it can no longer dangle. + if (!Value) { + for (auto It = Path.rbegin(), End = Path.rend(); It != End; ++It) { + if (It->Kind == IndirectLocalPathEntry::GslReferenceInit) + continue; + if (It->Kind == IndirectLocalPathEntry::GslPointerInit) + return; + break; + } + } + Path.push_back({Value ? IndirectLocalPathEntry::GslPointerInit + : IndirectLocalPathEntry::GslReferenceInit, + Arg, D}); if (Arg->isGLValue()) visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding, Visit, @@ -6802,18 +6815,21 @@ if (auto *MCE = dyn_cast(Call)) { const auto *MD = cast_or_null(MCE->getDirectCallee()); if (MD && shouldTrackImplicitObjectArg(MD)) - VisitPointerArg(MD, MCE->getImplicitObjectArgument()); + VisitPointerArg(MD, MCE->getImplicitObjectArgument(), + !MD->getReturnType()->isReferenceType()); return; } else if (auto *OCE = dyn_cast(Call)) { FunctionDecl *Callee = OCE->getDirectCallee(); if (Callee && Callee->isCXXInstanceMember() && shouldTrackImplicitObjectArg(cast(Callee))) - VisitPointerArg(Callee, OCE->getArg(0)); + VisitPointerArg(Callee, OCE->getArg(0), + !Callee->getReturnType()->isReferenceType()); return; } else if (auto *CE = dyn_cast(Call)) { FunctionDecl *Callee = CE->getDirectCallee(); if (Callee && shouldTrackFirstArgument(Callee)) - VisitPointerArg(Callee, CE->getArg(0)); + VisitPointerArg(Callee, CE->getArg(0), + !Callee->getReturnType()->isReferenceType()); return; } @@ -6821,7 +6837,7 @@ const auto *Ctor = CCE->getConstructor(); const CXXRecordDecl *RD = Ctor->getParent(); if (CCE->getNumArgs() > 0 && RD->hasAttr()) - VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0]); + VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0], true); } } @@ -7287,6 +7303,7 @@ case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: case IndirectLocalPathEntry::LifetimeBoundCall: + case IndirectLocalPathEntry::GslReferenceInit: case IndirectLocalPathEntry::GslPointerInit: // These exist primarily to mark the path as not permitting or // supporting lifetime extension. @@ -7309,7 +7326,8 @@ continue; if (It->Kind == IndirectLocalPathEntry::AddressOf) continue; - return It->Kind == IndirectLocalPathEntry::GslPointerInit; + return It->Kind == IndirectLocalPathEntry::GslPointerInit || + It->Kind == IndirectLocalPathEntry::GslReferenceInit; } return false; } @@ -7532,6 +7550,7 @@ case IndirectLocalPathEntry::LifetimeBoundCall: case IndirectLocalPathEntry::GslPointerInit: + case IndirectLocalPathEntry::GslReferenceInit: // FIXME: Consider adding a note for these. break; diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp --- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp @@ -450,3 +450,8 @@ MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) { return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}} } + +std::vector::iterator noFalsePositiveWithVectorOfPointers() { + std::vector::iterator> iters; + return iters.at(0); +}