Skip to content

Commit a918fa1

Browse files
authored
[clang] Emit -Wdangling diagnoses for cases where a gsl-pointer is construct from a gsl-owner object in a container. (llvm#104556)
The warning is not emitted for the case `string_view c = std::vector<std::string>({""}).at(0);` because we bail out during the visit of the LHS at [this point](https://github.com/llvm/llvm-project/blob/5d2c324fea2d7cf86ec50e4bb6b680acf89b2ed5/clang/lib/Sema/CheckExprLifetime.cpp#L341-L343) in the code. This bailout was introduced in [this commit](llvm@bcd0798) to address a false positive with `vector<vector::iterator>({""}).at(0);`. This PR refines that fix by ensuring that, for initialization involving a gsl-pointer, we only consider constructor calls that take the gsl-owner object. Fixes llvm#100384.
1 parent 50be4f1 commit a918fa1

File tree

3 files changed

+44
-12
lines changed

3 files changed

+44
-12
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ Improvements to Clang's diagnostics
288288
- The lifetimebound and GSL analysis in clang are coherent, allowing clang to
289289
detect more use-after-free bugs. (#GH100549).
290290

291+
- Clang now diagnoses dangling cases where a gsl-pointer is constructed from a gsl-owner object inside a container (#GH100384).
292+
291293
- Clang now warns for u8 character literals used in C23 with ``-Wpre-c23-compat`` instead of ``-Wpre-c++17-compat``.
292294

293295
Improvements to Clang's time-trace

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -403,13 +403,17 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
403403
visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
404404
Path.pop_back();
405405
};
406-
auto VisitGSLPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {
406+
auto VisitGSLPointerArg = [&](const FunctionDecl *Callee, Expr *Arg) {
407407
// We are not interested in the temporary base objects of gsl Pointers:
408408
// Temp().ptr; // Here ptr might not dangle.
409409
if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
410410
return;
411-
// Once we initialized a value with a reference, it can no longer dangle.
412-
if (!Value) {
411+
auto ReturnType = Callee->getReturnType();
412+
413+
// Once we initialized a value with a non gsl-owner reference, it can no
414+
// longer dangle.
415+
if (ReturnType->isReferenceType() &&
416+
!isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) {
413417
for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
414418
if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
415419
PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
@@ -420,9 +424,10 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
420424
break;
421425
}
422426
}
423-
Path.push_back({Value ? IndirectLocalPathEntry::GslPointerInit
424-
: IndirectLocalPathEntry::GslReferenceInit,
425-
Arg, D});
427+
Path.push_back({ReturnType->isReferenceType()
428+
? IndirectLocalPathEntry::GslReferenceInit
429+
: IndirectLocalPathEntry::GslPointerInit,
430+
Arg, Callee});
426431
if (Arg->isGLValue())
427432
visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
428433
Visit);
@@ -453,8 +458,7 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
453458
else if (EnableGSLAnalysis) {
454459
if (auto *CME = dyn_cast<CXXMethodDecl>(Callee);
455460
CME && shouldTrackImplicitObjectArg(CME))
456-
VisitGSLPointerArg(Callee, ObjectArg,
457-
!Callee->getReturnType()->isReferenceType());
461+
VisitGSLPointerArg(Callee, ObjectArg);
458462
}
459463
}
460464

@@ -465,13 +469,11 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
465469
VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
466470
else if (EnableGSLAnalysis && I == 0) {
467471
if (shouldTrackFirstArgument(Callee)) {
468-
VisitGSLPointerArg(Callee, Args[0],
469-
!Callee->getReturnType()->isReferenceType());
472+
VisitGSLPointerArg(Callee, Args[0]);
470473
} else if (auto *CCE = dyn_cast<CXXConstructExpr>(Call);
471474
CCE &&
472475
CCE->getConstructor()->getParent()->hasAttr<PointerAttr>()) {
473-
VisitGSLPointerArg(CCE->getConstructor()->getParamDecl(0), Args[0],
474-
true);
476+
VisitGSLPointerArg(CCE->getConstructor(), Args[0]);
475477
}
476478
}
477479
}

clang/test/Sema/warn-lifetime-analysis-nocfg.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,34 @@ int &danglingRawPtrFromLocal3() {
275275
return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
276276
}
277277

278+
// GH100384
279+
std::string_view containerWithAnnotatedElements() {
280+
std::string_view c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
281+
c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer}}
282+
283+
// no warning on constructing from gsl-pointer
284+
std::string_view c2 = std::vector<std::string_view>().at(0);
285+
286+
std::vector<std::string> local;
287+
return local.at(0); // expected-warning {{address of stack memory associated with local variable}}
288+
}
289+
290+
std::string_view localUniquePtr(int i) {
291+
std::unique_ptr<std::string> c1;
292+
if (i)
293+
return *c1; // expected-warning {{address of stack memory associated with local variable}}
294+
std::unique_ptr<std::string_view> c2;
295+
return *c2; // expect no-warning.
296+
}
297+
298+
std::string_view localOptional(int i) {
299+
std::optional<std::string> o;
300+
if (i)
301+
return o.value(); // expected-warning {{address of stack memory associated with local variable}}
302+
std::optional<std::string_view> abc;
303+
return abc.value(); // expect no warning
304+
}
305+
278306
const char *danglingRawPtrFromTemp() {
279307
return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}}
280308
}

0 commit comments

Comments
 (0)