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