Skip to content

Commit 1ad9666

Browse files
committed
address review comments.
1 parent 64e2c74 commit 1ad9666

File tree

2 files changed

+26
-24
lines changed

2 files changed

+26
-24
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ Improvements to Clang's diagnostics
298298

299299
- Clang now warns for u8 character literals used in C23 with ``-Wpre-c23-compat`` instead of ``-Wpre-c++17-compat``.
300300

301-
- Clang now diagnoses cases where a dangling ``GSLOwner<GSLPointer>`` object is constructed, e.g. `std::vector<string_view> v = {std::string()};` (#GH100526).
301+
- Clang now diagnoses cases where a dangling ``GSLOwner<GSLPointer>`` object is constructed, e.g. ``std::vector<string_view> v = {std::string()};`` (#GH100526).
302302

303303
Improvements to Clang's time-trace
304304
----------------------------------

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,26 @@ static bool isInStlNamespace(const Decl *D) {
267267
return DC->isStdNamespace();
268268
}
269269

270+
// Returns true if the given Record decl is a form of `GSLOwner<Pointer>`
271+
// type, e.g. std::vector<string_view>, std::optional<string_view>.
272+
static bool isContainerOfPointer(const RecordDecl *Container) {
273+
if (const auto *CTSD =
274+
dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
275+
if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
276+
return false;
277+
const auto &TAs = CTSD->getTemplateArgs();
278+
return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
279+
(isRecordWithAttr<PointerAttr>(TAs[0].getAsType()) ||
280+
TAs[0].getAsType()->isPointerType());
281+
}
282+
return false;
283+
}
284+
285+
static bool isGSLOwner(QualType T) {
286+
return isRecordWithAttr<OwnerAttr>(T) &&
287+
!isContainerOfPointer(T->getAsRecordDecl());
288+
}
289+
270290
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
271291
if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
272292
if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
@@ -275,7 +295,7 @@ static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
275295
return false;
276296
if (!isRecordWithAttr<PointerAttr>(
277297
Callee->getFunctionObjectParameterType()) &&
278-
!isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
298+
!isGSLOwner(Callee->getFunctionObjectParameterType()))
279299
return false;
280300
if (Callee->getReturnType()->isPointerType() ||
281301
isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
@@ -367,21 +387,6 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
367387
return isNormalAssignmentOperator(FD);
368388
}
369389

370-
// Returns true if the given Record decl is a form of `GSLOwner<Pointer>`
371-
// type, e.g. std::vector<string_view>, std::optional<string_view>.
372-
static bool isContainerOfPointer(const RecordDecl *Container) {
373-
if (const auto *CTSD =
374-
dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
375-
if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
376-
return false;
377-
const auto &TAs = CTSD->getTemplateArgs();
378-
return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
379-
(isRecordWithAttr<PointerAttr>(TAs[0].getAsType()) ||
380-
TAs[0].getAsType()->isPointerType());
381-
}
382-
return false;
383-
}
384-
385390
// Visit lifetimebound or gsl-pointer arguments.
386391
static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
387392
LocalVisitor Visit) {
@@ -428,7 +433,7 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
428433
// Once we initialized a value with a non gsl-owner reference, it can no
429434
// longer dangle.
430435
if (ReturnType->isReferenceType() &&
431-
!isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) {
436+
!isGSLOwner(ReturnType->getPointeeType())) {
432437
for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
433438
if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
434439
PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
@@ -483,6 +488,7 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
483488
if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
484489
VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
485490
else if (EnableGSLAnalysis && I == 0) {
491+
// Perform GSL analysis for the first argument
486492
if (shouldTrackFirstArgument(Callee)) {
487493
VisitGSLPointerArg(Callee, Args[0]);
488494
} else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Call)) {
@@ -1009,16 +1015,12 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
10091015
// int &p = *localUniquePtr;
10101016
// someContainer.add(std::move(localUniquePtr));
10111017
// return p;
1012-
IsLocalGslOwner =
1013-
isRecordWithAttr<OwnerAttr>(L->getType()) &&
1014-
!isContainerOfPointer(L->getType()->getAsRecordDecl());
1018+
IsLocalGslOwner = isGSLOwner(L->getType());
10151019
if (pathContainsInit(Path) || !IsLocalGslOwner)
10161020
return false;
10171021
} else {
10181022
IsGslPtrValueFromGslTempOwner =
1019-
MTE && !MTE->getExtendingDecl() &&
1020-
isRecordWithAttr<OwnerAttr>(MTE->getType()) &&
1021-
!isContainerOfPointer(MTE->getType()->getAsRecordDecl());
1023+
MTE && !MTE->getExtendingDecl() && isGSLOwner(MTE->getType());
10221024
// Skipping a chain of initializing gsl::Pointer annotated objects.
10231025
// We are looking only for the final source to find out if it was
10241026
// a local or temporary owner or the address of a local variable/param.

0 commit comments

Comments
 (0)