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