clang 22.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"
12#include "clang/AST/Type.h"
16#include "clang/Sema/Sema.h"
17#include "llvm/ADT/PointerIntPair.h"
18
19namespace clang::sema {
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
71 const InitializedEntity *InitField = nullptr) {
72 // C++11 [class.temporary]p5:
73 switch (Entity->getKind()) {
75 // The temporary [...] persists for the lifetime of the reference
76 return {Entity, LK_Extended};
77
79 // For subobjects, we look at the complete object.
80 if (Entity->getParent())
81 return getEntityLifetime(Entity->getParent(), 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
99 // Per [dcl.decomp]p3, the binding is treated as a variable of reference
100 // type.
101 return {Entity, LK_Extended};
102
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
111 // FIXME: This will always be ill-formed; should we eagerly diagnose it
112 // here?
113 return {nullptr, LK_FullExpression};
114
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
122 // FIXME: Should we lifetime-extend through the result of a statement
123 // expression?
124 return {nullptr, LK_StmtExprResult};
125
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
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
141 // For subobjects, we look at the complete object.
142 return getEntityLifetime(Entity->getParent(), InitField);
143
145 // For subobjects, we look at the complete object.
146 if (Entity->getParent())
147 return getEntityLifetime(Entity->getParent(), InitField);
148 return {InitField, LK_MemInitializer};
149
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
163 return {nullptr, LK_FullExpression};
164
166 // FIXME: Can we diagnose lifetime problems with exceptions?
167 return {nullptr, LK_FullExpression};
168
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(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(Path, [=](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
264 return isGslPointerType(QT) || QT->isPointerType() || QT->isNullPtrType();
265}
266
267// Decl::isInStdNamespace will return false for iterators in some STL
268// implementations due to them being defined in a namespace outside of the std
269// namespace.
270static bool isInStlNamespace(const Decl *D) {
271 const DeclContext *DC = D->getDeclContext();
272 if (!DC)
273 return false;
274 if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
275 if (const IdentifierInfo *II = ND->getIdentifier()) {
276 StringRef Name = II->getName();
277 if (Name.size() >= 2 && Name.front() == '_' &&
278 (Name[1] == '_' || isUppercase(Name[1])))
279 return true;
280 }
281
282 return DC->isStdNamespace();
283}
284
285// Returns true if the given Record decl is a form of `GSLOwner<Pointer>`
286// type, e.g. std::vector<string_view>, std::optional<string_view>.
287static bool isContainerOfPointer(const RecordDecl *Container) {
288 if (const auto *CTSD =
289 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
290 if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
291 return false;
292 const auto &TAs = CTSD->getTemplateArgs();
293 return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
294 isPointerLikeType(TAs[0].getAsType());
295 }
296 return false;
297}
298static bool isContainerOfOwner(const RecordDecl *Container) {
299 const auto *CTSD =
300 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
301 if (!CTSD)
302 return false;
303 if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
304 return false;
305 const auto &TAs = CTSD->getTemplateArgs();
306 return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
307 isGslOwnerType(TAs[0].getAsType());
308}
309
310// Returns true if the given Record is `std::initializer_list<pointer>`.
312 if (const auto *CTSD =
313 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
314 const auto &TAs = CTSD->getTemplateArgs();
315 return isInStlNamespace(RD) && RD->getIdentifier() &&
316 RD->getName() == "initializer_list" && TAs.size() > 0 &&
317 TAs[0].getKind() == TemplateArgument::Type &&
318 isPointerLikeType(TAs[0].getAsType());
319 }
320 return false;
321}
322
323static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
324 if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
325 if (isGslPointerType(Conv->getConversionType()) &&
326 Callee->getParent()->hasAttr<OwnerAttr>())
327 return true;
328 if (!isInStlNamespace(Callee->getParent()))
329 return false;
330 if (!isGslPointerType(Callee->getFunctionObjectParameterType()) &&
331 !isGslOwnerType(Callee->getFunctionObjectParameterType()))
332 return false;
333 if (isPointerLikeType(Callee->getReturnType())) {
334 if (!Callee->getIdentifier())
335 return false;
336 return llvm::StringSwitch<bool>(Callee->getName())
337 .Cases({"begin", "rbegin", "cbegin", "crbegin"}, true)
338 .Cases({"end", "rend", "cend", "crend"}, true)
339 .Cases({"c_str", "data", "get"}, true)
340 // Map and set types.
341 .Cases({"find", "equal_range", "lower_bound", "upper_bound"}, true)
342 .Default(false);
343 }
344 if (Callee->getReturnType()->isReferenceType()) {
345 if (!Callee->getIdentifier()) {
346 auto OO = Callee->getOverloadedOperator();
347 if (!Callee->getParent()->hasAttr<OwnerAttr>())
348 return false;
349 return OO == OverloadedOperatorKind::OO_Subscript ||
350 OO == OverloadedOperatorKind::OO_Star;
351 }
352 return llvm::StringSwitch<bool>(Callee->getName())
353 .Cases({"front", "back", "at", "top", "value"}, true)
354 .Default(false);
355 }
356 return false;
357}
358
360 if (!FD->getIdentifier() || FD->getNumParams() != 1)
361 return false;
362 const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
363 if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
364 return false;
365 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
366 return false;
367 if (FD->getReturnType()->isPointerType() ||
369 return llvm::StringSwitch<bool>(FD->getName())
370 .Cases({"begin", "rbegin", "cbegin", "crbegin"}, true)
371 .Cases({"end", "rend", "cend", "crend"}, true)
372 .Case("data", true)
373 .Default(false);
374 }
375 if (FD->getReturnType()->isReferenceType()) {
376 return llvm::StringSwitch<bool>(FD->getName())
377 .Cases({"get", "any_cast"}, true)
378 .Default(false);
379 }
380 return false;
381}
382
383// Returns true if the given constructor is a copy-like constructor, such as
384// `Ctor(Owner<U>&&)` or `Ctor(const Owner<U>&)`.
386 if (!Ctor || Ctor->param_size() != 1)
387 return false;
388 const auto *ParamRefType =
389 Ctor->getParamDecl(0)->getType()->getAs<ReferenceType>();
390 if (!ParamRefType)
391 return false;
392
393 // Check if the first parameter type is "Owner<U>".
394 if (const auto *TST =
395 ParamRefType->getPointeeType()->getAs<TemplateSpecializationType>())
396 return TST->getTemplateName()
397 .getAsTemplateDecl()
398 ->getTemplatedDecl()
399 ->hasAttr<OwnerAttr>();
400 return false;
401}
402
403// Returns true if we should perform the GSL analysis on the first argument for
404// the given constructor.
405static bool
407 const auto *LHSRecordDecl = Ctor->getConstructor()->getParent();
408
409 // Case 1, construct a GSL pointer, e.g. std::string_view
410 // Always inspect when LHS is a pointer.
411 if (LHSRecordDecl->hasAttr<PointerAttr>())
412 return true;
413
414 if (Ctor->getConstructor()->param_empty() ||
415 !isContainerOfPointer(LHSRecordDecl))
416 return false;
417
418 // Now, the LHS is an Owner<Pointer> type, e.g., std::vector<string_view>.
419 //
420 // At a high level, we cannot precisely determine what the nested pointer
421 // owns. However, by analyzing the RHS owner type, we can use heuristics to
422 // infer ownership information. These heuristics are designed to be
423 // conservative, minimizing false positives while still providing meaningful
424 // diagnostics.
425 //
426 // While this inference isn't perfect, it helps catch common use-after-free
427 // patterns.
428 auto RHSArgType = Ctor->getArg(0)->getType();
429 const auto *RHSRD = RHSArgType->getAsRecordDecl();
430 // LHS is constructed from an intializer_list.
431 //
432 // std::initializer_list is a proxy object that provides access to the backing
433 // array. We perform analysis on it to determine if there are any dangling
434 // temporaries in the backing array.
435 // E.g. std::vector<string_view> abc = {string()};
437 return true;
438
439 // RHS must be an owner.
440 if (!isGslOwnerType(RHSArgType))
441 return false;
442
443 // Bail out if the RHS is Owner<Pointer>.
444 //
445 // We cannot reliably determine what the LHS nested pointer owns -- it could
446 // be the entire RHS or the nested pointer in RHS. To avoid false positives,
447 // we skip this case, such as:
448 // std::stack<std::string_view> s(std::deque<std::string_view>{});
449 //
450 // TODO: this also has a false negative, it doesn't catch the case like:
451 // std::optional<span<int*>> os = std::vector<int*>{}
452 if (isContainerOfPointer(RHSRD))
453 return false;
454
455 // Assume that the nested Pointer is constructed from the nested Owner.
456 // E.g. std::optional<string_view> sv = std::optional<string>(s);
457 if (isContainerOfOwner(RHSRD))
458 return true;
459
460 // Now, the LHS is an Owner<Pointer> and the RHS is an Owner<X>, where X is
461 // neither an `Owner` nor a `Pointer`.
462 //
463 // Use the constructor's signature as a hint. If it is a copy-like constructor
464 // `Owner1<Pointer>(Owner2<X>&&)`, we assume that the nested pointer is
465 // constructed from X. In such cases, we do not diagnose, as `X` is not an
466 // owner, e.g.
467 // std::optional<string_view> sv = std::optional<Foo>();
468 if (const auto *PrimaryCtorTemplate =
470 PrimaryCtorTemplate &&
471 isCopyLikeConstructor(dyn_cast_if_present<CXXConstructorDecl>(
472 PrimaryCtorTemplate->getTemplatedDecl()))) {
473 return false;
474 }
475 // Assume that the nested pointer is constructed from the whole RHS.
476 // E.g. optional<string_view> s = std::string();
477 return true;
478}
479
480// Visit lifetimebound or gsl-pointer arguments.
481static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
482 LocalVisitor Visit) {
483 const FunctionDecl *Callee;
484 ArrayRef<Expr *> Args;
485
486 if (auto *CE = dyn_cast<CallExpr>(Call)) {
487 Callee = CE->getDirectCallee();
488 Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
489 } else {
490 auto *CCE = cast<CXXConstructExpr>(Call);
491 Callee = CCE->getConstructor();
492 Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
493 }
494 if (!Callee)
495 return;
496
497 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
498 diag::warn_dangling_lifetime_pointer, SourceLocation());
499 Expr *ObjectArg = nullptr;
500 if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
501 ObjectArg = Args[0];
502 Args = Args.slice(1);
503 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
504 ObjectArg = MCE->getImplicitObjectArgument();
505 }
506
507 auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
508 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
509 if (Arg->isGLValue())
510 visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
511 Visit);
512 else
513 visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
514 Path.pop_back();
515 };
516 auto VisitGSLPointerArg = [&](const FunctionDecl *Callee, Expr *Arg) {
517 auto ReturnType = Callee->getReturnType();
518
519 // Once we initialized a value with a non gsl-owner reference, it can no
520 // longer dangle.
521 if (ReturnType->isReferenceType() &&
522 !isGslOwnerType(ReturnType->getPointeeType())) {
523 for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
524 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
525 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
526 continue;
527 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
528 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
529 return;
530 break;
531 }
532 }
533 Path.push_back({ReturnType->isReferenceType()
534 ? IndirectLocalPathEntry::GslReferenceInit
535 : IndirectLocalPathEntry::GslPointerInit,
536 Arg, Callee});
537 if (Arg->isGLValue())
538 visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
539 Visit);
540 else
541 visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
542 Path.pop_back();
543 };
544
545 bool CheckCoroCall = false;
546 if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
547 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
548 RD->hasAttr<CoroReturnTypeAttr>() &&
549 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
550 }
551
552 if (ObjectArg) {
553 bool CheckCoroObjArg = CheckCoroCall;
554 // Coroutine lambda objects with empty capture list are not lifetimebound.
555 if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit());
556 LE && LE->captures().empty())
557 CheckCoroObjArg = false;
558 // Allow `get_return_object()` as the object param (__promise) is not
559 // lifetimebound.
560 if (Sema::CanBeGetReturnObject(Callee))
561 CheckCoroObjArg = false;
563 CheckCoroObjArg)
564 VisitLifetimeBoundArg(Callee, ObjectArg);
565 else if (EnableGSLAnalysis) {
566 if (auto *CME = dyn_cast<CXXMethodDecl>(Callee);
568 VisitGSLPointerArg(Callee, ObjectArg);
569 }
570 }
571
572 const FunctionDecl *CanonCallee =
574 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->getNumParams());
575 for (unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
576 Expr *Arg = Args[I];
577 RevertToOldSizeRAII RAII(Path);
578 if (auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
579 Path.push_back(
580 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
581 Arg = DAE->getExpr();
582 }
583 if (CheckCoroCall ||
584 CanonCallee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
585 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
586 else if (const auto *CaptureAttr =
587 CanonCallee->getParamDecl(I)->getAttr<LifetimeCaptureByAttr>();
588 CaptureAttr && isa<CXXConstructorDecl>(CanonCallee) &&
589 llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
590 return ArgIdx == LifetimeCaptureByAttr::This;
591 }))
592 // `lifetime_capture_by(this)` in a class constructor has the same
593 // semantics as `lifetimebound`:
594 //
595 // struct Foo {
596 // const int& a;
597 // // Equivalent to Foo(const int& t [[clang::lifetimebound]])
598 // Foo(const int& t [[clang::lifetime_capture_by(this)]]) : a(t) {}
599 // };
600 //
601 // In the implementation, `lifetime_capture_by` is treated as an alias for
602 // `lifetimebound` and shares the same code path. This implies the emitted
603 // diagnostics will be emitted under `-Wdangling`, not
604 // `-Wdangling-capture`.
605 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
606 else if (EnableGSLAnalysis && I == 0) {
607 // Perform GSL analysis for the first argument
608 if (shouldTrackFirstArgument(CanonCallee)) {
609 VisitGSLPointerArg(CanonCallee, Arg);
610 } else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Call);
612 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
613 }
614 }
615 }
616}
617
618/// Visit the locals that would be reachable through a reference bound to the
619/// glvalue expression \c Init.
620static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
621 Expr *Init, ReferenceKind RK,
622 LocalVisitor Visit) {
623 RevertToOldSizeRAII RAII(Path);
624
625 // Walk past any constructs which we can lifetime-extend across.
626 Expr *Old;
627 do {
628 Old = Init;
629
630 if (auto *FE = dyn_cast<FullExpr>(Init))
631 Init = FE->getSubExpr();
632
633 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
634 // If this is just redundant braces around an initializer, step over it.
635 if (ILE->isTransparent())
636 Init = ILE->getInit(0);
637 }
638
639 if (MemberExpr *ME = dyn_cast<MemberExpr>(Init->IgnoreImpCasts()))
640 Path.push_back(
641 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
642 // Step over any subobject adjustments; we may have a materialized
643 // temporary inside them.
644 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
645
646 // Per current approach for DR1376, look through casts to reference type
647 // when performing lifetime extension.
648 if (CastExpr *CE = dyn_cast<CastExpr>(Init))
649 if (CE->getSubExpr()->isGLValue())
650 Init = CE->getSubExpr();
651
652 // Per the current approach for DR1299, look through array element access
653 // on array glvalues when performing lifetime extension.
654 if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
655 Init = ASE->getBase();
656 auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
657 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
658 Init = ICE->getSubExpr();
659 else
660 // We can't lifetime extend through this but we might still find some
661 // retained temporaries.
662 return visitLocalsRetainedByInitializer(Path, Init, Visit, true);
663 }
664
665 // Step into CXXDefaultInitExprs so we can diagnose cases where a
666 // constructor inherits one as an implicit mem-initializer.
667 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
668 Path.push_back(
669 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
670 Init = DIE->getExpr();
671 }
672 } while (Init != Old);
673
674 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
675 if (Visit(Path, Local(MTE), RK))
676 visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true);
677 }
678
679 if (auto *M = dyn_cast<MemberExpr>(Init)) {
680 // Lifetime of a non-reference type field is same as base object.
681 if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
682 F && !F->getType()->isReferenceType())
683 visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true);
684 }
685
686 if (isa<CallExpr>(Init))
687 return visitFunctionCallArguments(Path, Init, Visit);
688
689 switch (Init->getStmtClass()) {
690 case Stmt::DeclRefExprClass: {
691 // If we find the name of a local non-reference parameter, we could have a
692 // lifetime problem.
693 auto *DRE = cast<DeclRefExpr>(Init);
694 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
695 if (VD && VD->hasLocalStorage() &&
696 !DRE->refersToEnclosingVariableOrCapture()) {
697 if (!VD->getType()->isReferenceType()) {
698 Visit(Path, Local(DRE), RK);
699 } else if (isa<ParmVarDecl>(DRE->getDecl())) {
700 // The lifetime of a reference parameter is unknown; assume it's OK
701 // for now.
702 break;
703 } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
704 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
705 visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
706 RK_ReferenceBinding, Visit);
707 }
708 }
709 break;
710 }
711
712 case Stmt::UnaryOperatorClass: {
713 // The only unary operator that make sense to handle here
714 // is Deref. All others don't resolve to a "name." This includes
715 // handling all sorts of rvalues passed to a unary operator.
717 if (U->getOpcode() == UO_Deref)
718 visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true);
719 break;
720 }
721
722 case Stmt::ArraySectionExprClass: {
724 Path, cast<ArraySectionExpr>(Init)->getBase(), Visit, true);
725 break;
726 }
727
728 case Stmt::ConditionalOperatorClass:
729 case Stmt::BinaryConditionalOperatorClass: {
731 if (!C->getTrueExpr()->getType()->isVoidType())
732 visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit);
733 if (!C->getFalseExpr()->getType()->isVoidType())
734 visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit);
735 break;
736 }
737
738 case Stmt::CompoundLiteralExprClass: {
739 if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
740 if (!CLE->isFileScope())
741 Visit(Path, Local(CLE), RK);
742 }
743 break;
744 }
745
746 // FIXME: Visit the left-hand side of an -> or ->*.
747
748 default:
749 break;
750 }
751}
752
753/// Visit the locals that would be reachable through an object initialized by
754/// the prvalue expression \c Init.
755static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
756 Expr *Init, LocalVisitor Visit,
757 bool RevisitSubinits) {
758 RevertToOldSizeRAII RAII(Path);
759
760 Expr *Old;
761 do {
762 Old = Init;
763
764 // Step into CXXDefaultInitExprs so we can diagnose cases where a
765 // constructor inherits one as an implicit mem-initializer.
766 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
767 Path.push_back(
768 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
769 Init = DIE->getExpr();
770 }
771
772 if (auto *FE = dyn_cast<FullExpr>(Init))
773 Init = FE->getSubExpr();
774
775 // Dig out the expression which constructs the extended temporary.
776 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
777
778 if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
779 Init = BTE->getSubExpr();
780
781 Init = Init->IgnoreParens();
782
783 // Step over value-preserving rvalue casts.
784 if (auto *CE = dyn_cast<CastExpr>(Init)) {
785 switch (CE->getCastKind()) {
786 case CK_LValueToRValue:
787 // If we can match the lvalue to a const object, we can look at its
788 // initializer.
789 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
791 Path, Init, RK_ReferenceBinding,
792 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
793 if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
794 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
795 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
796 !isVarOnPath(Path, VD)) {
797 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
798 visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit,
799 true);
800 }
801 } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
802 if (MTE->getType().isConstQualified())
803 visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),
804 Visit, true);
805 }
806 return false;
807 });
808
809 // We assume that objects can be retained by pointers cast to integers,
810 // but not if the integer is cast to floating-point type or to _Complex.
811 // We assume that casts to 'bool' do not preserve enough information to
812 // retain a local object.
813 case CK_NoOp:
814 case CK_BitCast:
815 case CK_BaseToDerived:
816 case CK_DerivedToBase:
817 case CK_UncheckedDerivedToBase:
818 case CK_Dynamic:
819 case CK_ToUnion:
820 case CK_UserDefinedConversion:
821 case CK_ConstructorConversion:
822 case CK_IntegralToPointer:
823 case CK_PointerToIntegral:
824 case CK_VectorSplat:
825 case CK_IntegralCast:
826 case CK_CPointerToObjCPointerCast:
827 case CK_BlockPointerToObjCPointerCast:
828 case CK_AnyPointerToBlockPointerCast:
829 case CK_AddressSpaceConversion:
830 break;
831
832 case CK_ArrayToPointerDecay:
833 // Model array-to-pointer decay as taking the address of the array
834 // lvalue.
835 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
837 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
838
839 default:
840 return;
841 }
842
843 Init = CE->getSubExpr();
844 }
845 } while (Old != Init);
846
847 // C++17 [dcl.init.list]p6:
848 // initializing an initializer_list object from the array extends the
849 // lifetime of the array exactly like binding a reference to a temporary.
850 if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
851 return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
852 RK_StdInitializerList, Visit);
853
854 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
855 // We already visited the elements of this initializer list while
856 // performing the initialization. Don't visit them again unless we've
857 // changed the lifetime of the initialized entity.
858 if (!RevisitSubinits)
859 return;
860
861 if (ILE->isTransparent())
862 return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
863 RevisitSubinits);
864
865 if (ILE->getType()->isArrayType()) {
866 for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
867 visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
868 RevisitSubinits);
869 return;
870 }
871
872 if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
873 assert(RD->isAggregate() && "aggregate init on non-aggregate");
874
875 // If we lifetime-extend a braced initializer which is initializing an
876 // aggregate, and that aggregate contains reference members which are
877 // bound to temporaries, those temporaries are also lifetime-extended.
878 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
879 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
880 visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
881 RK_ReferenceBinding, Visit);
882 else {
883 unsigned Index = 0;
884 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
885 visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
886 RevisitSubinits);
887 for (const auto *I : RD->fields()) {
888 if (Index >= ILE->getNumInits())
889 break;
890 if (I->isUnnamedBitField())
891 continue;
892 Expr *SubInit = ILE->getInit(Index);
893 if (I->getType()->isReferenceType())
895 RK_ReferenceBinding, Visit);
896 else
897 // This might be either aggregate-initialization of a member or
898 // initialization of a std::initializer_list object. Regardless,
899 // we should recursively lifetime-extend that initializer.
900 visitLocalsRetainedByInitializer(Path, SubInit, Visit,
901 RevisitSubinits);
902 ++Index;
903 }
904 }
905 }
906 return;
907 }
908
909 // The lifetime of an init-capture is that of the closure object constructed
910 // by a lambda-expression.
911 if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
912 LambdaExpr::capture_iterator CapI = LE->capture_begin();
913 for (Expr *E : LE->capture_inits()) {
914 assert(CapI != LE->capture_end());
915 const LambdaCapture &Cap = *CapI++;
916 if (!E)
917 continue;
918 if (Cap.capturesVariable())
919 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
920 if (E->isGLValue())
921 visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
922 Visit);
923 else
924 visitLocalsRetainedByInitializer(Path, E, Visit, true);
925 if (Cap.capturesVariable())
926 Path.pop_back();
927 }
928 }
929
930 // Assume that a copy or move from a temporary references the same objects
931 // that the temporary does.
932 if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {
933 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
934 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
935 Expr *Arg = MTE->getSubExpr();
936 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
937 CCE->getConstructor()});
938 visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
939 Path.pop_back();
940 }
941 }
942 }
943
945 return visitFunctionCallArguments(Path, Init, Visit);
946
947 if (auto *CPE = dyn_cast<CXXParenListInitExpr>(Init)) {
948 RevertToOldSizeRAII RAII(Path);
949 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
950 for (auto *I : CPE->getInitExprs()) {
951 if (I->isGLValue())
952 visitLocalsRetainedByReferenceBinding(Path, I, RK_ReferenceBinding,
953 Visit);
954 else
955 visitLocalsRetainedByInitializer(Path, I, Visit, true);
956 }
957 }
958 switch (Init->getStmtClass()) {
959 case Stmt::UnaryOperatorClass: {
960 auto *UO = cast<UnaryOperator>(Init);
961 // If the initializer is the address of a local, we could have a lifetime
962 // problem.
963 if (UO->getOpcode() == UO_AddrOf) {
964 // If this is &rvalue, then it's ill-formed and we have already diagnosed
965 // it. Don't produce a redundant warning about the lifetime of the
966 // temporary.
967 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
968 return;
969
970 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
971 visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
972 RK_ReferenceBinding, Visit);
973 }
974 break;
975 }
976
977 case Stmt::BinaryOperatorClass: {
978 // Handle pointer arithmetic.
979 auto *BO = cast<BinaryOperator>(Init);
980 BinaryOperatorKind BOK = BO->getOpcode();
981 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
982 break;
983
984 if (BO->getLHS()->getType()->isPointerType())
985 visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true);
986 else if (BO->getRHS()->getType()->isPointerType())
987 visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true);
988 break;
989 }
990
991 case Stmt::ConditionalOperatorClass:
992 case Stmt::BinaryConditionalOperatorClass: {
994 // In C++, we can have a throw-expression operand, which has 'void' type
995 // and isn't interesting from a lifetime perspective.
996 if (!C->getTrueExpr()->getType()->isVoidType())
997 visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true);
998 if (!C->getFalseExpr()->getType()->isVoidType())
999 visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true);
1000 break;
1001 }
1002
1003 case Stmt::BlockExprClass:
1004 if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
1005 // This is a local block, whose lifetime is that of the function.
1006 Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
1007 }
1008 break;
1009
1010 case Stmt::AddrLabelExprClass:
1011 // We want to warn if the address of a label would escape the function.
1012 Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
1013 break;
1014
1015 default:
1016 break;
1017 }
1018}
1019
1020/// Whether a path to an object supports lifetime extension.
1022 /// Lifetime-extend along this path.
1024 /// Do not lifetime extend along this path.
1026};
1027
1028/// Determine whether this is an indirect path to a temporary that we are
1029/// supposed to lifetime-extend along.
1030static PathLifetimeKind
1031shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
1032 for (auto Elem : Path) {
1033 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
1034 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
1035 continue;
1036 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
1039 }
1041}
1042
1043/// Find the range for the first interesting entry in the path at or after I.
1044static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
1045 Expr *E) {
1046 for (unsigned N = Path.size(); I != N; ++I) {
1047 switch (Path[I].Kind) {
1048 case IndirectLocalPathEntry::AddressOf:
1049 case IndirectLocalPathEntry::LValToRVal:
1050 case IndirectLocalPathEntry::LifetimeBoundCall:
1051 case IndirectLocalPathEntry::TemporaryCopy:
1052 case IndirectLocalPathEntry::GslReferenceInit:
1053 case IndirectLocalPathEntry::GslPointerInit:
1054 case IndirectLocalPathEntry::GslPointerAssignment:
1055 case IndirectLocalPathEntry::ParenAggInit:
1056 case IndirectLocalPathEntry::MemberExpr:
1057 // These exist primarily to mark the path as not permitting or
1058 // supporting lifetime extension.
1059 break;
1060
1061 case IndirectLocalPathEntry::VarInit:
1062 if (cast<VarDecl>(Path[I].D)->isImplicit())
1063 return SourceRange();
1064 [[fallthrough]];
1065 case IndirectLocalPathEntry::DefaultInit:
1066 return Path[I].E->getSourceRange();
1067
1068 case IndirectLocalPathEntry::LambdaCaptureInit:
1069 if (!Path[I].Capture->capturesVariable())
1070 continue;
1071 return Path[I].E->getSourceRange();
1072
1073 case IndirectLocalPathEntry::DefaultArg:
1074 return cast<CXXDefaultArgExpr>(Path[I].E)->getUsedLocation();
1075 }
1076 }
1077 return E->getSourceRange();
1078}
1079
1080static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) {
1081 for (const auto &It : llvm::reverse(Path)) {
1082 switch (It.Kind) {
1083 case IndirectLocalPathEntry::VarInit:
1084 case IndirectLocalPathEntry::AddressOf:
1085 case IndirectLocalPathEntry::LifetimeBoundCall:
1086 case IndirectLocalPathEntry::MemberExpr:
1087 continue;
1088 case IndirectLocalPathEntry::GslPointerInit:
1089 case IndirectLocalPathEntry::GslReferenceInit:
1090 case IndirectLocalPathEntry::GslPointerAssignment:
1091 return true;
1092 default:
1093 return false;
1094 }
1095 }
1096 return false;
1097}
1098// Result of analyzing the Path for GSLPointer.
1100 // Path does not correspond to a GSLPointer.
1102
1103 // A relevant case was identified.
1105 // Stop the entire traversal.
1107 // Skip this step and continue traversing inner AST nodes.
1109};
1110// Analyze cases where a GSLPointer is initialized or assigned from a
1111// temporary owner object.
1112static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path,
1113 Local L, LifetimeKind LK) {
1114 if (!pathOnlyHandlesGslPointer(Path))
1115 return NotGSLPointer;
1116
1117 // At this point, Path represents a series of operations involving a
1118 // GSLPointer, either in the process of initialization or assignment.
1119
1120 // Process temporary base objects for MemberExpr cases, e.g. Temp().field.
1121 for (const auto &E : Path) {
1122 if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
1123 // Avoid interfering with the local base object.
1124 if (pathContainsInit(Path))
1125 return Abandon;
1126
1127 // We are not interested in the temporary base objects of gsl Pointers:
1128 // auto p1 = Temp().ptr; // Here p1 might not dangle.
1129 // However, we want to diagnose for gsl owner fields:
1130 // auto p2 = Temp().owner; // Here p2 is dangling.
1131 if (const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(E.D);
1132 FD && !FD->getType()->isReferenceType() &&
1133 isGslOwnerType(FD->getType()) && LK != LK_MemInitializer) {
1134 return Report;
1135 }
1136 return Abandon;
1137 }
1138 }
1139
1140 // Note: A LifetimeBoundCall can appear interleaved in this sequence.
1141 // For example:
1142 // const std::string& Ref(const std::string& a [[clang::lifetimebound]]);
1143 // string_view abc = Ref(std::string());
1144 // The "Path" is [GSLPointerInit, LifetimeboundCall], where "L" is the
1145 // temporary "std::string()" object. We need to check the return type of the
1146 // function with the lifetimebound attribute.
1147 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1148 // The lifetimebound applies to the implicit object parameter of a method.
1149 const FunctionDecl *FD =
1150 llvm::dyn_cast_or_null<FunctionDecl>(Path.back().D);
1151 // The lifetimebound applies to a function parameter.
1152 if (const auto *PD = llvm::dyn_cast<ParmVarDecl>(Path.back().D))
1153 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1154
1155 if (isa_and_present<CXXConstructorDecl>(FD)) {
1156 // Constructor case: the parameter is annotated with lifetimebound
1157 // e.g., GSLPointer(const S& s [[clang::lifetimebound]])
1158 // We still respect this case even the type S is not an owner.
1159 return Report;
1160 }
1161 // Check the return type, e.g.
1162 // const GSLOwner& func(const Foo& foo [[clang::lifetimebound]])
1163 // GSLOwner* func(cosnt Foo& foo [[clang::lifetimebound]])
1164 // GSLPointer func(const Foo& foo [[clang::lifetimebound]])
1165 if (FD && ((FD->getReturnType()->isPointerOrReferenceType() &&
1168 return Report;
1169
1170 return Abandon;
1171 }
1172
1173 if (isa<DeclRefExpr>(L)) {
1174 // We do not want to follow the references when returning a pointer
1175 // originating from a local owner to avoid the following false positive:
1176 // int &p = *localUniquePtr;
1177 // someContainer.add(std::move(localUniquePtr));
1178 // return p;
1179 if (!pathContainsInit(Path) && isGslOwnerType(L->getType()))
1180 return Report;
1181 return Abandon;
1182 }
1183
1184 // The GSLPointer is from a temporary object.
1185 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1186
1187 bool IsGslPtrValueFromGslTempOwner =
1188 MTE && !MTE->getExtendingDecl() && isGslOwnerType(MTE->getType());
1189 // Skipping a chain of initializing gsl::Pointer annotated objects.
1190 // We are looking only for the final source to find out if it was
1191 // a local or temporary owner or the address of a local
1192 // variable/param.
1193 if (!IsGslPtrValueFromGslTempOwner)
1194 return Skip;
1195 return Report;
1196}
1197
1198static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef,
1199 const AssignedEntity &Entity) {
1200 bool EnableGSLAssignmentWarnings = !SemaRef.getDiagnostics().isIgnored(
1201 diag::warn_dangling_lifetime_pointer_assignment, SourceLocation());
1202 return (EnableGSLAssignmentWarnings &&
1203 (isGslPointerType(Entity.LHS->getType()) ||
1205 Entity.AssignmentOperator)));
1206}
1207
1208static void
1210 const InitializedEntity *ExtendingEntity, LifetimeKind LK,
1211 const AssignedEntity *AEntity,
1212 const CapturingEntity *CapEntity, Expr *Init) {
1213 assert(!AEntity || LK == LK_Assignment);
1214 assert(!CapEntity || LK == LK_LifetimeCapture);
1215 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1216 // If this entity doesn't have an interesting lifetime, don't bother looking
1217 // for temporaries within its initializer.
1218 if (LK == LK_FullExpression)
1219 return;
1220
1221 // FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
1222 // functions to a dedicated class.
1223 auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L,
1224 ReferenceKind RK) -> bool {
1225 SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
1226 SourceLocation DiagLoc = DiagRange.getBegin();
1227
1228 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1229
1230 bool IsGslPtrValueFromGslTempOwner = true;
1231 switch (analyzePathForGSLPointer(Path, L, LK)) {
1232 case Abandon:
1233 return false;
1234 case Skip:
1235 return true;
1236 case NotGSLPointer:
1237 IsGslPtrValueFromGslTempOwner = false;
1238 [[fallthrough]];
1239 case Report:
1240 break;
1241 }
1242
1243 switch (LK) {
1244 case LK_FullExpression:
1245 llvm_unreachable("already handled this");
1246
1247 case LK_Extended: {
1248 if (!MTE) {
1249 // The initialized entity has lifetime beyond the full-expression,
1250 // and the local entity does too, so don't warn.
1251 //
1252 // FIXME: We should consider warning if a static / thread storage
1253 // duration variable retains an automatic storage duration local.
1254 return false;
1255 }
1256
1257 switch (shouldLifetimeExtendThroughPath(Path)) {
1259 // Update the storage duration of the materialized temporary.
1260 // FIXME: Rebuild the expression instead of mutating it.
1261 MTE->setExtendingDecl(ExtendingEntity->getDecl(),
1262 ExtendingEntity->allocateManglingNumber());
1263 // Also visit the temporaries lifetime-extended by this initializer.
1264 return true;
1265
1267 if (SemaRef.getLangOpts().CPlusPlus23 && InitEntity) {
1268 if (const VarDecl *VD =
1269 dyn_cast_if_present<VarDecl>(InitEntity->getDecl());
1270 VD && VD->isCXXForRangeImplicitVar()) {
1271 return false;
1272 }
1273 }
1274
1275 if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
1276 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1277 << DiagRange;
1278 return false;
1279 }
1280
1281 // If the path goes through the initialization of a variable or field,
1282 // it can't possibly reach a temporary created in this full-expression.
1283 // We will have already diagnosed any problems with the initializer.
1284 if (pathContainsInit(Path))
1285 return false;
1286
1287 SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
1288 << RK << !InitEntity->getParent()
1289 << ExtendingEntity->getDecl()->isImplicit()
1290 << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
1291 break;
1292 }
1293 break;
1294 }
1295
1296 case LK_LifetimeCapture: {
1297 // The captured entity has lifetime beyond the full-expression,
1298 // and the capturing entity does too, so don't warn.
1299 if (!MTE)
1300 return false;
1301 if (CapEntity->Entity)
1302 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured)
1303 << CapEntity->Entity << DiagRange;
1304 else
1305 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1306 << DiagRange;
1307 return false;
1308 }
1309
1310 case LK_Assignment: {
1311 if (!MTE || pathContainsInit(Path))
1312 return false;
1313 if (IsGslPtrValueFromGslTempOwner)
1314 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1315 << AEntity->LHS << DiagRange;
1316 else
1317 SemaRef.Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1318 << AEntity->LHS->getType()->isPointerType() << AEntity->LHS
1319 << DiagRange;
1320 return false;
1321 }
1322 case LK_MemInitializer: {
1323 if (MTE) {
1324 // Under C++ DR1696, if a mem-initializer (or a default member
1325 // initializer used by the absence of one) would lifetime-extend a
1326 // temporary, the program is ill-formed.
1327 if (auto *ExtendingDecl =
1328 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1329 if (IsGslPtrValueFromGslTempOwner) {
1330 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1331 << ExtendingDecl << DiagRange;
1332 SemaRef.Diag(ExtendingDecl->getLocation(),
1333 diag::note_ref_or_ptr_member_declared_here)
1334 << true;
1335 return false;
1336 }
1337 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1338 SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
1340 ? diag::err_dangling_member
1341 : diag::warn_dangling_member)
1342 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1343 // Don't bother adding a note pointing to the field if we're inside
1344 // its default member initializer; our primary diagnostic points to
1345 // the same place in that case.
1346 if (Path.empty() ||
1347 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1348 SemaRef.Diag(ExtendingDecl->getLocation(),
1349 diag::note_lifetime_extending_member_declared_here)
1350 << RK << IsSubobjectMember;
1351 }
1352 } else {
1353 // We have a mem-initializer but no particular field within it; this
1354 // is either a base class or a delegating initializer directly
1355 // initializing the base-class from something that doesn't live long
1356 // enough.
1357 //
1358 // FIXME: Warn on this.
1359 return false;
1360 }
1361 } else {
1362 // Paths via a default initializer can only occur during error recovery
1363 // (there's no other way that a default initializer can refer to a
1364 // local). Don't produce a bogus warning on those cases.
1365 if (pathContainsInit(Path))
1366 return false;
1367
1368 auto *DRE = dyn_cast<DeclRefExpr>(L);
1369 // Suppress false positives for code like the one below:
1370 // Ctor(unique_ptr<T> up) : pointer(up.get()), owner(move(up)) {}
1371 // FIXME: move this logic to analyzePathForGSLPointer.
1372 if (DRE && isGslOwnerType(DRE->getType()))
1373 return false;
1374
1375 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
1376 if (!VD) {
1377 // A member was initialized to a local block.
1378 // FIXME: Warn on this.
1379 return false;
1380 }
1381
1382 if (auto *Member =
1383 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1384 bool IsPointer = !Member->getType()->isReferenceType();
1385 SemaRef.Diag(DiagLoc,
1386 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1387 : diag::warn_bind_ref_member_to_parameter)
1388 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1389 SemaRef.Diag(Member->getLocation(),
1390 diag::note_ref_or_ptr_member_declared_here)
1391 << (unsigned)IsPointer;
1392 }
1393 }
1394 break;
1395 }
1396
1397 case LK_New:
1399 if (IsGslPtrValueFromGslTempOwner)
1400 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1401 << DiagRange;
1402 else
1403 SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
1404 ? diag::warn_new_dangling_reference
1405 : diag::warn_new_dangling_initializer_list)
1406 << !InitEntity->getParent() << DiagRange;
1407 } else {
1408 // We can't determine if the allocation outlives the local declaration.
1409 return false;
1410 }
1411 break;
1412
1413 case LK_Return:
1414 case LK_MustTail:
1415 case LK_StmtExprResult:
1416 if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1417 // We can't determine if the local variable outlives the statement
1418 // expression.
1419 if (LK == LK_StmtExprResult)
1420 return false;
1421 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1422 << InitEntity->getType()->isReferenceType() << DRE->getDecl()
1423 << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail)
1424 << DiagRange;
1425 } else if (isa<BlockExpr>(L)) {
1426 SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1427 } else if (isa<AddrLabelExpr>(L)) {
1428 // Don't warn when returning a label from a statement expression.
1429 // Leaving the scope doesn't end its lifetime.
1430 if (LK == LK_StmtExprResult)
1431 return false;
1432 SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1433 } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1434 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1435 << InitEntity->getType()->isReferenceType() << CLE->getInitializer()
1436 << 2 << (LK == LK_MustTail) << DiagRange;
1437 } else {
1438 // P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
1439 // [stmt.return]/p6: In a function whose return type is a reference,
1440 // other than an invented function for std::is_convertible ([meta.rel]),
1441 // a return statement that binds the returned reference to a temporary
1442 // expression ([class.temporary]) is ill-formed.
1443 if (SemaRef.getLangOpts().CPlusPlus26 &&
1444 InitEntity->getType()->isReferenceType())
1445 SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
1446 << InitEntity->getType()->isReferenceType() << DiagRange;
1447 else if (LK == LK_MustTail)
1448 SemaRef.Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1449 << InitEntity->getType()->isReferenceType() << DiagRange;
1450 else
1451 SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1452 << InitEntity->getType()->isReferenceType() << DiagRange;
1453 }
1454 break;
1455 }
1456
1457 for (unsigned I = 0; I != Path.size(); ++I) {
1458 auto Elem = Path[I];
1459
1460 switch (Elem.Kind) {
1461 case IndirectLocalPathEntry::AddressOf:
1462 case IndirectLocalPathEntry::LValToRVal:
1463 case IndirectLocalPathEntry::ParenAggInit:
1464 // These exist primarily to mark the path as not permitting or
1465 // supporting lifetime extension.
1466 break;
1467
1468 case IndirectLocalPathEntry::LifetimeBoundCall:
1469 case IndirectLocalPathEntry::TemporaryCopy:
1470 case IndirectLocalPathEntry::MemberExpr:
1471 case IndirectLocalPathEntry::GslPointerInit:
1472 case IndirectLocalPathEntry::GslReferenceInit:
1473 case IndirectLocalPathEntry::GslPointerAssignment:
1474 // FIXME: Consider adding a note for these.
1475 break;
1476
1477 case IndirectLocalPathEntry::DefaultInit: {
1478 auto *FD = cast<FieldDecl>(Elem.D);
1479 SemaRef.Diag(FD->getLocation(),
1480 diag::note_init_with_default_member_initializer)
1481 << FD << nextPathEntryRange(Path, I + 1, L);
1482 break;
1483 }
1484
1485 case IndirectLocalPathEntry::VarInit: {
1486 const VarDecl *VD = cast<VarDecl>(Elem.D);
1487 SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
1488 << VD->getType()->isReferenceType() << VD->isImplicit()
1489 << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L);
1490 break;
1491 }
1492
1493 case IndirectLocalPathEntry::LambdaCaptureInit: {
1494 if (!Elem.Capture->capturesVariable())
1495 break;
1496 // FIXME: We can't easily tell apart an init-capture from a nested
1497 // capture of an init-capture.
1498 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1499 SemaRef.Diag(Elem.Capture->getLocation(),
1500 diag::note_lambda_capture_initializer)
1501 << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
1502 << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
1503 << nextPathEntryRange(Path, I + 1, L);
1504 break;
1505 }
1506
1507 case IndirectLocalPathEntry::DefaultArg: {
1508 const auto *DAE = cast<CXXDefaultArgExpr>(Elem.E);
1509 const ParmVarDecl *Param = DAE->getParam();
1510 SemaRef.Diag(Param->getDefaultArgRange().getBegin(),
1511 diag::note_init_with_default_argument)
1512 << Param << nextPathEntryRange(Path, I + 1, L);
1513 break;
1514 }
1515 }
1516 }
1517
1518 // We didn't lifetime-extend, so don't go any further; we don't need more
1519 // warnings or errors on inner temporaries within this one's initializer.
1520 return false;
1521 };
1522
1524 switch (LK) {
1525 case LK_Assignment: {
1526 if (shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity))
1528 AEntity->AssignmentOperator)
1529 ? IndirectLocalPathEntry::LifetimeBoundCall
1530 : IndirectLocalPathEntry::GslPointerAssignment,
1531 Init});
1532 break;
1533 }
1534 case LK_LifetimeCapture: {
1535 if (isPointerLikeType(Init->getType()))
1536 Path.push_back({IndirectLocalPathEntry::GslPointerInit, Init});
1537 break;
1538 }
1539 default:
1540 break;
1541 }
1542
1543 if (Init->isGLValue())
1544 visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
1545 TemporaryVisitor);
1546 else
1548 Path, Init, TemporaryVisitor,
1549 // Don't revisit the sub inits for the intialization case.
1550 /*RevisitSubinits=*/!InitEntity);
1551}
1552
1553void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity,
1554 Expr *Init) {
1555 auto LTResult = getEntityLifetime(&Entity);
1556 LifetimeKind LK = LTResult.getInt();
1557 const InitializedEntity *ExtendingEntity = LTResult.getPointer();
1558 checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK,
1559 /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init);
1560}
1561
1563 const InitializedEntity &Entity, Expr *Init) {
1564 checkExprLifetimeImpl(SemaRef, &Entity, nullptr, LK_MustTail,
1565 /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init);
1566}
1567
1568void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity,
1569 Expr *Init) {
1570 bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics().isIgnored(
1571 diag::warn_dangling_pointer_assignment, SourceLocation());
1572 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1573 Entity.LHS->getType()->isPointerType()) ||
1574 shouldRunGSLAssignmentAnalysis(SemaRef, Entity);
1575
1576 if (!RunAnalysis)
1577 return;
1578
1579 checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
1580 /*ExtendingEntity=*/nullptr, LK_Assignment, &Entity,
1581 /*CapEntity=*/nullptr, Init);
1582}
1583
1584void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity,
1585 Expr *Init) {
1586 if (SemaRef.getDiagnostics().isIgnored(diag::warn_dangling_reference_captured,
1587 SourceLocation()) &&
1588 SemaRef.getDiagnostics().isIgnored(
1589 diag::warn_dangling_reference_captured_by_unknown, SourceLocation()))
1590 return;
1591 return checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
1592 /*ExtendingEntity=*/nullptr, LK_LifetimeCapture,
1593 /*AEntity=*/nullptr,
1594 /*CapEntity=*/&Entity, Init);
1595}
1596
1597} // namespace clang::sema
C Language Family Type Representation.
Represents binding an expression to a temporary.
Definition ExprCXX.h:1493
Represents a call to a C++ constructor.
Definition ExprCXX.h:1548
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1691
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1611
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2255
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:3610
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
bool isStdNamespace() const
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isInStdNamespace() const
Definition DeclBase.cpp:449
T * getAttr() const
Definition DeclBase.h:573
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:593
SourceLocation getLocation() const
Definition DeclBase.h:439
DeclContext * getDeclContext()
Definition DeclBase.h:448
bool hasAttr() const
Definition DeclBase.h:577
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition Diagnostic.h:951
This represents one expression.
Definition Expr.h:112
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3077
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2000
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2797
QualType getReturnType() const
Definition Decl.h:2845
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition Decl.cpp:4309
bool param_empty() const
Definition Decl.h:2785
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3822
size_t param_size() const
Definition Decl.h:2790
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Definition Expr.h:5233
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.
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_MatrixElement
The entity being initialized is an element of a matrix.
@ 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.
bool capturesVariable() const
Determine whether this capture handles a variable.
const LambdaCapture * capture_iterator
An iterator that walks over the captures of the lambda, both implicit and explicit.
Definition ExprCXX.h:2033
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3298
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
Represents a parameter to a function.
Definition Decl.h:1790
A (possibly-)qualified type.
Definition TypeBase.h:937
Represents a struct/union/class.
Definition Decl.h:4321
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3573
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
DiagnosticsEngine & getDiagnostics() const
Definition Sema.h:922
const LangOptions & getLangOpts() const
Definition Sema.h:918
static bool CanBeGetReturnObject(const FunctionDecl *FD)
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
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
@ Type
The template argument is a type.
bool hasAttr(attr::Kind AK) const
Determine whether this type had the specified attribute applied to it (looking through top-level type...
Definition Type.cpp:1951
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isPointerType() const
Definition TypeBase.h:8515
bool isReferenceType() const
Definition TypeBase.h:8539
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:1909
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool isPointerOrReferenceType() const
Definition TypeBase.h:8519
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
bool isNullPtrType() const
Definition TypeBase.h:8908
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2244
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Definition Decl.cpp:5521
Represents a variable declaration or definition.
Definition Decl.h:926
bool isCXXForRangeImplicitVar() const
Whether this variable is the implicit '__range' variable in C++ range-based for loops.
Definition Decl.h:1622
#define bool
Definition gpuintrin.h:32
bool isGslPointerType(QualType QT)
bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
bool isGslOwnerType(QualType QT)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
static bool isStdInitializerListOfPointer(const RecordDecl *RD)
bool isGslPointerType(QualType QT)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, const CapturingEntity *CapEntity, Expr *Init)
static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, const AssignedEntity &Entity)
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit)
Visit the locals that would be reachable through a reference bound to the glvalue expression Init.
void checkExprLifetimeMustTailArg(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient, assuming that it is pas...
static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path)
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits)
Visit the locals that would be reachable through an object initialized by the prvalue expression Init...
static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path, Local L, LifetimeKind LK)
static bool isInStlNamespace(const Decl *D)
static bool shouldTrackFirstArgument(const FunctionDecl *FD)
static bool isContainerOfOwner(const RecordDecl *Container)
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...
static bool isContainerOfPointer(const RecordDecl *Container)
void checkInitLifetime(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 isCopyLikeConstructor(const CXXConstructorDecl *Ctor)
void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for assigning to the ent...
static bool shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor)
bool isGslOwnerType(QualType QT)
PathLifetimeKind
Whether a path to an object supports lifetime extension.
@ NoExtend
Do not lifetime extend along this path.
@ Extend
Lifetime-extend along this path.
static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD)
static bool pathContainsInit(const IndirectLocalPath &Path)
static bool isPointerLikeType(QualType QT)
static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, Expr *Init)
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee)
static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path)
Determine whether this is an indirect path to a temporary that we are supposed to lifetime-extend alo...
bool isa(CodeGen::Address addr)
Definition Address.h:330
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
U cast(CodeGen::Address addr)
Definition Address.h:327
Describes an entity that is being assigned.