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