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"
12#include "clang/AST/Type.h"
13#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"
14#include "clang/Basic/DiagnosticSema.h"
15#include "clang/Sema/Initialization.h"
16#include "clang/Sema/Sema.h"
17#include "llvm/ADT/PointerIntPair.h"
18
19namespace clang::sema {
20using lifetimes::isGslOwnerType;
21using lifetimes::isGslPointerType;
22
23namespace {
24enum LifetimeKind {
25 /// The lifetime of a temporary bound to this entity ends at the end of the
26 /// full-expression, and that's (probably) fine.
27 LK_FullExpression,
28
29 /// The lifetime of a temporary bound to this entity is extended to the
30 /// lifeitme of the entity itself.
31 LK_Extended,
32
33 /// The lifetime of a temporary bound to this entity probably ends too soon,
34 /// because the entity is allocated in a new-expression.
35 LK_New,
36
37 /// The lifetime of a temporary bound to this entity ends too soon, because
38 /// the entity is a return object.
39 LK_Return,
40
41 /// The lifetime of a temporary bound to this entity ends too soon, because
42 /// the entity passed to a musttail function call.
43 LK_MustTail,
44
45 /// The lifetime of a temporary bound to this entity ends too soon, because
46 /// the entity is the result of a statement expression.
47 LK_StmtExprResult,
48
49 /// This is a mem-initializer: if it would extend a temporary (other than via
50 /// a default member initializer), the program is ill-formed.
51 LK_MemInitializer,
52
53 /// The lifetime of a temporary bound to this entity may end too soon,
54 /// because the entity is a pointer and we assign the address of a temporary
55 /// object to it.
56 LK_Assignment,
57
58 /// The lifetime of a temporary bound to this entity may end too soon,
59 /// because the entity may capture the reference to a temporary object.
60 LK_LifetimeCapture,
61};
62using LifetimeResult =
63 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
64} // namespace
65
66/// Determine the declaration which an initialized entity ultimately refers to,
67/// for the purpose of lifetime-extending a temporary bound to a reference in
68/// the initialization of \p Entity.
69static LifetimeResult
70getEntityLifetime(const InitializedEntity *Entity,
71 const InitializedEntity *InitField = nullptr) {
72 // C++11 [class.temporary]p5:
73 switch (Entity->getKind()) {
74 case InitializedEntity::EK_Variable:
75 // The temporary [...] persists for the lifetime of the reference
76 return {Entity, LK_Extended};
77
78 case InitializedEntity::EK_Member:
79 // For subobjects, we look at the complete object.
80 if (Entity->getParent())
81 return getEntityLifetime(Entity: Entity->getParent(), InitField: Entity);
82
83 // except:
84 // C++17 [class.base.init]p8:
85 // A temporary expression bound to a reference member in a
86 // mem-initializer is ill-formed.
87 // C++17 [class.base.init]p11:
88 // A temporary expression bound to a reference member from a
89 // default member initializer is ill-formed.
90 //
91 // The context of p11 and its example suggest that it's only the use of a
92 // default member initializer from a constructor that makes the program
93 // ill-formed, not its mere existence, and that it can even be used by
94 // aggregate initialization.
95 return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
96 : LK_MemInitializer};
97
98 case InitializedEntity::EK_Binding:
99 // Per [dcl.decomp]p3, the binding is treated as a variable of reference
100 // type.
101 return {Entity, LK_Extended};
102
103 case InitializedEntity::EK_Parameter:
104 case InitializedEntity::EK_Parameter_CF_Audited:
105 // -- A temporary bound to a reference parameter in a function call
106 // persists until the completion of the full-expression containing
107 // the call.
108 return {nullptr, LK_FullExpression};
109
110 case InitializedEntity::EK_TemplateParameter:
111 // FIXME: This will always be ill-formed; should we eagerly diagnose it
112 // here?
113 return {nullptr, LK_FullExpression};
114
115 case InitializedEntity::EK_Result:
116 // -- The lifetime of a temporary bound to the returned value in a
117 // function return statement is not extended; the temporary is
118 // destroyed at the end of the full-expression in the return statement.
119 return {nullptr, LK_Return};
120
121 case InitializedEntity::EK_StmtExprResult:
122 // FIXME: Should we lifetime-extend through the result of a statement
123 // expression?
124 return {nullptr, LK_StmtExprResult};
125
126 case InitializedEntity::EK_New:
127 // -- A temporary bound to a reference in a new-initializer persists
128 // until the completion of the full-expression containing the
129 // new-initializer.
130 return {nullptr, LK_New};
131
132 case InitializedEntity::EK_Temporary:
133 case InitializedEntity::EK_CompoundLiteralInit:
134 case InitializedEntity::EK_RelatedResult:
135 // We don't yet know the storage duration of the surrounding temporary.
136 // Assume it's got full-expression duration for now, it will patch up our
137 // storage duration if that's not correct.
138 return {nullptr, LK_FullExpression};
139
140 case InitializedEntity::EK_ArrayElement:
141 // For subobjects, we look at the complete object.
142 return getEntityLifetime(Entity: Entity->getParent(), InitField);
143
144 case InitializedEntity::EK_Base:
145 // For subobjects, we look at the complete object.
146 if (Entity->getParent())
147 return getEntityLifetime(Entity: Entity->getParent(), InitField);
148 return {InitField, LK_MemInitializer};
149
150 case InitializedEntity::EK_Delegating:
151 // We can reach this case for aggregate initialization in a constructor:
152 // struct A { int &&r; };
153 // struct B : A { B() : A{0} {} };
154 // In this case, use the outermost field decl as the context.
155 return {InitField, LK_MemInitializer};
156
157 case InitializedEntity::EK_BlockElement:
158 case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
159 case InitializedEntity::EK_LambdaCapture:
160 case InitializedEntity::EK_VectorElement:
161 case InitializedEntity::EK_MatrixElement:
162 case InitializedEntity::EK_ComplexElement:
163 return {nullptr, LK_FullExpression};
164
165 case InitializedEntity::EK_Exception:
166 // FIXME: Can we diagnose lifetime problems with exceptions?
167 return {nullptr, LK_FullExpression};
168
169 case InitializedEntity::EK_ParenAggInitMember:
170 // -- A temporary object bound to a reference element of an aggregate of
171 // class type initialized from a parenthesized expression-list
172 // [dcl.init, 9.3] persists until the completion of the full-expression
173 // containing the expression-list.
174 return {nullptr, LK_FullExpression};
175 }
176
177 llvm_unreachable("unknown entity kind");
178}
179
180namespace {
181enum ReferenceKind {
182 /// Lifetime would be extended by a reference binding to a temporary.
183 RK_ReferenceBinding,
184 /// Lifetime would be extended by a std::initializer_list object binding to
185 /// its backing array.
186 RK_StdInitializerList,
187};
188
189/// A temporary or local variable. This will be one of:
190/// * A MaterializeTemporaryExpr.
191/// * A DeclRefExpr whose declaration is a local.
192/// * An AddrLabelExpr.
193/// * A BlockExpr for a block with captures.
194using Local = Expr *;
195
196/// Expressions we stepped over when looking for the local state. Any steps
197/// that would inhibit lifetime extension or take us out of subexpressions of
198/// the initializer are included.
199struct IndirectLocalPathEntry {
200 enum EntryKind {
201 DefaultInit,
202 AddressOf,
203 VarInit,
204 LValToRVal,
205 LifetimeBoundCall,
206 TemporaryCopy,
207 LambdaCaptureInit,
208 MemberExpr,
209 GslReferenceInit,
210 GslPointerInit,
211 GslPointerAssignment,
212 DefaultArg,
213 ParenAggInit,
214 } Kind;
215 Expr *E;
216 union {
217 const Decl *D = nullptr;
218 const LambdaCapture *Capture;
219 };
220 IndirectLocalPathEntry() {}
221 IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
222 IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
223 : Kind(K), E(E), D(D) {}
224 IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
225 : Kind(K), E(E), Capture(Capture) {}
226};
227
228using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
229
230struct RevertToOldSizeRAII {
231 IndirectLocalPath &Path;
232 unsigned OldSize = Path.size();
233 RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
234 ~RevertToOldSizeRAII() { Path.resize(N: OldSize); }
235};
236
237using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
238 ReferenceKind RK)>;
239} // namespace
240
241static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD) {
242 for (auto E : Path)
243 if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
244 return true;
245 return false;
246}
247
248static bool pathContainsInit(const IndirectLocalPath &Path) {
249 return llvm::any_of(Range: Path, P: [=](IndirectLocalPathEntry E) {
250 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
251 E.Kind == IndirectLocalPathEntry::VarInit;
252 });
253}
254
255static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
256 Expr *Init, LocalVisitor Visit,
257 bool RevisitSubinits);
258
259static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
260 Expr *Init, ReferenceKind RK,
261 LocalVisitor Visit);
262
263// Returns true if the given Record decl is a form of `GSLOwner<Pointer>`
264// type, e.g. std::vector<string_view>, std::optional<string_view>.
265static bool isContainerOfPointer(const RecordDecl *Container) {
266 if (const auto *CTSD =
267 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Val: Container)) {
268 if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
269 return false;
270 const auto &TAs = CTSD->getTemplateArgs();
271 return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
272 lifetimes::isPointerLikeType(QT: TAs[0].getAsType());
273 }
274 return false;
275}
276static bool isContainerOfOwner(const RecordDecl *Container) {
277 const auto *CTSD =
278 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Val: Container);
279 if (!CTSD)
280 return false;
281 if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
282 return false;
283 const auto &TAs = CTSD->getTemplateArgs();
284 return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
285 isGslOwnerType(QT: TAs[0].getAsType());
286}
287
288// Returns true if the given Record is `std::initializer_list<pointer>`.
289static bool isStdInitializerListOfPointer(const RecordDecl *RD) {
290 if (const auto *CTSD =
291 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Val: RD)) {
292 const auto &TAs = CTSD->getTemplateArgs();
293 return lifetimes::isInStlNamespace(D: RD) && RD->getIdentifier() &&
294 RD->getName() == "initializer_list" && TAs.size() > 0 &&
295 TAs[0].getKind() == TemplateArgument::Type &&
296 lifetimes::isPointerLikeType(QT: TAs[0].getAsType());
297 }
298 return false;
299}
300
301// Returns true if the given constructor is a copy-like constructor, such as
302// `Ctor(Owner<U>&&)` or `Ctor(const Owner<U>&)`.
303static bool isCopyLikeConstructor(const CXXConstructorDecl *Ctor) {
304 if (!Ctor || Ctor->param_size() != 1)
305 return false;
306 const auto *ParamRefType =
307 Ctor->getParamDecl(i: 0)->getType()->getAs<ReferenceType>();
308 if (!ParamRefType)
309 return false;
310
311 // Check if the first parameter type is "Owner<U>".
312 if (const auto *TST =
313 ParamRefType->getPointeeType()->getAs<TemplateSpecializationType>())
314 return TST->getTemplateName()
315 .getAsTemplateDecl()
316 ->getTemplatedDecl()
317 ->hasAttr<OwnerAttr>();
318 return false;
319}
320
321// Returns true if we should perform the GSL analysis on the first argument for
322// the given constructor.
323static bool
324shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor) {
325 const auto *LHSRecordDecl = Ctor->getConstructor()->getParent();
326
327 // Case 1, construct a GSL pointer, e.g. std::string_view
328 // Always inspect when LHS is a pointer.
329 if (LHSRecordDecl->hasAttr<PointerAttr>())
330 return true;
331
332 if (Ctor->getConstructor()->param_empty() ||
333 !isContainerOfPointer(Container: LHSRecordDecl))
334 return false;
335
336 // Now, the LHS is an Owner<Pointer> type, e.g., std::vector<string_view>.
337 //
338 // At a high level, we cannot precisely determine what the nested pointer
339 // owns. However, by analyzing the RHS owner type, we can use heuristics to
340 // infer ownership information. These heuristics are designed to be
341 // conservative, minimizing false positives while still providing meaningful
342 // diagnostics.
343 //
344 // While this inference isn't perfect, it helps catch common use-after-free
345 // patterns.
346 auto RHSArgType = Ctor->getArg(Arg: 0)->getType();
347 const auto *RHSRD = RHSArgType->getAsRecordDecl();
348 // LHS is constructed from an initializer_list.
349 //
350 // std::initializer_list is a proxy object that provides access to the backing
351 // array. We perform analysis on it to determine if there are any dangling
352 // temporaries in the backing array.
353 // E.g. std::vector<string_view> abc = {string()};
354 if (isStdInitializerListOfPointer(RD: RHSRD))
355 return true;
356
357 // RHS must be an owner.
358 if (!isGslOwnerType(QT: RHSArgType))
359 return false;
360
361 // Bail out if the RHS is Owner<Pointer>.
362 //
363 // We cannot reliably determine what the LHS nested pointer owns -- it could
364 // be the entire RHS or the nested pointer in RHS. To avoid false positives,
365 // we skip this case, such as:
366 // std::stack<std::string_view> s(std::deque<std::string_view>{});
367 //
368 // TODO: this also has a false negative, it doesn't catch the case like:
369 // std::optional<span<int*>> os = std::vector<int*>{}
370 if (isContainerOfPointer(Container: RHSRD))
371 return false;
372
373 // Assume that the nested Pointer is constructed from the nested Owner.
374 // E.g. std::optional<string_view> sv = std::optional<string>(s);
375 if (isContainerOfOwner(Container: RHSRD))
376 return true;
377
378 // Now, the LHS is an Owner<Pointer> and the RHS is an Owner<X>, where X is
379 // neither an `Owner` nor a `Pointer`.
380 //
381 // Use the constructor's signature as a hint. If it is a copy-like constructor
382 // `Owner1<Pointer>(Owner2<X>&&)`, we assume that the nested pointer is
383 // constructed from X. In such cases, we do not diagnose, as `X` is not an
384 // owner, e.g.
385 // std::optional<string_view> sv = std::optional<Foo>();
386 if (const auto *PrimaryCtorTemplate =
387 Ctor->getConstructor()->getPrimaryTemplate();
388 PrimaryCtorTemplate &&
389 isCopyLikeConstructor(Ctor: dyn_cast_if_present<CXXConstructorDecl>(
390 Val: PrimaryCtorTemplate->getTemplatedDecl()))) {
391 return false;
392 }
393 // Assume that the nested pointer is constructed from the whole RHS.
394 // E.g. optional<string_view> s = std::string();
395 return true;
396}
397
398// Visit lifetimebound or gsl-pointer arguments.
399static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
400 LocalVisitor Visit) {
401 const FunctionDecl *Callee;
402 ArrayRef<Expr *> Args;
403
404 if (auto *CE = dyn_cast<CallExpr>(Val: Call)) {
405 Callee = CE->getDirectCallee();
406 Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
407 } else {
408 auto *CCE = cast<CXXConstructExpr>(Val: Call);
409 Callee = CCE->getConstructor();
410 Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
411 }
412 if (!Callee)
413 return;
414
415 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
416 DiagID: diag::warn_dangling_lifetime_pointer, Loc: SourceLocation());
417 Expr *ObjectArg = nullptr;
418 if (isa<CXXOperatorCallExpr>(Val: Call) && Callee->isCXXInstanceMember()) {
419 ObjectArg = Args[0];
420 Args = Args.slice(N: 1);
421 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: Call)) {
422 ObjectArg = MCE->getImplicitObjectArgument();
423 }
424
425 auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
426 Path.push_back(Elt: {IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
427 if (Arg->isGLValue())
428 visitLocalsRetainedByReferenceBinding(Path, Init: Arg, RK: RK_ReferenceBinding,
429 Visit);
430 else
431 visitLocalsRetainedByInitializer(Path, Init: Arg, Visit, RevisitSubinits: true);
432 Path.pop_back();
433 };
434 auto VisitGSLPointerArg = [&](const FunctionDecl *Callee, Expr *Arg) {
435 auto ReturnType = Callee->getReturnType();
436
437 // Once we initialized a value with a non gsl-owner reference, it can no
438 // longer dangle.
439 if (ReturnType->isReferenceType() &&
440 !isGslOwnerType(QT: ReturnType->getPointeeType())) {
441 for (const IndirectLocalPathEntry &PE : llvm::reverse(C&: Path)) {
442 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
443 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
444 continue;
445 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
446 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
447 return;
448 break;
449 }
450 }
451 Path.push_back(Elt: {ReturnType->isReferenceType()
452 ? IndirectLocalPathEntry::GslReferenceInit
453 : IndirectLocalPathEntry::GslPointerInit,
454 Arg, Callee});
455 if (Arg->isGLValue())
456 visitLocalsRetainedByReferenceBinding(Path, Init: Arg, RK: RK_ReferenceBinding,
457 Visit);
458 else
459 visitLocalsRetainedByInitializer(Path, Init: Arg, Visit, RevisitSubinits: true);
460 Path.pop_back();
461 };
462
463 bool CheckCoroCall = false;
464 if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
465 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
466 RD->hasAttr<CoroReturnTypeAttr>() &&
467 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
468 }
469
470 if (ObjectArg) {
471 bool CheckCoroObjArg = CheckCoroCall;
472 // Coroutine lambda objects with empty capture list are not lifetimebound.
473 if (auto *LE = dyn_cast<LambdaExpr>(Val: ObjectArg->IgnoreImplicit());
474 LE && LE->captures().empty())
475 CheckCoroObjArg = false;
476 // Allow `get_return_object()` as the object param (__promise) is not
477 // lifetimebound.
478 if (Sema::CanBeGetReturnObject(FD: Callee))
479 CheckCoroObjArg = false;
480 if (lifetimes::implicitObjectParamIsLifetimeBound(FD: Callee) ||
481 CheckCoroObjArg)
482 VisitLifetimeBoundArg(Callee, ObjectArg);
483 else if (EnableGSLAnalysis) {
484 if (auto *CME = dyn_cast<CXXMethodDecl>(Val: Callee);
485 CME && lifetimes::shouldTrackImplicitObjectArg(
486 ImplicitObjectArgument: *ObjectArg, Callee: CME, /*RunningUnderLifetimeSafety=*/false))
487 VisitGSLPointerArg(Callee, ObjectArg);
488 }
489 }
490
491 const FunctionDecl *CanonCallee =
492 lifetimes::getDeclWithMergedLifetimeBoundAttrs(FD: Callee);
493 unsigned NP = std::min(a: Callee->getNumParams(), b: CanonCallee->getNumParams());
494 for (unsigned I = 0, N = std::min<unsigned>(a: NP, b: Args.size()); I != N; ++I) {
495 Expr *Arg = Args[I];
496 RevertToOldSizeRAII RAII(Path);
497 if (auto *DAE = dyn_cast<CXXDefaultArgExpr>(Val: Arg)) {
498 Path.push_back(
499 Elt: {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
500 Arg = DAE->getExpr();
501 }
502 if (CheckCoroCall ||
503 CanonCallee->getParamDecl(i: I)->hasAttr<LifetimeBoundAttr>())
504 VisitLifetimeBoundArg(CanonCallee->getParamDecl(i: I), Arg);
505 else if (isa<CXXConstructorDecl>(Val: CanonCallee) &&
506 llvm::any_of(Range: CanonCallee->getParamDecl(i: I)
507 ->specific_attrs<LifetimeCaptureByAttr>(),
508 P: [](const LifetimeCaptureByAttr *CaptureAttr) {
509 return llvm::is_contained(
510 Range: CaptureAttr->params(),
511 Element: LifetimeCaptureByAttr::This);
512 }))
513 // `lifetime_capture_by(this)` in a class constructor has the same
514 // semantics as `lifetimebound`:
515 //
516 // struct Foo {
517 // const int& a;
518 // // Equivalent to Foo(const int& t [[clang::lifetimebound]])
519 // Foo(const int& t [[clang::lifetime_capture_by(this)]]) : a(t) {}
520 // };
521 //
522 // In the implementation, `lifetime_capture_by` is treated as an alias for
523 // `lifetimebound` and shares the same code path. This implies the emitted
524 // diagnostics will be emitted under `-Wdangling`, not
525 // `-Wdangling-capture`.
526 VisitLifetimeBoundArg(CanonCallee->getParamDecl(i: I), Arg);
527 else if (EnableGSLAnalysis && I == 0) {
528 // Perform GSL analysis for the first argument
529 if (lifetimes::shouldTrackFirstArgument(FD: CanonCallee)) {
530 VisitGSLPointerArg(CanonCallee, Arg);
531 } else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Val: Call);
532 Ctor && shouldTrackFirstArgumentForConstructor(Ctor)) {
533 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
534 }
535 }
536 }
537}
538
539/// Visit the locals that would be reachable through a reference bound to the
540/// glvalue expression \c Init.
541static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
542 Expr *Init, ReferenceKind RK,
543 LocalVisitor Visit) {
544 RevertToOldSizeRAII RAII(Path);
545
546 // Walk past any constructs which we can lifetime-extend across.
547 Expr *Old;
548 do {
549 Old = Init;
550
551 if (auto *FE = dyn_cast<FullExpr>(Val: Init))
552 Init = FE->getSubExpr();
553
554 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Val: Init)) {
555 // If this is just redundant braces around an initializer, step over it.
556 if (ILE->isTransparent())
557 Init = ILE->getInit(Init: 0);
558 }
559
560 if (MemberExpr *ME = dyn_cast<MemberExpr>(Val: Init->IgnoreImpCasts()))
561 Path.push_back(
562 Elt: {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
563 // Step over any subobject adjustments; we may have a materialized
564 // temporary inside them.
565 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
566
567 // Per current approach for DR1376, look through casts to reference type
568 // when performing lifetime extension.
569 if (CastExpr *CE = dyn_cast<CastExpr>(Val: Init))
570 if (CE->getSubExpr()->isGLValue())
571 Init = CE->getSubExpr();
572
573 // Per the current approach for DR1299, look through array element access
574 // on array glvalues when performing lifetime extension.
575 if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: Init)) {
576 Init = ASE->getBase();
577 auto *ICE = dyn_cast<ImplicitCastExpr>(Val: Init);
578 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
579 Init = ICE->getSubExpr();
580 else
581 // We can't lifetime extend through this but we might still find some
582 // retained temporaries.
583 return visitLocalsRetainedByInitializer(Path, Init, Visit, RevisitSubinits: true);
584 }
585
586 // Step into CXXDefaultInitExprs so we can diagnose cases where a
587 // constructor inherits one as an implicit mem-initializer.
588 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Val: Init)) {
589 Path.push_back(
590 Elt: {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
591 Init = DIE->getExpr();
592 }
593 } while (Init != Old);
594
595 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: Init)) {
596 if (Visit(Path, Local(MTE), RK))
597 visitLocalsRetainedByInitializer(Path, Init: MTE->getSubExpr(), Visit, RevisitSubinits: true);
598 }
599
600 if (auto *M = dyn_cast<MemberExpr>(Val: Init)) {
601 // Lifetime of a non-reference type field is same as base object.
602 if (auto *F = dyn_cast<FieldDecl>(Val: M->getMemberDecl());
603 F && !F->getType()->isReferenceType())
604 visitLocalsRetainedByInitializer(Path, Init: M->getBase(), Visit, RevisitSubinits: true);
605 }
606
607 if (isa<CallExpr>(Val: Init))
608 return visitFunctionCallArguments(Path, Call: Init, Visit);
609
610 switch (Init->getStmtClass()) {
611 case Stmt::DeclRefExprClass: {
612 // If we find the name of a local non-reference parameter, we could have a
613 // lifetime problem.
614 auto *DRE = cast<DeclRefExpr>(Val: Init);
615 auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl());
616 if (VD && VD->hasLocalStorage() &&
617 !DRE->refersToEnclosingVariableOrCapture()) {
618 if (!VD->getType()->isReferenceType()) {
619 Visit(Path, Local(DRE), RK);
620 } else if (isa<ParmVarDecl>(Val: DRE->getDecl())) {
621 // The lifetime of a reference parameter is unknown; assume it's OK
622 // for now.
623 break;
624 } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
625 Path.push_back(Elt: {IndirectLocalPathEntry::VarInit, DRE, VD});
626 visitLocalsRetainedByReferenceBinding(Path, Init: VD->getInit(),
627 RK: RK_ReferenceBinding, Visit);
628 }
629 }
630 break;
631 }
632
633 case Stmt::UnaryOperatorClass: {
634 // The only unary operator that make sense to handle here
635 // is Deref. All others don't resolve to a "name." This includes
636 // handling all sorts of rvalues passed to a unary operator.
637 const UnaryOperator *U = cast<UnaryOperator>(Val: Init);
638 if (U->getOpcode() == UO_Deref)
639 visitLocalsRetainedByInitializer(Path, Init: U->getSubExpr(), Visit, RevisitSubinits: true);
640 break;
641 }
642
643 case Stmt::ArraySectionExprClass: {
644 visitLocalsRetainedByInitializer(
645 Path, Init: cast<ArraySectionExpr>(Val: Init)->getBase(), Visit, RevisitSubinits: true);
646 break;
647 }
648
649 case Stmt::ConditionalOperatorClass:
650 case Stmt::BinaryConditionalOperatorClass: {
651 auto *C = cast<AbstractConditionalOperator>(Val: Init);
652 if (!C->getTrueExpr()->getType()->isVoidType())
653 visitLocalsRetainedByReferenceBinding(Path, Init: C->getTrueExpr(), RK, Visit);
654 if (!C->getFalseExpr()->getType()->isVoidType())
655 visitLocalsRetainedByReferenceBinding(Path, Init: C->getFalseExpr(), RK, Visit);
656 break;
657 }
658
659 case Stmt::CompoundLiteralExprClass: {
660 if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Val: Init)) {
661 if (!CLE->isFileScope())
662 Visit(Path, Local(CLE), RK);
663 }
664 break;
665 }
666
667 // FIXME: Visit the left-hand side of an -> or ->*.
668
669 default:
670 break;
671 }
672}
673
674/// Visit the locals that would be reachable through an object initialized by
675/// the prvalue expression \c Init.
676static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
677 Expr *Init, LocalVisitor Visit,
678 bool RevisitSubinits) {
679 RevertToOldSizeRAII RAII(Path);
680
681 Expr *Old;
682 do {
683 Old = Init;
684
685 // Step into CXXDefaultInitExprs so we can diagnose cases where a
686 // constructor inherits one as an implicit mem-initializer.
687 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Val: Init)) {
688 Path.push_back(
689 Elt: {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
690 Init = DIE->getExpr();
691 }
692
693 if (auto *FE = dyn_cast<FullExpr>(Val: Init))
694 Init = FE->getSubExpr();
695
696 // Dig out the expression which constructs the extended temporary.
697 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
698
699 if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Val: Init))
700 Init = BTE->getSubExpr();
701
702 Init = Init->IgnoreParens();
703
704 // Step over value-preserving rvalue casts.
705 if (auto *CE = dyn_cast<CastExpr>(Val: Init)) {
706 switch (CE->getCastKind()) {
707 case CK_LValueToRValue:
708 // If we can match the lvalue to a const object, we can look at its
709 // initializer.
710 Path.push_back(Elt: {IndirectLocalPathEntry::LValToRVal, CE});
711 return visitLocalsRetainedByReferenceBinding(
712 Path, Init, RK: RK_ReferenceBinding,
713 Visit: [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
714 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: L)) {
715 auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl());
716 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
717 !isVarOnPath(Path, VD)) {
718 Path.push_back(Elt: {IndirectLocalPathEntry::VarInit, DRE, VD});
719 visitLocalsRetainedByInitializer(Path, Init: VD->getInit(), Visit,
720 RevisitSubinits: true);
721 }
722 } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: L)) {
723 if (MTE->getType().isConstQualified())
724 visitLocalsRetainedByInitializer(Path, Init: MTE->getSubExpr(),
725 Visit, RevisitSubinits: true);
726 }
727 return false;
728 });
729
730 // We assume that objects can be retained by pointers cast to integers,
731 // but not if the integer is cast to floating-point type or to _Complex.
732 // We assume that casts to 'bool' do not preserve enough information to
733 // retain a local object.
734 case CK_NoOp:
735 case CK_BitCast:
736 case CK_BaseToDerived:
737 case CK_DerivedToBase:
738 case CK_UncheckedDerivedToBase:
739 case CK_Dynamic:
740 case CK_ToUnion:
741 case CK_UserDefinedConversion:
742 case CK_ConstructorConversion:
743 case CK_IntegralToPointer:
744 case CK_PointerToIntegral:
745 case CK_VectorSplat:
746 case CK_IntegralCast:
747 case CK_CPointerToObjCPointerCast:
748 case CK_BlockPointerToObjCPointerCast:
749 case CK_AnyPointerToBlockPointerCast:
750 case CK_AddressSpaceConversion:
751 break;
752
753 case CK_ArrayToPointerDecay:
754 // Model array-to-pointer decay as taking the address of the array
755 // lvalue.
756 Path.push_back(Elt: {IndirectLocalPathEntry::AddressOf, CE});
757 return visitLocalsRetainedByReferenceBinding(
758 Path, Init: CE->getSubExpr(), RK: RK_ReferenceBinding, Visit);
759
760 default:
761 return;
762 }
763
764 Init = CE->getSubExpr();
765 }
766 } while (Old != Init);
767
768 // C++17 [dcl.init.list]p6:
769 // initializing an initializer_list object from the array extends the
770 // lifetime of the array exactly like binding a reference to a temporary.
771 if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Val: Init))
772 return visitLocalsRetainedByReferenceBinding(Path, Init: ILE->getSubExpr(),
773 RK: RK_StdInitializerList, Visit);
774
775 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Val: Init)) {
776 // We already visited the elements of this initializer list while
777 // performing the initialization. Don't visit them again unless we've
778 // changed the lifetime of the initialized entity.
779 if (!RevisitSubinits)
780 return;
781
782 if (ILE->isTransparent())
783 return visitLocalsRetainedByInitializer(Path, Init: ILE->getInit(Init: 0), Visit,
784 RevisitSubinits);
785
786 if (ILE->getType()->isArrayType()) {
787 for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
788 visitLocalsRetainedByInitializer(Path, Init: ILE->getInit(Init: I), Visit,
789 RevisitSubinits);
790 return;
791 }
792
793 if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
794 assert(RD->isAggregate() && "aggregate init on non-aggregate");
795
796 // If we lifetime-extend a braced initializer which is initializing an
797 // aggregate, and that aggregate contains reference members which are
798 // bound to temporaries, those temporaries are also lifetime-extended.
799 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
800 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
801 visitLocalsRetainedByReferenceBinding(Path, Init: ILE->getInit(Init: 0),
802 RK: RK_ReferenceBinding, Visit);
803 else {
804 unsigned Index = 0;
805 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
806 visitLocalsRetainedByInitializer(Path, Init: ILE->getInit(Init: Index), Visit,
807 RevisitSubinits);
808 for (const auto *I : RD->fields()) {
809 if (Index >= ILE->getNumInits())
810 break;
811 if (I->isUnnamedBitField())
812 continue;
813 Expr *SubInit = ILE->getInit(Init: Index);
814 if (I->getType()->isReferenceType())
815 visitLocalsRetainedByReferenceBinding(Path, Init: SubInit,
816 RK: RK_ReferenceBinding, Visit);
817 else
818 // This might be either aggregate-initialization of a member or
819 // initialization of a std::initializer_list object. Regardless,
820 // we should recursively lifetime-extend that initializer.
821 visitLocalsRetainedByInitializer(Path, Init: SubInit, Visit,
822 RevisitSubinits);
823 ++Index;
824 }
825 }
826 }
827 return;
828 }
829
830 // The lifetime of an init-capture is that of the closure object constructed
831 // by a lambda-expression.
832 if (auto *LE = dyn_cast<LambdaExpr>(Val: Init)) {
833 LambdaExpr::capture_iterator CapI = LE->capture_begin();
834 for (Expr *E : LE->capture_inits()) {
835 assert(CapI != LE->capture_end());
836 const LambdaCapture &Cap = *CapI++;
837 if (!E)
838 continue;
839 if (Cap.capturesVariable())
840 Path.push_back(Elt: {IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
841 if (E->isGLValue())
842 visitLocalsRetainedByReferenceBinding(Path, Init: E, RK: RK_ReferenceBinding,
843 Visit);
844 else
845 visitLocalsRetainedByInitializer(Path, Init: E, Visit, RevisitSubinits: true);
846 if (Cap.capturesVariable())
847 Path.pop_back();
848 }
849 }
850
851 // Assume that a copy or move from a temporary references the same objects
852 // that the temporary does.
853 if (auto *CCE = dyn_cast<CXXConstructExpr>(Val: Init)) {
854 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
855 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: CCE->getArg(Arg: 0))) {
856 Expr *Arg = MTE->getSubExpr();
857 Path.push_back(Elt: {IndirectLocalPathEntry::TemporaryCopy, Arg,
858 CCE->getConstructor()});
859 visitLocalsRetainedByInitializer(Path, Init: Arg, Visit, RevisitSubinits: true);
860 Path.pop_back();
861 }
862 }
863 }
864
865 if (isa<CallExpr>(Val: Init) || isa<CXXConstructExpr>(Val: Init))
866 return visitFunctionCallArguments(Path, Call: Init, Visit);
867
868 if (auto *CPE = dyn_cast<CXXParenListInitExpr>(Val: Init)) {
869 RevertToOldSizeRAII RAII(Path);
870 Path.push_back(Elt: {IndirectLocalPathEntry::ParenAggInit, CPE});
871 for (auto *I : CPE->getInitExprs()) {
872 if (I->isGLValue())
873 visitLocalsRetainedByReferenceBinding(Path, Init: I, RK: RK_ReferenceBinding,
874 Visit);
875 else
876 visitLocalsRetainedByInitializer(Path, Init: I, Visit, RevisitSubinits: true);
877 }
878 }
879 switch (Init->getStmtClass()) {
880 case Stmt::UnaryOperatorClass: {
881 auto *UO = cast<UnaryOperator>(Val: Init);
882 // If the initializer is the address of a local, we could have a lifetime
883 // problem.
884 if (UO->getOpcode() == UO_AddrOf) {
885 // If this is &rvalue, then it's ill-formed and we have already diagnosed
886 // it. Don't produce a redundant warning about the lifetime of the
887 // temporary.
888 if (isa<MaterializeTemporaryExpr>(Val: UO->getSubExpr()))
889 return;
890
891 Path.push_back(Elt: {IndirectLocalPathEntry::AddressOf, UO});
892 visitLocalsRetainedByReferenceBinding(Path, Init: UO->getSubExpr(),
893 RK: RK_ReferenceBinding, Visit);
894 }
895 break;
896 }
897
898 case Stmt::BinaryOperatorClass: {
899 // Handle pointer arithmetic.
900 auto *BO = cast<BinaryOperator>(Val: Init);
901 BinaryOperatorKind BOK = BO->getOpcode();
902 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
903 break;
904
905 if (BO->getLHS()->getType()->isPointerType())
906 visitLocalsRetainedByInitializer(Path, Init: BO->getLHS(), Visit, RevisitSubinits: true);
907 else if (BO->getRHS()->getType()->isPointerType())
908 visitLocalsRetainedByInitializer(Path, Init: BO->getRHS(), Visit, RevisitSubinits: true);
909 break;
910 }
911
912 case Stmt::ConditionalOperatorClass:
913 case Stmt::BinaryConditionalOperatorClass: {
914 auto *C = cast<AbstractConditionalOperator>(Val: Init);
915 // In C++, we can have a throw-expression operand, which has 'void' type
916 // and isn't interesting from a lifetime perspective.
917 if (!C->getTrueExpr()->getType()->isVoidType())
918 visitLocalsRetainedByInitializer(Path, Init: C->getTrueExpr(), Visit, RevisitSubinits: true);
919 if (!C->getFalseExpr()->getType()->isVoidType())
920 visitLocalsRetainedByInitializer(Path, Init: C->getFalseExpr(), Visit, RevisitSubinits: true);
921 break;
922 }
923
924 case Stmt::BlockExprClass:
925 if (cast<BlockExpr>(Val: Init)->getBlockDecl()->hasCaptures()) {
926 // This is a local block, whose lifetime is that of the function.
927 Visit(Path, Local(cast<BlockExpr>(Val: Init)), RK_ReferenceBinding);
928 }
929 break;
930
931 case Stmt::AddrLabelExprClass:
932 // We want to warn if the address of a label would escape the function.
933 Visit(Path, Local(cast<AddrLabelExpr>(Val: Init)), RK_ReferenceBinding);
934 break;
935
936 default:
937 break;
938 }
939}
940
941/// Whether a path to an object supports lifetime extension.
942enum PathLifetimeKind {
943 /// Lifetime-extend along this path.
944 Extend,
945 /// Do not lifetime extend along this path.
946 NoExtend
947};
948
949/// Determine whether this is an indirect path to a temporary that we are
950/// supposed to lifetime-extend along.
951static PathLifetimeKind
952shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
953 for (auto Elem : Path) {
954 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
955 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
956 continue;
957 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
958 ? PathLifetimeKind::Extend
959 : PathLifetimeKind::NoExtend;
960 }
961 return PathLifetimeKind::Extend;
962}
963
964/// Find the range for the first interesting entry in the path at or after I.
965static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
966 Expr *E) {
967 for (unsigned N = Path.size(); I != N; ++I) {
968 switch (Path[I].Kind) {
969 case IndirectLocalPathEntry::AddressOf:
970 case IndirectLocalPathEntry::LValToRVal:
971 case IndirectLocalPathEntry::LifetimeBoundCall:
972 case IndirectLocalPathEntry::TemporaryCopy:
973 case IndirectLocalPathEntry::GslReferenceInit:
974 case IndirectLocalPathEntry::GslPointerInit:
975 case IndirectLocalPathEntry::GslPointerAssignment:
976 case IndirectLocalPathEntry::ParenAggInit:
977 case IndirectLocalPathEntry::MemberExpr:
978 // These exist primarily to mark the path as not permitting or
979 // supporting lifetime extension.
980 break;
981
982 case IndirectLocalPathEntry::VarInit:
983 if (cast<VarDecl>(Val: Path[I].D)->isImplicit())
984 return SourceRange();
985 [[fallthrough]];
986 case IndirectLocalPathEntry::DefaultInit:
987 return Path[I].E->getSourceRange();
988
989 case IndirectLocalPathEntry::LambdaCaptureInit:
990 if (!Path[I].Capture->capturesVariable())
991 continue;
992 return Path[I].E->getSourceRange();
993
994 case IndirectLocalPathEntry::DefaultArg:
995 return cast<CXXDefaultArgExpr>(Val: Path[I].E)->getUsedLocation();
996 }
997 }
998 return E->getSourceRange();
999}
1000
1001static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) {
1002 for (const auto &It : llvm::reverse(C: Path)) {
1003 switch (It.Kind) {
1004 case IndirectLocalPathEntry::VarInit:
1005 case IndirectLocalPathEntry::AddressOf:
1006 case IndirectLocalPathEntry::LifetimeBoundCall:
1007 case IndirectLocalPathEntry::MemberExpr:
1008 continue;
1009 case IndirectLocalPathEntry::GslPointerInit:
1010 case IndirectLocalPathEntry::GslReferenceInit:
1011 case IndirectLocalPathEntry::GslPointerAssignment:
1012 return true;
1013 default:
1014 return false;
1015 }
1016 }
1017 return false;
1018}
1019// Result of analyzing the Path for GSLPointer.
1020enum AnalysisResult {
1021 // Path does not correspond to a GSLPointer.
1022 NotGSLPointer,
1023
1024 // A relevant case was identified.
1025 Report,
1026 // Stop the entire traversal.
1027 Abandon,
1028 // Skip this step and continue traversing inner AST nodes.
1029 Skip,
1030};
1031// Analyze cases where a GSLPointer is initialized or assigned from a
1032// temporary owner object.
1033static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path,
1034 Local L, LifetimeKind LK) {
1035 if (!pathOnlyHandlesGslPointer(Path))
1036 return NotGSLPointer;
1037
1038 // At this point, Path represents a series of operations involving a
1039 // GSLPointer, either in the process of initialization or assignment.
1040
1041 // Process temporary base objects for MemberExpr cases, e.g. Temp().field.
1042 for (const auto &E : Path) {
1043 if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
1044 // Avoid interfering with the local base object.
1045 if (pathContainsInit(Path))
1046 return Abandon;
1047
1048 // We are not interested in the temporary base objects of gsl Pointers:
1049 // auto p1 = Temp().ptr; // Here p1 might not dangle.
1050 // However, we want to diagnose for gsl owner fields:
1051 // auto p2 = Temp().owner; // Here p2 is dangling.
1052 if (const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(Val: E.D);
1053 FD && !FD->getType()->isReferenceType() &&
1054 isGslOwnerType(QT: FD->getType()) && LK != LK_MemInitializer) {
1055 return Report;
1056 }
1057 return Abandon;
1058 }
1059 }
1060
1061 // Note: A LifetimeBoundCall can appear interleaved in this sequence.
1062 // For example:
1063 // const std::string& Ref(const std::string& a [[clang::lifetimebound]]);
1064 // string_view abc = Ref(std::string());
1065 // The "Path" is [GSLPointerInit, LifetimeboundCall], where "L" is the
1066 // temporary "std::string()" object. We need to check the return type of the
1067 // function with the lifetimebound attribute.
1068 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1069 // The lifetimebound applies to the implicit object parameter of a method.
1070 const FunctionDecl *FD =
1071 llvm::dyn_cast_or_null<FunctionDecl>(Val: Path.back().D);
1072 // The lifetimebound applies to a function parameter.
1073 if (const auto *PD = llvm::dyn_cast<ParmVarDecl>(Val: Path.back().D))
1074 FD = llvm::dyn_cast<FunctionDecl>(Val: PD->getDeclContext());
1075
1076 if (isa_and_present<CXXConstructorDecl>(Val: FD)) {
1077 // Constructor case: the parameter is annotated with lifetimebound
1078 // e.g., GSLPointer(const S& s [[clang::lifetimebound]])
1079 // We still respect this case even the type S is not an owner.
1080 return Report;
1081 }
1082 // Check the return type, e.g.
1083 // const GSLOwner& func(const Foo& foo [[clang::lifetimebound]])
1084 // GSLOwner* func(cosnt Foo& foo [[clang::lifetimebound]])
1085 // GSLPointer func(const Foo& foo [[clang::lifetimebound]])
1086 if (FD && ((FD->getReturnType()->isPointerOrReferenceType() &&
1087 isGslOwnerType(QT: FD->getReturnType()->getPointeeType())) ||
1088 isGslPointerType(QT: FD->getReturnType())))
1089 return Report;
1090
1091 return Abandon;
1092 }
1093
1094 if (isa<DeclRefExpr>(Val: L)) {
1095 // We do not want to follow the references when returning a pointer
1096 // originating from a local owner to avoid the following false positive:
1097 // int &p = *localUniquePtr;
1098 // someContainer.add(std::move(localUniquePtr));
1099 // return p;
1100 if (!pathContainsInit(Path) && isGslOwnerType(QT: L->getType()))
1101 return Report;
1102 return Abandon;
1103 }
1104
1105 // The GSLPointer is from a temporary object.
1106 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: L);
1107
1108 bool IsGslPtrValueFromGslTempOwner =
1109 MTE && !MTE->getExtendingDecl() && isGslOwnerType(QT: MTE->getType());
1110 // Skipping a chain of initializing gsl::Pointer annotated objects.
1111 // We are looking only for the final source to find out if it was
1112 // a local or temporary owner or the address of a local
1113 // variable/param.
1114 if (!IsGslPtrValueFromGslTempOwner)
1115 return Skip;
1116 return Report;
1117}
1118
1119static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef,
1120 const AssignedEntity &Entity) {
1121 bool EnableGSLAssignmentWarnings = !SemaRef.getDiagnostics().isIgnored(
1122 DiagID: diag::warn_dangling_lifetime_pointer_assignment, Loc: SourceLocation());
1123 return (EnableGSLAssignmentWarnings &&
1124 (isGslPointerType(QT: Entity.LHS->getType()) ||
1125 lifetimes::isAssignmentOperatorLifetimeBound(
1126 CMD: Entity.AssignmentOperator)));
1127}
1128
1129static void
1130checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity,
1131 const InitializedEntity *ExtendingEntity, LifetimeKind LK,
1132 const AssignedEntity *AEntity,
1133 const CapturingEntity *CapEntity, Expr *Init) {
1134 assert(!AEntity || LK == LK_Assignment);
1135 assert(!CapEntity || LK == LK_LifetimeCapture);
1136 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1137 // If this entity doesn't have an interesting lifetime, don't bother looking
1138 // for temporaries within its initializer.
1139 if (LK == LK_FullExpression)
1140 return;
1141
1142 // FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
1143 // functions to a dedicated class.
1144 auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L,
1145 ReferenceKind RK) -> bool {
1146 SourceRange DiagRange = nextPathEntryRange(Path, I: 0, E: L);
1147 SourceLocation DiagLoc = DiagRange.getBegin();
1148
1149 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: L);
1150
1151 bool IsGslPtrValueFromGslTempOwner = true;
1152 switch (analyzePathForGSLPointer(Path, L, LK)) {
1153 case Abandon:
1154 return false;
1155 case Skip:
1156 return true;
1157 case NotGSLPointer:
1158 IsGslPtrValueFromGslTempOwner = false;
1159 [[fallthrough]];
1160 case Report:
1161 break;
1162 }
1163
1164 switch (LK) {
1165 case LK_FullExpression:
1166 llvm_unreachable("already handled this");
1167
1168 case LK_Extended: {
1169 if (!MTE) {
1170 // The initialized entity has lifetime beyond the full-expression,
1171 // and the local entity does too, so don't warn.
1172 //
1173 // FIXME: We should consider warning if a static / thread storage
1174 // duration variable retains an automatic storage duration local.
1175 return false;
1176 }
1177
1178 switch (shouldLifetimeExtendThroughPath(Path)) {
1179 case PathLifetimeKind::Extend:
1180 // Update the storage duration of the materialized temporary.
1181 // FIXME: Rebuild the expression instead of mutating it.
1182 MTE->setExtendingDecl(ExtendedBy: ExtendingEntity->getDecl(),
1183 ManglingNumber: ExtendingEntity->allocateManglingNumber());
1184 // Also visit the temporaries lifetime-extended by this initializer.
1185 return true;
1186
1187 case PathLifetimeKind::NoExtend:
1188 if (SemaRef.getLangOpts().CPlusPlus23 && InitEntity) {
1189 if (const VarDecl *VD =
1190 dyn_cast_if_present<VarDecl>(Val: InitEntity->getDecl());
1191 VD && VD->isCXXForRangeImplicitVar()) {
1192 return false;
1193 }
1194 }
1195
1196 if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
1197 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_lifetime_pointer)
1198 << DiagRange;
1199 return false;
1200 }
1201
1202 // If the path goes through the initialization of a variable or field,
1203 // it can't possibly reach a temporary created in this full-expression.
1204 // We will have already diagnosed any problems with the initializer.
1205 if (pathContainsInit(Path))
1206 return false;
1207
1208 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_variable)
1209 << RK << !InitEntity->getParent()
1210 << ExtendingEntity->getDecl()->isImplicit()
1211 << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
1212 break;
1213 }
1214 break;
1215 }
1216
1217 case LK_LifetimeCapture: {
1218 // The captured entity has lifetime beyond the full-expression,
1219 // and the capturing entity does too, so don't warn.
1220 if (!MTE)
1221 return false;
1222 if (CapEntity->Entity)
1223 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_reference_captured)
1224 << CapEntity->Entity << DiagRange;
1225 else
1226 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_reference_captured_by_unknown)
1227 << DiagRange;
1228 return false;
1229 }
1230
1231 case LK_Assignment: {
1232 if (!MTE || pathContainsInit(Path))
1233 return false;
1234 if (IsGslPtrValueFromGslTempOwner)
1235 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_lifetime_pointer_assignment)
1236 << AEntity->LHS << DiagRange;
1237 else
1238 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_pointer_assignment)
1239 << AEntity->LHS->getType()->isPointerType() << AEntity->LHS
1240 << DiagRange;
1241 return false;
1242 }
1243 case LK_MemInitializer: {
1244 if (MTE) {
1245 // Under C++ DR1696, if a mem-initializer (or a default member
1246 // initializer used by the absence of one) would lifetime-extend a
1247 // temporary, the program is ill-formed.
1248 if (auto *ExtendingDecl =
1249 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1250 if (IsGslPtrValueFromGslTempOwner) {
1251 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_lifetime_pointer_member)
1252 << ExtendingDecl << DiagRange;
1253 SemaRef.Diag(Loc: ExtendingDecl->getLocation(),
1254 DiagID: diag::note_ref_or_ptr_member_declared_here)
1255 << true;
1256 return false;
1257 }
1258 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1259 SemaRef.Diag(Loc: DiagLoc, DiagID: shouldLifetimeExtendThroughPath(Path) !=
1260 PathLifetimeKind::NoExtend
1261 ? diag::err_dangling_member
1262 : diag::warn_dangling_member)
1263 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1264 // Don't bother adding a note pointing to the field if we're inside
1265 // its default member initializer; our primary diagnostic points to
1266 // the same place in that case.
1267 if (Path.empty() ||
1268 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1269 SemaRef.Diag(Loc: ExtendingDecl->getLocation(),
1270 DiagID: diag::note_lifetime_extending_member_declared_here)
1271 << RK << IsSubobjectMember;
1272 }
1273 } else {
1274 // We have a mem-initializer but no particular field within it; this
1275 // is either a base class or a delegating initializer directly
1276 // initializing the base-class from something that doesn't live long
1277 // enough.
1278 //
1279 // FIXME: Warn on this.
1280 return false;
1281 }
1282 } else {
1283 // Paths via a default initializer can only occur during error recovery
1284 // (there's no other way that a default initializer can refer to a
1285 // local). Don't produce a bogus warning on those cases.
1286 if (pathContainsInit(Path))
1287 return false;
1288
1289 auto *DRE = dyn_cast<DeclRefExpr>(Val: L);
1290 // Suppress false positives for code like the one below:
1291 // Ctor(unique_ptr<T> up) : pointer(up.get()), owner(move(up)) {}
1292 // FIXME: move this logic to analyzePathForGSLPointer.
1293 if (DRE && isGslOwnerType(QT: DRE->getType()))
1294 return false;
1295
1296 auto *VD = DRE ? dyn_cast<VarDecl>(Val: DRE->getDecl()) : nullptr;
1297 if (!VD) {
1298 // A member was initialized to a local block.
1299 // FIXME: Warn on this.
1300 return false;
1301 }
1302
1303 if (auto *Member =
1304 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1305 bool IsPointer = !Member->getType()->isReferenceType();
1306 SemaRef.Diag(Loc: DiagLoc,
1307 DiagID: IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1308 : diag::warn_bind_ref_member_to_parameter)
1309 << Member << VD << isa<ParmVarDecl>(Val: VD) << DiagRange;
1310 SemaRef.Diag(Loc: Member->getLocation(),
1311 DiagID: diag::note_ref_or_ptr_member_declared_here)
1312 << (unsigned)IsPointer;
1313 }
1314 }
1315 break;
1316 }
1317
1318 case LK_New:
1319 if (isa<MaterializeTemporaryExpr>(Val: L)) {
1320 if (IsGslPtrValueFromGslTempOwner)
1321 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_dangling_lifetime_pointer)
1322 << DiagRange;
1323 else
1324 SemaRef.Diag(Loc: DiagLoc, DiagID: RK == RK_ReferenceBinding
1325 ? diag::warn_new_dangling_reference
1326 : diag::warn_new_dangling_initializer_list)
1327 << !InitEntity->getParent() << DiagRange;
1328 } else {
1329 // We can't determine if the allocation outlives the local declaration.
1330 return false;
1331 }
1332 break;
1333
1334 case LK_Return:
1335 case LK_MustTail:
1336 case LK_StmtExprResult:
1337 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: L)) {
1338 // We can't determine if the local variable outlives the statement
1339 // expression.
1340 if (LK == LK_StmtExprResult)
1341 return false;
1342 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
1343 if (VD->getType().getAddressSpace() == LangAS::opencl_local)
1344 return false;
1345 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_ret_stack_addr_ref)
1346 << InitEntity->getType()->isReferenceType() << DRE->getDecl()
1347 << isa<ParmVarDecl>(Val: DRE->getDecl()) << (LK == LK_MustTail)
1348 << DiagRange;
1349 } else if (isa<BlockExpr>(Val: L)) {
1350 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::err_ret_local_block) << DiagRange;
1351 } else if (isa<AddrLabelExpr>(Val: L)) {
1352 // Don't warn when returning a label from a statement expression.
1353 // Leaving the scope doesn't end its lifetime.
1354 if (LK == LK_StmtExprResult)
1355 return false;
1356 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_ret_addr_label) << DiagRange;
1357 } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Val: L)) {
1358 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_ret_stack_addr_ref)
1359 << InitEntity->getType()->isReferenceType() << CLE->getInitializer()
1360 << 2 << (LK == LK_MustTail) << DiagRange;
1361 } else {
1362 // P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
1363 // [stmt.return]/p6: In a function whose return type is a reference,
1364 // other than an invented function for std::is_convertible ([meta.rel]),
1365 // a return statement that binds the returned reference to a temporary
1366 // expression ([class.temporary]) is ill-formed.
1367 if (SemaRef.getLangOpts().CPlusPlus26 &&
1368 InitEntity->getType()->isReferenceType())
1369 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::err_ret_local_temp_ref)
1370 << InitEntity->getType()->isReferenceType() << DiagRange;
1371 else if (LK == LK_MustTail)
1372 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_musttail_local_temp_addr_ref)
1373 << InitEntity->getType()->isReferenceType() << DiagRange;
1374 else
1375 SemaRef.Diag(Loc: DiagLoc, DiagID: diag::warn_ret_local_temp_addr_ref)
1376 << InitEntity->getType()->isReferenceType() << DiagRange;
1377 }
1378 break;
1379 }
1380
1381 for (unsigned I = 0; I != Path.size(); ++I) {
1382 auto Elem = Path[I];
1383
1384 switch (Elem.Kind) {
1385 case IndirectLocalPathEntry::AddressOf:
1386 case IndirectLocalPathEntry::LValToRVal:
1387 case IndirectLocalPathEntry::ParenAggInit:
1388 // These exist primarily to mark the path as not permitting or
1389 // supporting lifetime extension.
1390 break;
1391
1392 case IndirectLocalPathEntry::LifetimeBoundCall:
1393 case IndirectLocalPathEntry::TemporaryCopy:
1394 case IndirectLocalPathEntry::MemberExpr:
1395 case IndirectLocalPathEntry::GslPointerInit:
1396 case IndirectLocalPathEntry::GslReferenceInit:
1397 case IndirectLocalPathEntry::GslPointerAssignment:
1398 // FIXME: Consider adding a note for these.
1399 break;
1400
1401 case IndirectLocalPathEntry::DefaultInit: {
1402 auto *FD = cast<FieldDecl>(Val: Elem.D);
1403 SemaRef.Diag(Loc: FD->getLocation(),
1404 DiagID: diag::note_init_with_default_member_initializer)
1405 << FD << nextPathEntryRange(Path, I: I + 1, E: L);
1406 break;
1407 }
1408
1409 case IndirectLocalPathEntry::VarInit: {
1410 const VarDecl *VD = cast<VarDecl>(Val: Elem.D);
1411 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_local_var_initializer)
1412 << VD->getType()->isReferenceType() << VD->isImplicit()
1413 << VD->getDeclName() << nextPathEntryRange(Path, I: I + 1, E: L);
1414 break;
1415 }
1416
1417 case IndirectLocalPathEntry::LambdaCaptureInit: {
1418 if (!Elem.Capture->capturesVariable())
1419 break;
1420 // FIXME: We can't easily tell apart an init-capture from a nested
1421 // capture of an init-capture.
1422 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1423 SemaRef.Diag(Loc: Elem.Capture->getLocation(),
1424 DiagID: diag::note_lambda_capture_initializer)
1425 << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
1426 << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
1427 << nextPathEntryRange(Path, I: I + 1, E: L);
1428 break;
1429 }
1430
1431 case IndirectLocalPathEntry::DefaultArg: {
1432 const auto *DAE = cast<CXXDefaultArgExpr>(Val: Elem.E);
1433 const ParmVarDecl *Param = DAE->getParam();
1434 SemaRef.Diag(Loc: Param->getDefaultArgRange().getBegin(),
1435 DiagID: diag::note_init_with_default_argument)
1436 << Param << nextPathEntryRange(Path, I: I + 1, E: L);
1437 break;
1438 }
1439 }
1440 }
1441
1442 // We didn't lifetime-extend, so don't go any further; we don't need more
1443 // warnings or errors on inner temporaries within this one's initializer.
1444 return false;
1445 };
1446
1447 llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
1448 switch (LK) {
1449 case LK_Assignment: {
1450 if (shouldRunGSLAssignmentAnalysis(SemaRef, Entity: *AEntity))
1451 Path.push_back(Elt: {lifetimes::isAssignmentOperatorLifetimeBound(
1452 CMD: AEntity->AssignmentOperator)
1453 ? IndirectLocalPathEntry::LifetimeBoundCall
1454 : IndirectLocalPathEntry::GslPointerAssignment,
1455 Init});
1456 break;
1457 }
1458 case LK_LifetimeCapture: {
1459 if (lifetimes::isPointerLikeType(QT: Init->getType()))
1460 Path.push_back(Elt: {IndirectLocalPathEntry::GslPointerInit, Init});
1461 break;
1462 }
1463 default:
1464 break;
1465 }
1466
1467 if (Init->isGLValue())
1468 visitLocalsRetainedByReferenceBinding(Path, Init, RK: RK_ReferenceBinding,
1469 Visit: TemporaryVisitor);
1470 else
1471 visitLocalsRetainedByInitializer(
1472 Path, Init, Visit: TemporaryVisitor,
1473 // Don't revisit the sub inits for the initialization case.
1474 /*RevisitSubinits=*/!InitEntity);
1475}
1476
1477void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity,
1478 Expr *Init) {
1479 auto LTResult = getEntityLifetime(Entity: &Entity);
1480 LifetimeKind LK = LTResult.getInt();
1481 const InitializedEntity *ExtendingEntity = LTResult.getPointer();
1482 checkExprLifetimeImpl(SemaRef, InitEntity: &Entity, ExtendingEntity, LK,
1483 /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init);
1484}
1485
1486void checkExprLifetimeMustTailArg(Sema &SemaRef,
1487 const InitializedEntity &Entity, Expr *Init) {
1488 checkExprLifetimeImpl(SemaRef, InitEntity: &Entity, ExtendingEntity: nullptr, LK: LK_MustTail,
1489 /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init);
1490}
1491
1492void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity,
1493 Expr *Init) {
1494 bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics().isIgnored(
1495 DiagID: diag::warn_dangling_pointer_assignment, Loc: SourceLocation());
1496 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1497 Entity.LHS->getType()->isPointerType()) ||
1498 shouldRunGSLAssignmentAnalysis(SemaRef, Entity);
1499
1500 if (!RunAnalysis)
1501 return;
1502
1503 checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
1504 /*ExtendingEntity=*/nullptr, LK: LK_Assignment, AEntity: &Entity,
1505 /*CapEntity=*/nullptr, Init);
1506}
1507
1508void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity,
1509 Expr *Init) {
1510 if (SemaRef.getDiagnostics().isIgnored(DiagID: diag::warn_dangling_reference_captured,
1511 Loc: SourceLocation()) &&
1512 SemaRef.getDiagnostics().isIgnored(
1513 DiagID: diag::warn_dangling_reference_captured_by_unknown, Loc: SourceLocation()))
1514 return;
1515 return checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
1516 /*ExtendingEntity=*/nullptr, LK: LK_LifetimeCapture,
1517 /*AEntity=*/nullptr,
1518 /*CapEntity=*/&Entity, Init);
1519}
1520
1521} // namespace clang::sema
1522