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