clang 20.0.0git
CheckExprLifetime.cpp
Go to the documentation of this file.
1//===--- CheckExprLifetime.cpp --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CheckExprLifetime.h"
10#include "clang/AST/Decl.h"
11#include "clang/AST/Expr.h"
14#include "clang/Sema/Sema.h"
15#include "llvm/ADT/PointerIntPair.h"
16
17namespace clang::sema {
18namespace {
19enum LifetimeKind {
20 /// The lifetime of a temporary bound to this entity ends at the end of the
21 /// full-expression, and that's (probably) fine.
22 LK_FullExpression,
23
24 /// The lifetime of a temporary bound to this entity is extended to the
25 /// lifeitme of the entity itself.
26 LK_Extended,
27
28 /// The lifetime of a temporary bound to this entity probably ends too soon,
29 /// because the entity is allocated in a new-expression.
30 LK_New,
31
32 /// The lifetime of a temporary bound to this entity ends too soon, because
33 /// the entity is a return object.
34 LK_Return,
35
36 /// The lifetime of a temporary bound to this entity ends too soon, because
37 /// the entity is the result of a statement expression.
38 LK_StmtExprResult,
39
40 /// This is a mem-initializer: if it would extend a temporary (other than via
41 /// a default member initializer), the program is ill-formed.
42 LK_MemInitializer,
43
44 /// The lifetime of a temporary bound to this entity probably ends too soon,
45 /// because the entity is a pointer and we assign the address of a temporary
46 /// object to it.
47 LK_Assignment,
48};
49using LifetimeResult =
50 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
51} // namespace
52
53/// Determine the declaration which an initialized entity ultimately refers to,
54/// for the purpose of lifetime-extending a temporary bound to a reference in
55/// the initialization of \p Entity.
56static LifetimeResult
58 const InitializedEntity *InitField = nullptr) {
59 // C++11 [class.temporary]p5:
60 switch (Entity->getKind()) {
62 // The temporary [...] persists for the lifetime of the reference
63 return {Entity, LK_Extended};
64
66 // For subobjects, we look at the complete object.
67 if (Entity->getParent())
68 return getEntityLifetime(Entity->getParent(), Entity);
69
70 // except:
71 // C++17 [class.base.init]p8:
72 // A temporary expression bound to a reference member in a
73 // mem-initializer is ill-formed.
74 // C++17 [class.base.init]p11:
75 // A temporary expression bound to a reference member from a
76 // default member initializer is ill-formed.
77 //
78 // The context of p11 and its example suggest that it's only the use of a
79 // default member initializer from a constructor that makes the program
80 // ill-formed, not its mere existence, and that it can even be used by
81 // aggregate initialization.
82 return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
83 : LK_MemInitializer};
84
86 // Per [dcl.decomp]p3, the binding is treated as a variable of reference
87 // type.
88 return {Entity, LK_Extended};
89
92 // -- A temporary bound to a reference parameter in a function call
93 // persists until the completion of the full-expression containing
94 // the call.
95 return {nullptr, LK_FullExpression};
96
98 // FIXME: This will always be ill-formed; should we eagerly diagnose it
99 // here?
100 return {nullptr, LK_FullExpression};
101
103 // -- The lifetime of a temporary bound to the returned value in a
104 // function return statement is not extended; the temporary is
105 // destroyed at the end of the full-expression in the return statement.
106 return {nullptr, LK_Return};
107
109 // FIXME: Should we lifetime-extend through the result of a statement
110 // expression?
111 return {nullptr, LK_StmtExprResult};
112
114 // -- A temporary bound to a reference in a new-initializer persists
115 // until the completion of the full-expression containing the
116 // new-initializer.
117 return {nullptr, LK_New};
118
122 // We don't yet know the storage duration of the surrounding temporary.
123 // Assume it's got full-expression duration for now, it will patch up our
124 // storage duration if that's not correct.
125 return {nullptr, LK_FullExpression};
126
128 // For subobjects, we look at the complete object.
129 return getEntityLifetime(Entity->getParent(), InitField);
130
132 // For subobjects, we look at the complete object.
133 if (Entity->getParent())
134 return getEntityLifetime(Entity->getParent(), InitField);
135 return {InitField, LK_MemInitializer};
136
138 // We can reach this case for aggregate initialization in a constructor:
139 // struct A { int &&r; };
140 // struct B : A { B() : A{0} {} };
141 // In this case, use the outermost field decl as the context.
142 return {InitField, LK_MemInitializer};
143
149 return {nullptr, LK_FullExpression};
150
152 // FIXME: Can we diagnose lifetime problems with exceptions?
153 return {nullptr, LK_FullExpression};
154
156 // -- A temporary object bound to a reference element of an aggregate of
157 // class type initialized from a parenthesized expression-list
158 // [dcl.init, 9.3] persists until the completion of the full-expression
159 // containing the expression-list.
160 return {nullptr, LK_FullExpression};
161 }
162
163 llvm_unreachable("unknown entity kind");
164}
165
166namespace {
167enum ReferenceKind {
168 /// Lifetime would be extended by a reference binding to a temporary.
169 RK_ReferenceBinding,
170 /// Lifetime would be extended by a std::initializer_list object binding to
171 /// its backing array.
172 RK_StdInitializerList,
173};
174
175/// A temporary or local variable. This will be one of:
176/// * A MaterializeTemporaryExpr.
177/// * A DeclRefExpr whose declaration is a local.
178/// * An AddrLabelExpr.
179/// * A BlockExpr for a block with captures.
180using Local = Expr *;
181
182/// Expressions we stepped over when looking for the local state. Any steps
183/// that would inhibit lifetime extension or take us out of subexpressions of
184/// the initializer are included.
185struct IndirectLocalPathEntry {
186 enum EntryKind {
187 DefaultInit,
188 AddressOf,
189 VarInit,
190 LValToRVal,
191 LifetimeBoundCall,
192 TemporaryCopy,
193 LambdaCaptureInit,
194 GslReferenceInit,
195 GslPointerInit,
196 GslPointerAssignment,
198 Expr *E;
199 union {
200 const Decl *D = nullptr;
201 const LambdaCapture *Capture;
202 };
203 IndirectLocalPathEntry() {}
204 IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
205 IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
206 : Kind(K), E(E), D(D) {}
207 IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
208 : Kind(K), E(E), Capture(Capture) {}
209};
210
211using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
212
213struct RevertToOldSizeRAII {
214 IndirectLocalPath &Path;
215 unsigned OldSize = Path.size();
216 RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
217 ~RevertToOldSizeRAII() { Path.resize(OldSize); }
218};
219
220using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
221 ReferenceKind RK)>;
222} // namespace
223
224static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
225 for (auto E : Path)
226 if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
227 return true;
228 return false;
229}
230
231static bool pathContainsInit(IndirectLocalPath &Path) {
232 return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
233 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
234 E.Kind == IndirectLocalPathEntry::VarInit;
235 });
236}
237
238static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
239 Expr *Init, LocalVisitor Visit,
240 bool RevisitSubinits,
241 bool EnableLifetimeWarnings);
242
243static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
244 Expr *Init, ReferenceKind RK,
245 LocalVisitor Visit,
246 bool EnableLifetimeWarnings);
247
248template <typename T> static bool isRecordWithAttr(QualType Type) {
249 if (auto *RD = Type->getAsCXXRecordDecl())
250 return RD->hasAttr<T>();
251 return false;
252}
253
254// Decl::isInStdNamespace will return false for iterators in some STL
255// implementations due to them being defined in a namespace outside of the std
256// namespace.
257static bool isInStlNamespace(const Decl *D) {
258 const DeclContext *DC = D->getDeclContext();
259 if (!DC)
260 return false;
261 if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
262 if (const IdentifierInfo *II = ND->getIdentifier()) {
263 StringRef Name = II->getName();
264 if (Name.size() >= 2 && Name.front() == '_' &&
265 (Name[1] == '_' || isUppercase(Name[1])))
266 return true;
267 }
268
269 return DC->isStdNamespace();
270}
271
272static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
273 if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
274 if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
275 return true;
276 if (!isInStlNamespace(Callee->getParent()))
277 return false;
278 if (!isRecordWithAttr<PointerAttr>(
279 Callee->getFunctionObjectParameterType()) &&
280 !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
281 return false;
282 if (Callee->getReturnType()->isPointerType() ||
283 isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
284 if (!Callee->getIdentifier())
285 return false;
286 return llvm::StringSwitch<bool>(Callee->getName())
287 .Cases("begin", "rbegin", "cbegin", "crbegin", true)
288 .Cases("end", "rend", "cend", "crend", true)
289 .Cases("c_str", "data", "get", true)
290 // Map and set types.
291 .Cases("find", "equal_range", "lower_bound", "upper_bound", true)
292 .Default(false);
293 } else if (Callee->getReturnType()->isReferenceType()) {
294 if (!Callee->getIdentifier()) {
295 auto OO = Callee->getOverloadedOperator();
296 return OO == OverloadedOperatorKind::OO_Subscript ||
297 OO == OverloadedOperatorKind::OO_Star;
298 }
299 return llvm::StringSwitch<bool>(Callee->getName())
300 .Cases("front", "back", "at", "top", "value", true)
301 .Default(false);
302 }
303 return false;
304}
305
307 if (!FD->getIdentifier() || FD->getNumParams() != 1)
308 return false;
309 const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
310 if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
311 return false;
312 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
313 return false;
314 if (FD->getReturnType()->isPointerType() ||
315 isRecordWithAttr<PointerAttr>(FD->getReturnType())) {
316 return llvm::StringSwitch<bool>(FD->getName())
317 .Cases("begin", "rbegin", "cbegin", "crbegin", true)
318 .Cases("end", "rend", "cend", "crend", true)
319 .Case("data", true)
320 .Default(false);
321 } else if (FD->getReturnType()->isReferenceType()) {
322 return llvm::StringSwitch<bool>(FD->getName())
323 .Cases("get", "any_cast", true)
324 .Default(false);
325 }
326 return false;
327}
328
329static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
330 LocalVisitor Visit) {
331 auto VisitPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {
332 // We are not interested in the temporary base objects of gsl Pointers:
333 // Temp().ptr; // Here ptr might not dangle.
334 if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
335 return;
336 // Once we initialized a value with a reference, it can no longer dangle.
337 if (!Value) {
338 for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
339 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)
340 continue;
341 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
342 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
343 return;
344 break;
345 }
346 }
347 Path.push_back({Value ? IndirectLocalPathEntry::GslPointerInit
348 : IndirectLocalPathEntry::GslReferenceInit,
349 Arg, D});
350 if (Arg->isGLValue())
351 visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
352 Visit,
353 /*EnableLifetimeWarnings=*/true);
354 else
355 visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
356 /*EnableLifetimeWarnings=*/true);
357 Path.pop_back();
358 };
359
360 if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
361 const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
362 if (MD && shouldTrackImplicitObjectArg(MD))
363 VisitPointerArg(MD, MCE->getImplicitObjectArgument(),
364 !MD->getReturnType()->isReferenceType());
365 return;
366 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
367 FunctionDecl *Callee = OCE->getDirectCallee();
368 if (Callee && Callee->isCXXInstanceMember() &&
369 shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
370 VisitPointerArg(Callee, OCE->getArg(0),
371 !Callee->getReturnType()->isReferenceType());
372 return;
373 } else if (auto *CE = dyn_cast<CallExpr>(Call)) {
374 FunctionDecl *Callee = CE->getDirectCallee();
375 if (Callee && shouldTrackFirstArgument(Callee))
376 VisitPointerArg(Callee, CE->getArg(0),
377 !Callee->getReturnType()->isReferenceType());
378 return;
379 }
380
381 if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
382 const auto *Ctor = CCE->getConstructor();
383 const CXXRecordDecl *RD = Ctor->getParent();
384 if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())
385 VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0], true);
386 }
387}
388
390 const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
391 if (!TSI)
392 return false;
393 // Don't declare this variable in the second operand of the for-statement;
394 // GCC miscompiles that by ending its lifetime before evaluating the
395 // third operand. See gcc.gnu.org/PR86769.
397 for (TypeLoc TL = TSI->getTypeLoc();
398 (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
399 TL = ATL.getModifiedLoc()) {
400 if (ATL.getAttrAs<LifetimeBoundAttr>())
401 return true;
402 }
403
404 // Assume that all assignment operators with a "normal" return type return
405 // *this, that is, an lvalue reference that is the same type as the implicit
406 // object parameter (or the LHS for a non-member operator$=).
408 if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) {
409 QualType RetT = FD->getReturnType();
410 if (RetT->isLValueReferenceType()) {
411 ASTContext &Ctx = FD->getASTContext();
412 QualType LHST;
413 auto *MD = dyn_cast<CXXMethodDecl>(FD);
414 if (MD && MD->isCXXInstanceMember())
415 LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
416 else
417 LHST = MD->getParamDecl(0)->getType();
418 if (Ctx.hasSameType(RetT, LHST))
419 return true;
420 }
421 }
422
423 return false;
424}
425
426static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
427 LocalVisitor Visit) {
428 const FunctionDecl *Callee;
429 ArrayRef<Expr *> Args;
430
431 if (auto *CE = dyn_cast<CallExpr>(Call)) {
432 Callee = CE->getDirectCallee();
433 Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
434 } else {
435 auto *CCE = cast<CXXConstructExpr>(Call);
436 Callee = CCE->getConstructor();
437 Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
438 }
439 if (!Callee)
440 return;
441
442 Expr *ObjectArg = nullptr;
443 if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
444 ObjectArg = Args[0];
445 Args = Args.slice(1);
446 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
447 ObjectArg = MCE->getImplicitObjectArgument();
448 }
449
450 auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
451 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
452 if (Arg->isGLValue())
453 visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
454 Visit,
455 /*EnableLifetimeWarnings=*/false);
456 else
457 visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
458 /*EnableLifetimeWarnings=*/false);
459 Path.pop_back();
460 };
461
462 bool CheckCoroCall = false;
463 if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
464 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
465 RD->hasAttr<CoroReturnTypeAttr>() &&
466 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
467 }
468
469 if (ObjectArg) {
470 bool CheckCoroObjArg = CheckCoroCall;
471 // Coroutine lambda objects with empty capture list are not lifetimebound.
472 if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit());
473 LE && LE->captures().empty())
474 CheckCoroObjArg = false;
475 // Allow `get_return_object()` as the object param (__promise) is not
476 // lifetimebound.
477 if (Sema::CanBeGetReturnObject(Callee))
478 CheckCoroObjArg = false;
479 if (implicitObjectParamIsLifetimeBound(Callee) || CheckCoroObjArg)
480 VisitLifetimeBoundArg(Callee, ObjectArg);
481 }
482
483 for (unsigned I = 0,
484 N = std::min<unsigned>(Callee->getNumParams(), Args.size());
485 I != N; ++I) {
486 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
487 VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
488 }
489}
490
491/// Visit the locals that would be reachable through a reference bound to the
492/// glvalue expression \c Init.
493static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
494 Expr *Init, ReferenceKind RK,
495 LocalVisitor Visit,
496 bool EnableLifetimeWarnings) {
497 RevertToOldSizeRAII RAII(Path);
498
499 // Walk past any constructs which we can lifetime-extend across.
500 Expr *Old;
501 do {
502 Old = Init;
503
504 if (auto *FE = dyn_cast<FullExpr>(Init))
505 Init = FE->getSubExpr();
506
507 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
508 // If this is just redundant braces around an initializer, step over it.
509 if (ILE->isTransparent())
510 Init = ILE->getInit(0);
511 }
512
513 // Step over any subobject adjustments; we may have a materialized
514 // temporary inside them.
515 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
516
517 // Per current approach for DR1376, look through casts to reference type
518 // when performing lifetime extension.
519 if (CastExpr *CE = dyn_cast<CastExpr>(Init))
520 if (CE->getSubExpr()->isGLValue())
521 Init = CE->getSubExpr();
522
523 // Per the current approach for DR1299, look through array element access
524 // on array glvalues when performing lifetime extension.
525 if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
526 Init = ASE->getBase();
527 auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
528 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
529 Init = ICE->getSubExpr();
530 else
531 // We can't lifetime extend through this but we might still find some
532 // retained temporaries.
533 return visitLocalsRetainedByInitializer(Path, Init, Visit, true,
534 EnableLifetimeWarnings);
535 }
536
537 // Step into CXXDefaultInitExprs so we can diagnose cases where a
538 // constructor inherits one as an implicit mem-initializer.
539 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
540 Path.push_back(
541 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
542 Init = DIE->getExpr();
543 }
544 } while (Init != Old);
545
546 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
547 if (Visit(Path, Local(MTE), RK))
548 visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true,
549 EnableLifetimeWarnings);
550 }
551
552 if (auto *M = dyn_cast<MemberExpr>(Init)) {
553 // Lifetime of a non-reference type field is same as base object.
554 if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
555 F && !F->getType()->isReferenceType())
556 visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true,
557 EnableLifetimeWarnings);
558 }
559
560 if (isa<CallExpr>(Init)) {
561 if (EnableLifetimeWarnings)
563 return visitLifetimeBoundArguments(Path, Init, Visit);
564 }
565
566 switch (Init->getStmtClass()) {
567 case Stmt::DeclRefExprClass: {
568 // If we find the name of a local non-reference parameter, we could have a
569 // lifetime problem.
570 auto *DRE = cast<DeclRefExpr>(Init);
571 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
572 if (VD && VD->hasLocalStorage() &&
573 !DRE->refersToEnclosingVariableOrCapture()) {
574 if (!VD->getType()->isReferenceType()) {
575 Visit(Path, Local(DRE), RK);
576 } else if (isa<ParmVarDecl>(DRE->getDecl())) {
577 // The lifetime of a reference parameter is unknown; assume it's OK
578 // for now.
579 break;
580 } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
581 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
583 RK_ReferenceBinding, Visit,
584 EnableLifetimeWarnings);
585 }
586 }
587 break;
588 }
589
590 case Stmt::UnaryOperatorClass: {
591 // The only unary operator that make sense to handle here
592 // is Deref. All others don't resolve to a "name." This includes
593 // handling all sorts of rvalues passed to a unary operator.
594 const UnaryOperator *U = cast<UnaryOperator>(Init);
595 if (U->getOpcode() == UO_Deref)
596 visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true,
597 EnableLifetimeWarnings);
598 break;
599 }
600
601 case Stmt::ArraySectionExprClass: {
603 cast<ArraySectionExpr>(Init)->getBase(),
604 Visit, true, EnableLifetimeWarnings);
605 break;
606 }
607
608 case Stmt::ConditionalOperatorClass:
609 case Stmt::BinaryConditionalOperatorClass: {
610 auto *C = cast<AbstractConditionalOperator>(Init);
611 if (!C->getTrueExpr()->getType()->isVoidType())
612 visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit,
613 EnableLifetimeWarnings);
614 if (!C->getFalseExpr()->getType()->isVoidType())
615 visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit,
616 EnableLifetimeWarnings);
617 break;
618 }
619
620 case Stmt::CompoundLiteralExprClass: {
621 if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
622 if (!CLE->isFileScope())
623 Visit(Path, Local(CLE), RK);
624 }
625 break;
626 }
627
628 // FIXME: Visit the left-hand side of an -> or ->*.
629
630 default:
631 break;
632 }
633}
634
635/// Visit the locals that would be reachable through an object initialized by
636/// the prvalue expression \c Init.
637static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
638 Expr *Init, LocalVisitor Visit,
639 bool RevisitSubinits,
640 bool EnableLifetimeWarnings) {
641 RevertToOldSizeRAII RAII(Path);
642
643 Expr *Old;
644 do {
645 Old = Init;
646
647 // Step into CXXDefaultInitExprs so we can diagnose cases where a
648 // constructor inherits one as an implicit mem-initializer.
649 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
650 Path.push_back(
651 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
652 Init = DIE->getExpr();
653 }
654
655 if (auto *FE = dyn_cast<FullExpr>(Init))
656 Init = FE->getSubExpr();
657
658 // Dig out the expression which constructs the extended temporary.
659 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
660
661 if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
662 Init = BTE->getSubExpr();
663
664 Init = Init->IgnoreParens();
665
666 // Step over value-preserving rvalue casts.
667 if (auto *CE = dyn_cast<CastExpr>(Init)) {
668 switch (CE->getCastKind()) {
669 case CK_LValueToRValue:
670 // If we can match the lvalue to a const object, we can look at its
671 // initializer.
672 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
674 Path, Init, RK_ReferenceBinding,
675 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
676 if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
677 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
678 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
679 !isVarOnPath(Path, VD)) {
680 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
682 Path, VD->getInit(), Visit, true, EnableLifetimeWarnings);
683 }
684 } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
685 if (MTE->getType().isConstQualified())
686 visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),
687 Visit, true,
688 EnableLifetimeWarnings);
689 }
690 return false;
691 },
692 EnableLifetimeWarnings);
693
694 // We assume that objects can be retained by pointers cast to integers,
695 // but not if the integer is cast to floating-point type or to _Complex.
696 // We assume that casts to 'bool' do not preserve enough information to
697 // retain a local object.
698 case CK_NoOp:
699 case CK_BitCast:
700 case CK_BaseToDerived:
701 case CK_DerivedToBase:
702 case CK_UncheckedDerivedToBase:
703 case CK_Dynamic:
704 case CK_ToUnion:
705 case CK_UserDefinedConversion:
706 case CK_ConstructorConversion:
707 case CK_IntegralToPointer:
708 case CK_PointerToIntegral:
709 case CK_VectorSplat:
710 case CK_IntegralCast:
711 case CK_CPointerToObjCPointerCast:
712 case CK_BlockPointerToObjCPointerCast:
713 case CK_AnyPointerToBlockPointerCast:
714 case CK_AddressSpaceConversion:
715 break;
716
717 case CK_ArrayToPointerDecay:
718 // Model array-to-pointer decay as taking the address of the array
719 // lvalue.
720 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
721 return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),
722 RK_ReferenceBinding, Visit,
723 EnableLifetimeWarnings);
724
725 default:
726 return;
727 }
728
729 Init = CE->getSubExpr();
730 }
731 } while (Old != Init);
732
733 // C++17 [dcl.init.list]p6:
734 // initializing an initializer_list object from the array extends the
735 // lifetime of the array exactly like binding a reference to a temporary.
736 if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
737 return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
738 RK_StdInitializerList, Visit,
739 EnableLifetimeWarnings);
740
741 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
742 // We already visited the elements of this initializer list while
743 // performing the initialization. Don't visit them again unless we've
744 // changed the lifetime of the initialized entity.
745 if (!RevisitSubinits)
746 return;
747
748 if (ILE->isTransparent())
749 return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
750 RevisitSubinits,
751 EnableLifetimeWarnings);
752
753 if (ILE->getType()->isArrayType()) {
754 for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
755 visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
756 RevisitSubinits,
757 EnableLifetimeWarnings);
758 return;
759 }
760
761 if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
762 assert(RD->isAggregate() && "aggregate init on non-aggregate");
763
764 // If we lifetime-extend a braced initializer which is initializing an
765 // aggregate, and that aggregate contains reference members which are
766 // bound to temporaries, those temporaries are also lifetime-extended.
767 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
768 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
770 RK_ReferenceBinding, Visit,
771 EnableLifetimeWarnings);
772 else {
773 unsigned Index = 0;
774 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
775 visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
776 RevisitSubinits,
777 EnableLifetimeWarnings);
778 for (const auto *I : RD->fields()) {
779 if (Index >= ILE->getNumInits())
780 break;
781 if (I->isUnnamedBitField())
782 continue;
783 Expr *SubInit = ILE->getInit(Index);
784 if (I->getType()->isReferenceType())
786 RK_ReferenceBinding, Visit,
787 EnableLifetimeWarnings);
788 else
789 // This might be either aggregate-initialization of a member or
790 // initialization of a std::initializer_list object. Regardless,
791 // we should recursively lifetime-extend that initializer.
793 Path, SubInit, Visit, RevisitSubinits, EnableLifetimeWarnings);
794 ++Index;
795 }
796 }
797 }
798 return;
799 }
800
801 // The lifetime of an init-capture is that of the closure object constructed
802 // by a lambda-expression.
803 if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
804 LambdaExpr::capture_iterator CapI = LE->capture_begin();
805 for (Expr *E : LE->capture_inits()) {
806 assert(CapI != LE->capture_end());
807 const LambdaCapture &Cap = *CapI++;
808 if (!E)
809 continue;
810 if (Cap.capturesVariable())
811 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
812 if (E->isGLValue())
813 visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
814 Visit, EnableLifetimeWarnings);
815 else
817 EnableLifetimeWarnings);
818 if (Cap.capturesVariable())
819 Path.pop_back();
820 }
821 }
822
823 // Assume that a copy or move from a temporary references the same objects
824 // that the temporary does.
825 if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {
826 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
827 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
828 Expr *Arg = MTE->getSubExpr();
829 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
830 CCE->getConstructor()});
831 visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
832 /*EnableLifetimeWarnings*/ false);
833 Path.pop_back();
834 }
835 }
836 }
837
838 if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {
839 if (EnableLifetimeWarnings)
841 return visitLifetimeBoundArguments(Path, Init, Visit);
842 }
843
844 switch (Init->getStmtClass()) {
845 case Stmt::UnaryOperatorClass: {
846 auto *UO = cast<UnaryOperator>(Init);
847 // If the initializer is the address of a local, we could have a lifetime
848 // problem.
849 if (UO->getOpcode() == UO_AddrOf) {
850 // If this is &rvalue, then it's ill-formed and we have already diagnosed
851 // it. Don't produce a redundant warning about the lifetime of the
852 // temporary.
853 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
854 return;
855
856 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
858 RK_ReferenceBinding, Visit,
859 EnableLifetimeWarnings);
860 }
861 break;
862 }
863
864 case Stmt::BinaryOperatorClass: {
865 // Handle pointer arithmetic.
866 auto *BO = cast<BinaryOperator>(Init);
867 BinaryOperatorKind BOK = BO->getOpcode();
868 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
869 break;
870
871 if (BO->getLHS()->getType()->isPointerType())
872 visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true,
873 EnableLifetimeWarnings);
874 else if (BO->getRHS()->getType()->isPointerType())
875 visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true,
876 EnableLifetimeWarnings);
877 break;
878 }
879
880 case Stmt::ConditionalOperatorClass:
881 case Stmt::BinaryConditionalOperatorClass: {
882 auto *C = cast<AbstractConditionalOperator>(Init);
883 // In C++, we can have a throw-expression operand, which has 'void' type
884 // and isn't interesting from a lifetime perspective.
885 if (!C->getTrueExpr()->getType()->isVoidType())
886 visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true,
887 EnableLifetimeWarnings);
888 if (!C->getFalseExpr()->getType()->isVoidType())
889 visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true,
890 EnableLifetimeWarnings);
891 break;
892 }
893
894 case Stmt::BlockExprClass:
895 if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
896 // This is a local block, whose lifetime is that of the function.
897 Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
898 }
899 break;
900
901 case Stmt::AddrLabelExprClass:
902 // We want to warn if the address of a label would escape the function.
903 Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
904 break;
905
906 default:
907 break;
908 }
909}
910
911/// Whether a path to an object supports lifetime extension.
913 /// Lifetime-extend along this path.
915 /// We should lifetime-extend, but we don't because (due to technical
916 /// limitations) we can't. This happens for default member initializers,
917 /// which we don't clone for every use, so we don't have a unique
918 /// MaterializeTemporaryExpr to update.
920 /// Do not lifetime extend along this path.
923
924/// Determine whether this is an indirect path to a temporary that we are
925/// supposed to lifetime-extend along.
926static PathLifetimeKind
927shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
929 for (auto Elem : Path) {
930 if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
932 else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
934 }
935 return Kind;
936}
937
938/// Find the range for the first interesting entry in the path at or after I.
939static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
940 Expr *E) {
941 for (unsigned N = Path.size(); I != N; ++I) {
942 switch (Path[I].Kind) {
943 case IndirectLocalPathEntry::AddressOf:
944 case IndirectLocalPathEntry::LValToRVal:
945 case IndirectLocalPathEntry::LifetimeBoundCall:
946 case IndirectLocalPathEntry::TemporaryCopy:
947 case IndirectLocalPathEntry::GslReferenceInit:
948 case IndirectLocalPathEntry::GslPointerInit:
949 case IndirectLocalPathEntry::GslPointerAssignment:
950 // These exist primarily to mark the path as not permitting or
951 // supporting lifetime extension.
952 break;
953
954 case IndirectLocalPathEntry::VarInit:
955 if (cast<VarDecl>(Path[I].D)->isImplicit())
956 return SourceRange();
957 [[fallthrough]];
958 case IndirectLocalPathEntry::DefaultInit:
959 return Path[I].E->getSourceRange();
960
961 case IndirectLocalPathEntry::LambdaCaptureInit:
962 if (!Path[I].Capture->capturesVariable())
963 continue;
964 return Path[I].E->getSourceRange();
965 }
966 }
967 return E->getSourceRange();
968}
969
970static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
971 for (const auto &It : llvm::reverse(Path)) {
972 switch (It.Kind) {
973 case IndirectLocalPathEntry::VarInit:
974 case IndirectLocalPathEntry::AddressOf:
975 case IndirectLocalPathEntry::LifetimeBoundCall:
976 continue;
977 case IndirectLocalPathEntry::GslPointerInit:
978 case IndirectLocalPathEntry::GslReferenceInit:
979 case IndirectLocalPathEntry::GslPointerAssignment:
980 return true;
981 default:
982 return false;
983 }
984 }
985 return false;
986}
987
988static void checkExprLifetimeImpl(Sema &SemaRef,
989 const InitializedEntity *InitEntity,
990 const InitializedEntity *ExtendingEntity,
991 LifetimeKind LK,
992 const AssignedEntity *AEntity, Expr *Init,
993 bool EnableLifetimeWarnings) {
994 assert((AEntity && LK == LK_Assignment) ||
995 (InitEntity && LK != LK_Assignment));
996 // If this entity doesn't have an interesting lifetime, don't bother looking
997 // for temporaries within its initializer.
998 if (LK == LK_FullExpression)
999 return;
1000
1001 // FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
1002 // functions to a dedicated class.
1003 auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
1004 ReferenceKind RK) -> bool {
1005 SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
1006 SourceLocation DiagLoc = DiagRange.getBegin();
1007
1008 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1009
1010 bool IsGslPtrValueFromGslTempOwner = false;
1011 bool IsLocalGslOwner = false;
1013 if (isa<DeclRefExpr>(L)) {
1014 // We do not want to follow the references when returning a pointer
1015 // originating from a local owner to avoid the following false positive:
1016 // int &p = *localUniquePtr;
1017 // someContainer.add(std::move(localUniquePtr));
1018 // return p;
1019 IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
1020 if (pathContainsInit(Path) || !IsLocalGslOwner)
1021 return false;
1022 } else {
1023 IsGslPtrValueFromGslTempOwner =
1024 MTE && !MTE->getExtendingDecl() &&
1025 isRecordWithAttr<OwnerAttr>(MTE->getType());
1026 // Skipping a chain of initializing gsl::Pointer annotated objects.
1027 // We are looking only for the final source to find out if it was
1028 // a local or temporary owner or the address of a local variable/param.
1029 if (!IsGslPtrValueFromGslTempOwner)
1030 return true;
1031 }
1032 }
1033
1034 switch (LK) {
1035 case LK_FullExpression:
1036 llvm_unreachable("already handled this");
1037
1038 case LK_Extended: {
1039 if (!MTE) {
1040 // The initialized entity has lifetime beyond the full-expression,
1041 // and the local entity does too, so don't warn.
1042 //
1043 // FIXME: We should consider warning if a static / thread storage
1044 // duration variable retains an automatic storage duration local.
1045 return false;
1046 }
1047
1048 if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
1049 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1050 << DiagRange;
1051 return false;
1052 }
1053
1056 // Update the storage duration of the materialized temporary.
1057 // FIXME: Rebuild the expression instead of mutating it.
1058 MTE->setExtendingDecl(ExtendingEntity->getDecl(),
1059 ExtendingEntity->allocateManglingNumber());
1060 // Also visit the temporaries lifetime-extended by this initializer.
1061 return true;
1062
1064 // We're supposed to lifetime-extend the temporary along this path (per
1065 // the resolution of DR1815), but we don't support that yet.
1066 //
1067 // FIXME: Properly handle this situation. Perhaps the easiest approach
1068 // would be to clone the initializer expression on each use that would
1069 // lifetime extend its temporaries.
1070 SemaRef.Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
1071 << RK << DiagRange;
1072 break;
1073
1075 // If the path goes through the initialization of a variable or field,
1076 // it can't possibly reach a temporary created in this full-expression.
1077 // We will have already diagnosed any problems with the initializer.
1079 return false;
1080
1081 SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
1082 << RK << !InitEntity->getParent()
1083 << ExtendingEntity->getDecl()->isImplicit()
1084 << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
1085 break;
1086 }
1087 break;
1088 }
1089
1090 case LK_Assignment: {
1091 if (!MTE || pathContainsInit(Path))
1092 return false;
1095 "No lifetime extension for assignments");
1096 SemaRef.Diag(DiagLoc,
1097 IsGslPtrValueFromGslTempOwner
1098 ? diag::warn_dangling_lifetime_pointer_assignment
1099 : diag::warn_dangling_pointer_assignment)
1100 << AEntity->LHS << DiagRange;
1101 return false;
1102 }
1103 case LK_MemInitializer: {
1104 if (MTE) {
1105 // Under C++ DR1696, if a mem-initializer (or a default member
1106 // initializer used by the absence of one) would lifetime-extend a
1107 // temporary, the program is ill-formed.
1108 if (auto *ExtendingDecl =
1109 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1110 if (IsGslPtrValueFromGslTempOwner) {
1111 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1112 << ExtendingDecl << DiagRange;
1113 SemaRef.Diag(ExtendingDecl->getLocation(),
1114 diag::note_ref_or_ptr_member_declared_here)
1115 << true;
1116 return false;
1117 }
1118 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1119 SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
1121 ? diag::err_dangling_member
1122 : diag::warn_dangling_member)
1123 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1124 // Don't bother adding a note pointing to the field if we're inside
1125 // its default member initializer; our primary diagnostic points to
1126 // the same place in that case.
1127 if (Path.empty() ||
1128 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1129 SemaRef.Diag(ExtendingDecl->getLocation(),
1130 diag::note_lifetime_extending_member_declared_here)
1131 << RK << IsSubobjectMember;
1132 }
1133 } else {
1134 // We have a mem-initializer but no particular field within it; this
1135 // is either a base class or a delegating initializer directly
1136 // initializing the base-class from something that doesn't live long
1137 // enough.
1138 //
1139 // FIXME: Warn on this.
1140 return false;
1141 }
1142 } else {
1143 // Paths via a default initializer can only occur during error recovery
1144 // (there's no other way that a default initializer can refer to a
1145 // local). Don't produce a bogus warning on those cases.
1147 return false;
1148
1149 // Suppress false positives for code like the one below:
1150 // Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}
1151 if (IsLocalGslOwner && pathOnlyHandlesGslPointer(Path))
1152 return false;
1153
1154 auto *DRE = dyn_cast<DeclRefExpr>(L);
1155 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
1156 if (!VD) {
1157 // A member was initialized to a local block.
1158 // FIXME: Warn on this.
1159 return false;
1160 }
1161
1162 if (auto *Member =
1163 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1164 bool IsPointer = !Member->getType()->isReferenceType();
1165 SemaRef.Diag(DiagLoc,
1166 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1167 : diag::warn_bind_ref_member_to_parameter)
1168 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1169 SemaRef.Diag(Member->getLocation(),
1170 diag::note_ref_or_ptr_member_declared_here)
1171 << (unsigned)IsPointer;
1172 }
1173 }
1174 break;
1175 }
1176
1177 case LK_New:
1178 if (isa<MaterializeTemporaryExpr>(L)) {
1179 if (IsGslPtrValueFromGslTempOwner)
1180 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1181 << DiagRange;
1182 else
1183 SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
1184 ? diag::warn_new_dangling_reference
1185 : diag::warn_new_dangling_initializer_list)
1186 << !InitEntity->getParent() << DiagRange;
1187 } else {
1188 // We can't determine if the allocation outlives the local declaration.
1189 return false;
1190 }
1191 break;
1192
1193 case LK_Return:
1194 case LK_StmtExprResult:
1195 if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1196 // We can't determine if the local variable outlives the statement
1197 // expression.
1198 if (LK == LK_StmtExprResult)
1199 return false;
1200 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1201 << InitEntity->getType()->isReferenceType() << DRE->getDecl()
1202 << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
1203 } else if (isa<BlockExpr>(L)) {
1204 SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1205 } else if (isa<AddrLabelExpr>(L)) {
1206 // Don't warn when returning a label from a statement expression.
1207 // Leaving the scope doesn't end its lifetime.
1208 if (LK == LK_StmtExprResult)
1209 return false;
1210 SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1211 } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1212 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1213 << InitEntity->getType()->isReferenceType() << CLE->getInitializer()
1214 << 2 << DiagRange;
1215 } else {
1216 // P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
1217 // [stmt.return]/p6: In a function whose return type is a reference,
1218 // other than an invented function for std::is_convertible ([meta.rel]),
1219 // a return statement that binds the returned reference to a temporary
1220 // expression ([class.temporary]) is ill-formed.
1221 if (SemaRef.getLangOpts().CPlusPlus26 &&
1222 InitEntity->getType()->isReferenceType())
1223 SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
1224 << InitEntity->getType()->isReferenceType() << DiagRange;
1225 else
1226 SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1227 << InitEntity->getType()->isReferenceType() << DiagRange;
1228 }
1229 break;
1230 }
1231
1232 for (unsigned I = 0; I != Path.size(); ++I) {
1233 auto Elem = Path[I];
1234
1235 switch (Elem.Kind) {
1236 case IndirectLocalPathEntry::AddressOf:
1237 case IndirectLocalPathEntry::LValToRVal:
1238 // These exist primarily to mark the path as not permitting or
1239 // supporting lifetime extension.
1240 break;
1241
1242 case IndirectLocalPathEntry::LifetimeBoundCall:
1243 case IndirectLocalPathEntry::TemporaryCopy:
1244 case IndirectLocalPathEntry::GslPointerInit:
1245 case IndirectLocalPathEntry::GslReferenceInit:
1246 case IndirectLocalPathEntry::GslPointerAssignment:
1247 // FIXME: Consider adding a note for these.
1248 break;
1249
1250 case IndirectLocalPathEntry::DefaultInit: {
1251 auto *FD = cast<FieldDecl>(Elem.D);
1252 SemaRef.Diag(FD->getLocation(),
1253 diag::note_init_with_default_member_initializer)
1254 << FD << nextPathEntryRange(Path, I + 1, L);
1255 break;
1256 }
1257
1258 case IndirectLocalPathEntry::VarInit: {
1259 const VarDecl *VD = cast<VarDecl>(Elem.D);
1260 SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
1261 << VD->getType()->isReferenceType() << VD->isImplicit()
1262 << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L);
1263 break;
1264 }
1265
1266 case IndirectLocalPathEntry::LambdaCaptureInit:
1267 if (!Elem.Capture->capturesVariable())
1268 break;
1269 // FIXME: We can't easily tell apart an init-capture from a nested
1270 // capture of an init-capture.
1271 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1272 SemaRef.Diag(Elem.Capture->getLocation(),
1273 diag::note_lambda_capture_initializer)
1274 << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
1275 << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
1276 << nextPathEntryRange(Path, I + 1, L);
1277 break;
1278 }
1279 }
1280
1281 // We didn't lifetime-extend, so don't go any further; we don't need more
1282 // warnings or errors on inner temporaries within this one's initializer.
1283 return false;
1284 };
1285
1287 if (EnableLifetimeWarnings && LK == LK_Assignment &&
1288 isRecordWithAttr<PointerAttr>(AEntity->LHS->getType()))
1289 Path.push_back({IndirectLocalPathEntry::GslPointerAssignment, Init});
1290
1291 if (Init->isGLValue())
1292 visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
1293 TemporaryVisitor,
1294 EnableLifetimeWarnings);
1295 else
1297 Path, Init, TemporaryVisitor,
1298 // Don't revisit the sub inits for the intialization case.
1299 /*RevisitSubinits=*/!InitEntity, EnableLifetimeWarnings);
1300}
1301
1302void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity,
1303 Expr *Init) {
1304 auto LTResult = getEntityLifetime(&Entity);
1305 LifetimeKind LK = LTResult.getInt();
1306 const InitializedEntity *ExtendingEntity = LTResult.getPointer();
1307 bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
1308 diag::warn_dangling_lifetime_pointer, SourceLocation());
1309 checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK,
1310 /*AEntity*/ nullptr, Init, EnableLifetimeWarnings);
1311}
1312
1313void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity,
1314 Expr *Init) {
1315 bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
1316 diag::warn_dangling_lifetime_pointer, SourceLocation());
1317 bool RunAnalysis = Entity.LHS->getType()->isPointerType() ||
1318 (EnableLifetimeWarnings &&
1319 isRecordWithAttr<PointerAttr>(Entity.LHS->getType()));
1320
1321 if (!RunAnalysis)
1322 return;
1323
1324 checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
1325 /*ExtendingEntity=*/nullptr, LK_Assignment, &Entity,
1326 Init, EnableLifetimeWarnings);
1327}
1328
1329} // namespace clang::sema
const Decl * D
enum clang::sema::@1655::IndirectLocalPathEntry::EntryKind Kind
IndirectLocalPath & Path
const LambdaCapture * Capture
Expr * E
unsigned OldSize
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:186
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2643
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
Type source information for an attributed type.
Definition: TypeLoc.h:875
const T * getAttrAs()
Definition: TypeLoc.h:905
TypeLoc getModifiedLoc() const
The modified type, which is generally canonically different from the attribute type.
Definition: TypeLoc.h:889
Represents binding an expression to a temporary.
Definition: ExprCXX.h:1491
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2063
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3498
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2089
bool isStdNamespace() const
Definition: DeclBase.cpp:1317
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
bool isInStdNamespace() const
Definition: DeclBase.cpp:425
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:523
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:599
SourceLocation getLocation() const
Definition: DeclBase.h:445
bool hasAttr() const
Definition: DeclBase.h:583
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:760
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition: Diagnostic.h:916
This represents one expression.
Definition: Expr.h:110
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3058
QualType getType() const
Definition: Expr.h:142
Represents a function declaration or definition.
Definition: Decl.h:1932
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2669
QualType getReturnType() const
Definition: Decl.h:2717
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3678
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Definition: Expr.h:5029
Describes an entity that is being initialized.
EntityKind getKind() const
Determine the kind of initialization.
unsigned allocateManglingNumber() const
QualType getType() const
Retrieve type being initialized.
ValueDecl * getDecl() const
Retrieve the variable, parameter, or field being initialized.
Definition: SemaInit.cpp:3630
const InitializedEntity * getParent() const
Retrieve the parent of the entity being initialized, when the initialization itself is occurring with...
@ EK_Variable
The entity being initialized is a variable.
@ EK_Temporary
The entity being initialized is a temporary object.
@ EK_Binding
The entity being initialized is a structured binding of a decomposition declaration.
@ EK_BlockElement
The entity being initialized is a field of block descriptor for the copied-in c++ object.
@ EK_Parameter_CF_Audited
The entity being initialized is a function parameter; function is member of group of audited CF APIs.
@ EK_LambdaToBlockConversionBlockElement
The entity being initialized is a field of block descriptor for the copied-in lambda object that's us...
@ EK_Member
The entity being initialized is a non-static data member subobject.
@ EK_Base
The entity being initialized is a base member subobject.
@ EK_Result
The entity being initialized is the result of a function call.
@ EK_TemplateParameter
The entity being initialized is a non-type template parameter.
@ EK_StmtExprResult
The entity being initialized is the result of a statement expression.
@ EK_ParenAggInitMember
The entity being initialized is a non-static data member subobject of an object initialized via paren...
@ EK_VectorElement
The entity being initialized is an element of a vector.
@ EK_New
The entity being initialized is an object (or array of objects) allocated via new.
@ EK_CompoundLiteralInit
The entity being initialized is the initializer for a compound literal.
@ EK_Parameter
The entity being initialized is a function parameter.
@ EK_Delegating
The initialization is being done by a delegating constructor.
@ EK_ComplexElement
The entity being initialized is the real or imaginary part of a complex number.
@ EK_ArrayElement
The entity being initialized is an element of an array.
@ EK_LambdaCapture
The entity being initialized is the field that captures a variable in a lambda.
@ EK_Exception
The entity being initialized is an exception object that is being thrown.
@ EK_RelatedResult
The entity being implicitly initialized back to the formal result type.
bool isDefaultMemberInitializer() const
Is this the default member initializer of a member (specified inside the class definition)?
Describes the capture of a variable or of this, or of a C++1y init-capture.
Definition: LambdaCapture.h:25
bool capturesVariable() const
Determine whether this capture handles a variable.
Definition: LambdaCapture.h:88
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
A (possibly-)qualified type.
Definition: Type.h:941
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:535
DiagnosticsEngine & getDiagnostics() const
Definition: Sema.h:597
const LangOptions & getLangOpts() const
Definition: Sema.h:593
static bool CanBeGetReturnObject(const FunctionDecl *FD)
Definition: SemaDecl.cpp:15789
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
Definition: TypeLoc.h:2684
A container of type source information.
Definition: Type.h:7721
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
The base class of the type hierarchy.
Definition: Type.h:1829
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1882
bool isPointerType() const
Definition: Type.h:8003
bool isReferenceType() const
Definition: Type.h:8021
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
Definition: Type.cpp:1867
bool isLValueReferenceType() const
Definition: Type.h:8025
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2188
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:667
QualType getType() const
Definition: Decl.h:678
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Definition: Decl.cpp:5357
Represents a variable declaration or definition.
Definition: Decl.h:879
static bool pathContainsInit(IndirectLocalPath &Path)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, Expr *Init, bool EnableLifetimeWarnings)
static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD)
void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for initializing the ent...
static bool isInStlNamespace(const Decl *D)
static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
static bool isRecordWithAttr(QualType Type)
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits, bool EnableLifetimeWarnings)
Visit the locals that would be reachable through an object initialized by the prvalue expression Init...
static bool shouldTrackFirstArgument(const FunctionDecl *FD)
static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit, bool EnableLifetimeWarnings)
Visit the locals that would be reachable through a reference bound to the glvalue expression Init.
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, Expr *E)
Find the range for the first interesting entry in the path at or after I.
static LifetimeResult getEntityLifetime(const InitializedEntity *Entity, const InitializedEntity *InitField=nullptr)
Determine the declaration which an initialized entity ultimately refers to, for the purpose of lifeti...
PathLifetimeKind
Whether a path to an object supports lifetime extension.
@ NoExtend
Do not lifetime extend along this path.
@ ShouldExtend
We should lifetime-extend, but we don't because (due to technical limitations) we can't.
@ Extend
Lifetime-extend along this path.
static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path)
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee)
static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path)
Determine whether this is an indirect path to a temporary that we are supposed to lifetime-extend alo...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
bool isCompoundAssignmentOperator(OverloadedOperatorKind Kind)
Determine if this is a compound assignment operator.
Definition: OperatorKinds.h:53
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
Definition: CharInfo.h:126
@ LCK_ByRef
Capturing by reference.
Definition: Lambda.h:37
BinaryOperatorKind
const FunctionProtoType * T
#define bool
Definition: stdbool.h:24
Describes an entity that is being assigned.