@@ -267,6 +267,26 @@ static bool isInStlNamespace(const Decl *D) {
267
267
return DC->isStdNamespace ();
268
268
}
269
269
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
+
270
290
static bool shouldTrackImplicitObjectArg (const CXXMethodDecl *Callee) {
271
291
if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
272
292
if (isRecordWithAttr<PointerAttr>(Conv->getConversionType ()))
@@ -275,7 +295,7 @@ static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
275
295
return false ;
276
296
if (!isRecordWithAttr<PointerAttr>(
277
297
Callee->getFunctionObjectParameterType ()) &&
278
- !isRecordWithAttr<OwnerAttr> (Callee->getFunctionObjectParameterType ()))
298
+ !isGSLOwner (Callee->getFunctionObjectParameterType ()))
279
299
return false ;
280
300
if (Callee->getReturnType ()->isPointerType () ||
281
301
isRecordWithAttr<PointerAttr>(Callee->getReturnType ())) {
@@ -367,21 +387,6 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
367
387
return isNormalAssignmentOperator (FD);
368
388
}
369
389
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
-
385
390
// Visit lifetimebound or gsl-pointer arguments.
386
391
static void visitFunctionCallArguments (IndirectLocalPath &Path, Expr *Call,
387
392
LocalVisitor Visit) {
@@ -428,7 +433,7 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
428
433
// Once we initialized a value with a non gsl-owner reference, it can no
429
434
// longer dangle.
430
435
if (ReturnType->isReferenceType () &&
431
- !isRecordWithAttr<OwnerAttr> (ReturnType->getPointeeType ())) {
436
+ !isGSLOwner (ReturnType->getPointeeType ())) {
432
437
for (const IndirectLocalPathEntry &PE : llvm::reverse (Path)) {
433
438
if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
434
439
PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
@@ -483,6 +488,7 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
483
488
if (CheckCoroCall || Callee->getParamDecl (I)->hasAttr <LifetimeBoundAttr>())
484
489
VisitLifetimeBoundArg (Callee->getParamDecl (I), Args[I]);
485
490
else if (EnableGSLAnalysis && I == 0 ) {
491
+ // Perform GSL analysis for the first argument
486
492
if (shouldTrackFirstArgument (Callee)) {
487
493
VisitGSLPointerArg (Callee, Args[0 ]);
488
494
} else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Call)) {
@@ -1009,16 +1015,12 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
1009
1015
// int &p = *localUniquePtr;
1010
1016
// someContainer.add(std::move(localUniquePtr));
1011
1017
// return p;
1012
- IsLocalGslOwner =
1013
- isRecordWithAttr<OwnerAttr>(L->getType ()) &&
1014
- !isContainerOfPointer (L->getType ()->getAsRecordDecl ());
1018
+ IsLocalGslOwner = isGSLOwner (L->getType ());
1015
1019
if (pathContainsInit (Path) || !IsLocalGslOwner)
1016
1020
return false ;
1017
1021
} else {
1018
1022
IsGslPtrValueFromGslTempOwner =
1019
- MTE && !MTE->getExtendingDecl () &&
1020
- isRecordWithAttr<OwnerAttr>(MTE->getType ()) &&
1021
- !isContainerOfPointer (MTE->getType ()->getAsRecordDecl ());
1023
+ MTE && !MTE->getExtendingDecl () && isGSLOwner (MTE->getType ());
1022
1024
// Skipping a chain of initializing gsl::Pointer annotated objects.
1023
1025
// We are looking only for the final source to find out if it was
1024
1026
// a local or temporary owner or the address of a local variable/param.
0 commit comments