@@ -270,34 +270,49 @@ void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) {
270270}
271271
272272void Sema::inferLifetimeCaptureByAttribute (FunctionDecl *FD) {
273- if (!FD)
273+ auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD);
274+ if (!MD || !MD->getParent ()->isInStdNamespace ())
274275 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+ return ;
308+ Annotate (MD);
277309 return ;
278- // FIXME: Infer for operator[] for map-like containers. For example:
279- // std::map<string_view, ...> m;
280- // m[ReturnString(..)] = ...;
310+ }
281311 static const llvm::StringSet<> CapturingMethods{" insert" , " push" ,
282312 " push_front" , " push_back" };
283313 if (!CapturingMethods.contains (MD->getName ()))
284314 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- }
315+ Annotate (MD);
301316}
302317
303318void Sema::inferNullableClassAttribute (CXXRecordDecl *CRD) {
0 commit comments