@@ -326,24 +326,11 @@ static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
326
326
return false ;
327
327
}
328
328
329
- static bool implicitObjectParamIsLifetimeBound (const FunctionDecl *FD) {
330
- const TypeSourceInfo *TSI = FD->getTypeSourceInfo ();
331
- if (!TSI)
332
- return false ;
333
- // Don't declare this variable in the second operand of the for-statement;
334
- // GCC miscompiles that by ending its lifetime before evaluating the
335
- // third operand. See gcc.gnu.org/PR86769.
336
- AttributedTypeLoc ATL;
337
- for (TypeLoc TL = TSI->getTypeLoc ();
338
- (ATL = TL.getAsAdjusted <AttributedTypeLoc>());
339
- TL = ATL.getModifiedLoc ()) {
340
- if (ATL.getAttrAs <LifetimeBoundAttr>())
341
- return true ;
342
- }
343
-
344
- // Assume that all assignment operators with a "normal" return type return
345
- // *this, that is, an lvalue reference that is the same type as the implicit
346
- // object parameter (or the LHS for a non-member operator$=).
329
+ // Return true if this is an "normal" assignment operator.
330
+ // We assuments that a normal assingment operator always returns *this, that is,
331
+ // an lvalue reference that is the same type as the implicit object parameter
332
+ // (or the LHS for a non-member operator$=).
333
+ static bool isNormalAsisgnmentOperator (const FunctionDecl *FD) {
347
334
OverloadedOperatorKind OO = FD->getDeclName ().getCXXOverloadedOperator ();
348
335
if (OO == OO_Equal || isCompoundAssignmentOperator (OO)) {
349
336
QualType RetT = FD->getReturnType ();
@@ -359,10 +346,27 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
359
346
return true ;
360
347
}
361
348
}
362
-
363
349
return false ;
364
350
}
365
351
352
+ static bool implicitObjectParamIsLifetimeBound (const FunctionDecl *FD) {
353
+ const TypeSourceInfo *TSI = FD->getTypeSourceInfo ();
354
+ if (!TSI)
355
+ return false ;
356
+ // Don't declare this variable in the second operand of the for-statement;
357
+ // GCC miscompiles that by ending its lifetime before evaluating the
358
+ // third operand. See gcc.gnu.org/PR86769.
359
+ AttributedTypeLoc ATL;
360
+ for (TypeLoc TL = TSI->getTypeLoc ();
361
+ (ATL = TL.getAsAdjusted <AttributedTypeLoc>());
362
+ TL = ATL.getModifiedLoc ()) {
363
+ if (ATL.getAttrAs <LifetimeBoundAttr>())
364
+ return true ;
365
+ }
366
+
367
+ return isNormalAsisgnmentOperator (FD);
368
+ }
369
+
366
370
// Visit lifetimebound or gsl-pointer arguments.
367
371
static void visitFunctionCallArguments (IndirectLocalPath &Path, Expr *Call,
368
372
LocalVisitor Visit,
@@ -968,6 +972,22 @@ static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
968
972
return false ;
969
973
}
970
974
975
+ static bool isAssginmentOperatorLifetimeBound (CXXMethodDecl *CMD) {
976
+ if (!CMD)
977
+ return false ;
978
+ return isNormalAsisgnmentOperator (CMD) && CMD->param_size () == 1 &&
979
+ CMD->getParamDecl (0 )->hasAttr <LifetimeBoundAttr>();
980
+ }
981
+
982
+ static bool shouldRunGSLAssignmentAnalysis (const Sema &SemaRef,
983
+ const AssignedEntity &Entity) {
984
+ bool EnableGSLAssignmentWarnings = !SemaRef.getDiagnostics ().isIgnored (
985
+ diag::warn_dangling_lifetime_pointer_assignment, SourceLocation ());
986
+ return (EnableGSLAssignmentWarnings &&
987
+ (isRecordWithAttr<PointerAttr>(Entity.LHS ->getType ()) ||
988
+ isAssginmentOperatorLifetimeBound (Entity.AssignmentOperator )));
989
+ }
990
+
971
991
static void checkExprLifetimeImpl (Sema &SemaRef,
972
992
const InitializedEntity *InitEntity,
973
993
const InitializedEntity *ExtendingEntity,
@@ -1267,8 +1287,7 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
1267
1287
};
1268
1288
1269
1289
llvm::SmallVector<IndirectLocalPathEntry, 8 > Path;
1270
- if (EnableLifetimeWarnings && LK == LK_Assignment &&
1271
- isRecordWithAttr<PointerAttr>(AEntity->LHS ->getType ()))
1290
+ if (LK == LK_Assignment && shouldRunGSLAssignmentAnalysis (SemaRef, *AEntity))
1272
1291
Path.push_back ({IndirectLocalPathEntry::GslPointerAssignment, Init});
1273
1292
1274
1293
if (Init->isGLValue ())
@@ -1301,8 +1320,7 @@ void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity,
1301
1320
diag::warn_dangling_pointer_assignment, SourceLocation ());
1302
1321
bool RunAnalysis = (EnableDanglingPointerAssignment &&
1303
1322
Entity.LHS ->getType ()->isPointerType ()) ||
1304
- (EnableLifetimeWarnings &&
1305
- isRecordWithAttr<PointerAttr>(Entity.LHS ->getType ()));
1323
+ shouldRunGSLAssignmentAnalysis (SemaRef, Entity);
1306
1324
1307
1325
if (!RunAnalysis)
1308
1326
return ;
0 commit comments