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