summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Horvath <xazax@google.com>2019-11-27 09:08:51 -0800
committerGabor Horvath <xazax@google.com>2019-11-27 09:15:14 -0800
commitbcd0798c47ca865f95226859893016a17402441e (patch)
treec9ed05e104eef062ab917ecaeba15dc286a41a9d
parent3d9b1128d609323dd4017250be0f6def94495205 (diff)
downloadbcm5719-llvm-bcd0798c47ca865f95226859893016a17402441e.tar.gz
bcm5719-llvm-bcd0798c47ca865f95226859893016a17402441e.zip
[LifetimeAnalysis] Fix PR44150
References need somewhat special treatment. While copying a gsl::Pointer will propagate the points-to set, creating an object from a reference often behaves more like a dereference operation. Differential Revision: https://reviews.llvm.org/D70755
-rw-r--r--clang/lib/Sema/SemaInit.cpp33
-rw-r--r--clang/test/Sema/warn-lifetime-analysis-nocfg.cpp5
2 files changed, 31 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 80d7cfed711..7421754d95c 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6653,6 +6653,7 @@ struct IndirectLocalPathEntry {
VarInit,
LValToRVal,
LifetimeBoundCall,
+ GslReferenceInit,
GslPointerInit
} Kind;
Expr *E;
@@ -6783,12 +6784,24 @@ static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
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<MemberExpr>(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 @@ static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
if (MD && shouldTrackImplicitObjectArg(MD))
- VisitPointerArg(MD, MCE->getImplicitObjectArgument());
+ VisitPointerArg(MD, MCE->getImplicitObjectArgument(),
+ !MD->getReturnType()->isReferenceType());
return;
} else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
FunctionDecl *Callee = OCE->getDirectCallee();
if (Callee && Callee->isCXXInstanceMember() &&
shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
- VisitPointerArg(Callee, OCE->getArg(0));
+ VisitPointerArg(Callee, OCE->getArg(0),
+ !Callee->getReturnType()->isReferenceType());
return;
} else if (auto *CE = dyn_cast<CallExpr>(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 @@ static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
const auto *Ctor = CCE->getConstructor();
const CXXRecordDecl *RD = Ctor->getParent();
if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())
- VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0]);
+ VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0], true);
}
}
@@ -7287,6 +7303,7 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
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 @@ static bool pathOnlyInitializesGslPointer(IndirectLocalPath &Path) {
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 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
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
index 8ba76869444..3319d5aa2db 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -450,3 +450,8 @@ MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) {
MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) {
return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}}
}
+
+std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() {
+ std::vector<std::vector<int>::iterator> iters;
+ return iters.at(0);
+}
OpenPOWER on IntegriCloud