@@ -298,11 +298,6 @@ static bool isStdInitializerListOfPointer(const RecordDecl *RD) {
298
298
return false ;
299
299
}
300
300
301
- static bool isGSLOwner (QualType T) {
302
- return isRecordWithAttr<OwnerAttr>(T) &&
303
- !isContainerOfPointer (T->getAsRecordDecl ());
304
- }
305
-
306
301
static bool shouldTrackImplicitObjectArg (const CXXMethodDecl *Callee) {
307
302
if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
308
303
if (isRecordWithAttr<PointerAttr>(Conv->getConversionType ()) &&
@@ -312,7 +307,7 @@ static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
312
307
return false ;
313
308
if (!isRecordWithAttr<PointerAttr>(
314
309
Callee->getFunctionObjectParameterType ()) &&
315
- !isGSLOwner (Callee->getFunctionObjectParameterType ()))
310
+ !isRecordWithAttr<OwnerAttr> (Callee->getFunctionObjectParameterType ()))
316
311
return false ;
317
312
if (isPointerLikeType (Callee->getReturnType ())) {
318
313
if (!Callee->getIdentifier ())
@@ -368,22 +363,29 @@ static bool
368
363
shouldTrackFirstArgumentForConstructor (const CXXConstructExpr *Ctor) {
369
364
const auto *ClassD = Ctor->getConstructor ()->getParent ();
370
365
371
- auto FirstArgType = Ctor->getArg (0 )->getType ();
372
366
// Case 1, construct a GSL pointer, e.g. std::string_view
373
367
if (ClassD->hasAttr <PointerAttr>())
374
368
return true ;
375
369
376
- // case 2: construct a container of pointer (std::vector<std::string_view>)
377
- // from an owner or a std::initilizer_list.
378
- //
379
- // std::initializer_list is a proxy object that provides access to the backing
380
- // array. We perform analysis on it to determine if there are any dangling
381
- // temporaries in the backing array.
370
+ auto FirstArgType = Ctor->getArg (0 )->getType ();
371
+ // Case 2, construct a container of pointer (std::vector<std::string_view>)
372
+ // from a std::initilizer_list or an GSL owner
382
373
if (Ctor->getConstructor ()->getNumParams () != 1 ||
383
374
!isContainerOfPointer (ClassD))
384
375
return false ;
385
- return isGSLOwner (FirstArgType) ||
386
- isStdInitializerListOfPointer (FirstArgType->getAsRecordDecl ());
376
+
377
+ // For the typical case: `std::vector<std::string_view> abc = {std::string()};`
378
+ // std::initializer_list is a proxy object that provides access to the backing
379
+ // array. We perform analysis on it to determine if there are any dangling
380
+ // temporaries in the backing array.
381
+ if (isStdInitializerListOfPointer (FirstArgType->getAsRecordDecl ()))
382
+ return true ;
383
+ // For the case: `std::optional<std::string_view> abc = std::string();`
384
+ // When constructing from a container of pointers, it's less likely to result
385
+ // in a dangling pointer. Therefore, we try to be conservative to not track
386
+ // the argument futher to avoid false positives.
387
+ return isRecordWithAttr<OwnerAttr>(FirstArgType) &&
388
+ !isContainerOfPointer (FirstArgType->getAsRecordDecl ());
387
389
}
388
390
389
391
// Return true if this is an "normal" assignment operator.
@@ -473,7 +475,7 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
473
475
// Once we initialized a value with a non gsl-owner reference, it can no
474
476
// longer dangle.
475
477
if (ReturnType->isReferenceType () &&
476
- !isGSLOwner (ReturnType->getPointeeType ())) {
478
+ !isRecordWithAttr<OwnerAttr> (ReturnType->getPointeeType ())) {
477
479
for (const IndirectLocalPathEntry &PE : llvm::reverse (Path)) {
478
480
if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
479
481
PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
@@ -1045,12 +1047,13 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
1045
1047
// int &p = *localUniquePtr;
1046
1048
// someContainer.add(std::move(localUniquePtr));
1047
1049
// return p;
1048
- IsLocalGslOwner = isGSLOwner (L->getType ());
1050
+ IsLocalGslOwner = isRecordWithAttr<OwnerAttr> (L->getType ());
1049
1051
if (pathContainsInit (Path) || !IsLocalGslOwner)
1050
1052
return false ;
1051
1053
} else {
1052
1054
IsGslPtrValueFromGslTempOwner =
1053
- MTE && !MTE->getExtendingDecl () && isGSLOwner (MTE->getType ());
1055
+ MTE && !MTE->getExtendingDecl () &&
1056
+ isRecordWithAttr<OwnerAttr>(MTE->getType ());
1054
1057
// Skipping a chain of initializing gsl::Pointer annotated objects.
1055
1058
// We are looking only for the final source to find out if it was
1056
1059
// a local or temporary owner or the address of a local variable/param.
0 commit comments