@@ -270,34 +270,48 @@ void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) {
270
270
}
271
271
272
272
void Sema::inferLifetimeCaptureByAttribute (FunctionDecl *FD) {
273
- if (!FD)
273
+ auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD);
274
+ if (!MD || !MD->getParent ()->isInStdNamespace ())
274
275
return ;
275
- auto *MD = dyn_cast<CXXMethodDecl>(FD);
276
- if (!MD || !MD->getIdentifier () || !MD->getParent ()->isInStdNamespace ())
276
+ auto Annotate = [this ](const FunctionDecl *MD) {
277
+ // Do not infer if any parameter is explicitly annotated.
278
+ for (ParmVarDecl *PVD : MD->parameters ())
279
+ if (PVD->hasAttr <LifetimeCaptureByAttr>())
280
+ return ;
281
+ for (ParmVarDecl *PVD : MD->parameters ()) {
282
+ // Methods in standard containers that capture values typically accept
283
+ // reference-type parameters, e.g., `void push_back(const T& value)`.
284
+ // We only apply the lifetime_capture_by attribute to parameters of
285
+ // pointer-like reference types (`const T&`, `T&&`).
286
+ if (PVD->getType ()->isReferenceType () &&
287
+ sema::isPointerLikeType (PVD->getType ().getNonReferenceType ())) {
288
+ int CaptureByThis[] = {LifetimeCaptureByAttr::THIS};
289
+ PVD->addAttr (
290
+ LifetimeCaptureByAttr::CreateImplicit (Context, CaptureByThis, 1 ));
291
+ }
292
+ }
293
+ };
294
+
295
+ if (!MD->getIdentifier ()) {
296
+ static const llvm::StringSet<> MapLikeContainer{
297
+ " map" ,
298
+ " multimap" ,
299
+ " unordered_map" ,
300
+ " unordered_multimap" ,
301
+ };
302
+ // Infer for the map's operator []:
303
+ // std::map<string_view, ...> m;
304
+ // m[ReturnString(..)] = ...; // !dangling references in m.
305
+ if (MD->getOverloadedOperator () == OO_Subscript &&
306
+ MapLikeContainer.contains (MD->getParent ()->getName ()))
307
+ Annotate (MD);
277
308
return ;
278
- // FIXME: Infer for operator[] for map-like containers. For example:
279
- // std::map<string_view, ...> m;
280
- // m[ReturnString(..)] = ...;
309
+ }
281
310
static const llvm::StringSet<> CapturingMethods{" insert" , " push" ,
282
311
" push_front" , " push_back" };
283
312
if (!CapturingMethods.contains (MD->getName ()))
284
313
return ;
285
- // Do not infer if any parameter is explicitly annotated.
286
- for (ParmVarDecl *PVD : MD->parameters ())
287
- if (PVD->hasAttr <LifetimeCaptureByAttr>())
288
- return ;
289
- for (ParmVarDecl *PVD : MD->parameters ()) {
290
- // Methods in standard containers that capture values typically accept
291
- // reference-type parameters, e.g., `void push_back(const T& value)`.
292
- // We only apply the lifetime_capture_by attribute to parameters of
293
- // pointer-like reference types (`const T&`, `T&&`).
294
- if (PVD->getType ()->isReferenceType () &&
295
- sema::isPointerLikeType (PVD->getType ().getNonReferenceType ())) {
296
- int CaptureByThis[] = {LifetimeCaptureByAttr::THIS};
297
- PVD->addAttr (
298
- LifetimeCaptureByAttr::CreateImplicit (Context, CaptureByThis, 1 ));
299
- }
300
- }
314
+ Annotate (MD);
301
315
}
302
316
303
317
void Sema::inferNullableClassAttribute (CXXRecordDecl *CRD) {
0 commit comments