Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Sema/CheckExprLifetime.cpp
35234 views
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/Basic/DiagnosticSema.h"
13
#include "clang/Sema/Initialization.h"
14
#include "clang/Sema/Sema.h"
15
#include "llvm/ADT/PointerIntPair.h"
16
17
namespace clang::sema {
18
namespace {
19
enum LifetimeKind {
20
/// The lifetime of a temporary bound to this entity ends at the end of the
21
/// full-expression, and that's (probably) fine.
22
LK_FullExpression,
23
24
/// The lifetime of a temporary bound to this entity is extended to the
25
/// lifeitme of the entity itself.
26
LK_Extended,
27
28
/// The lifetime of a temporary bound to this entity probably ends too soon,
29
/// because the entity is allocated in a new-expression.
30
LK_New,
31
32
/// The lifetime of a temporary bound to this entity ends too soon, because
33
/// the entity is a return object.
34
LK_Return,
35
36
/// The lifetime of a temporary bound to this entity ends too soon, because
37
/// the entity is the result of a statement expression.
38
LK_StmtExprResult,
39
40
/// This is a mem-initializer: if it would extend a temporary (other than via
41
/// a default member initializer), the program is ill-formed.
42
LK_MemInitializer,
43
44
/// The lifetime of a temporary bound to this entity probably ends too soon,
45
/// because the entity is a pointer and we assign the address of a temporary
46
/// object to it.
47
LK_Assignment,
48
};
49
using LifetimeResult =
50
llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
51
} // namespace
52
53
/// Determine the declaration which an initialized entity ultimately refers to,
54
/// for the purpose of lifetime-extending a temporary bound to a reference in
55
/// the initialization of \p Entity.
56
static LifetimeResult
57
getEntityLifetime(const InitializedEntity *Entity,
58
const InitializedEntity *InitField = nullptr) {
59
// C++11 [class.temporary]p5:
60
switch (Entity->getKind()) {
61
case InitializedEntity::EK_Variable:
62
// The temporary [...] persists for the lifetime of the reference
63
return {Entity, LK_Extended};
64
65
case InitializedEntity::EK_Member:
66
// For subobjects, we look at the complete object.
67
if (Entity->getParent())
68
return getEntityLifetime(Entity->getParent(), Entity);
69
70
// except:
71
// C++17 [class.base.init]p8:
72
// A temporary expression bound to a reference member in a
73
// mem-initializer is ill-formed.
74
// C++17 [class.base.init]p11:
75
// A temporary expression bound to a reference member from a
76
// default member initializer is ill-formed.
77
//
78
// The context of p11 and its example suggest that it's only the use of a
79
// default member initializer from a constructor that makes the program
80
// ill-formed, not its mere existence, and that it can even be used by
81
// aggregate initialization.
82
return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
83
: LK_MemInitializer};
84
85
case InitializedEntity::EK_Binding:
86
// Per [dcl.decomp]p3, the binding is treated as a variable of reference
87
// type.
88
return {Entity, LK_Extended};
89
90
case InitializedEntity::EK_Parameter:
91
case InitializedEntity::EK_Parameter_CF_Audited:
92
// -- A temporary bound to a reference parameter in a function call
93
// persists until the completion of the full-expression containing
94
// the call.
95
return {nullptr, LK_FullExpression};
96
97
case InitializedEntity::EK_TemplateParameter:
98
// FIXME: This will always be ill-formed; should we eagerly diagnose it
99
// here?
100
return {nullptr, LK_FullExpression};
101
102
case InitializedEntity::EK_Result:
103
// -- The lifetime of a temporary bound to the returned value in a
104
// function return statement is not extended; the temporary is
105
// destroyed at the end of the full-expression in the return statement.
106
return {nullptr, LK_Return};
107
108
case InitializedEntity::EK_StmtExprResult:
109
// FIXME: Should we lifetime-extend through the result of a statement
110
// expression?
111
return {nullptr, LK_StmtExprResult};
112
113
case InitializedEntity::EK_New:
114
// -- A temporary bound to a reference in a new-initializer persists
115
// until the completion of the full-expression containing the
116
// new-initializer.
117
return {nullptr, LK_New};
118
119
case InitializedEntity::EK_Temporary:
120
case InitializedEntity::EK_CompoundLiteralInit:
121
case InitializedEntity::EK_RelatedResult:
122
// We don't yet know the storage duration of the surrounding temporary.
123
// Assume it's got full-expression duration for now, it will patch up our
124
// storage duration if that's not correct.
125
return {nullptr, LK_FullExpression};
126
127
case InitializedEntity::EK_ArrayElement:
128
// For subobjects, we look at the complete object.
129
return getEntityLifetime(Entity->getParent(), InitField);
130
131
case InitializedEntity::EK_Base:
132
// For subobjects, we look at the complete object.
133
if (Entity->getParent())
134
return getEntityLifetime(Entity->getParent(), InitField);
135
return {InitField, LK_MemInitializer};
136
137
case InitializedEntity::EK_Delegating:
138
// We can reach this case for aggregate initialization in a constructor:
139
// struct A { int &&r; };
140
// struct B : A { B() : A{0} {} };
141
// In this case, use the outermost field decl as the context.
142
return {InitField, LK_MemInitializer};
143
144
case InitializedEntity::EK_BlockElement:
145
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
146
case InitializedEntity::EK_LambdaCapture:
147
case InitializedEntity::EK_VectorElement:
148
case InitializedEntity::EK_ComplexElement:
149
return {nullptr, LK_FullExpression};
150
151
case InitializedEntity::EK_Exception:
152
// FIXME: Can we diagnose lifetime problems with exceptions?
153
return {nullptr, LK_FullExpression};
154
155
case InitializedEntity::EK_ParenAggInitMember:
156
// -- A temporary object bound to a reference element of an aggregate of
157
// class type initialized from a parenthesized expression-list
158
// [dcl.init, 9.3] persists until the completion of the full-expression
159
// containing the expression-list.
160
return {nullptr, LK_FullExpression};
161
}
162
163
llvm_unreachable("unknown entity kind");
164
}
165
166
namespace {
167
enum ReferenceKind {
168
/// Lifetime would be extended by a reference binding to a temporary.
169
RK_ReferenceBinding,
170
/// Lifetime would be extended by a std::initializer_list object binding to
171
/// its backing array.
172
RK_StdInitializerList,
173
};
174
175
/// A temporary or local variable. This will be one of:
176
/// * A MaterializeTemporaryExpr.
177
/// * A DeclRefExpr whose declaration is a local.
178
/// * An AddrLabelExpr.
179
/// * A BlockExpr for a block with captures.
180
using Local = Expr *;
181
182
/// Expressions we stepped over when looking for the local state. Any steps
183
/// that would inhibit lifetime extension or take us out of subexpressions of
184
/// the initializer are included.
185
struct IndirectLocalPathEntry {
186
enum EntryKind {
187
DefaultInit,
188
AddressOf,
189
VarInit,
190
LValToRVal,
191
LifetimeBoundCall,
192
TemporaryCopy,
193
LambdaCaptureInit,
194
GslReferenceInit,
195
GslPointerInit,
196
GslPointerAssignment,
197
} Kind;
198
Expr *E;
199
union {
200
const Decl *D = nullptr;
201
const LambdaCapture *Capture;
202
};
203
IndirectLocalPathEntry() {}
204
IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
205
IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
206
: Kind(K), E(E), D(D) {}
207
IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
208
: Kind(K), E(E), Capture(Capture) {}
209
};
210
211
using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
212
213
struct RevertToOldSizeRAII {
214
IndirectLocalPath &Path;
215
unsigned OldSize = Path.size();
216
RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
217
~RevertToOldSizeRAII() { Path.resize(OldSize); }
218
};
219
220
using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
221
ReferenceKind RK)>;
222
} // namespace
223
224
static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
225
for (auto E : Path)
226
if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
227
return true;
228
return false;
229
}
230
231
static bool pathContainsInit(IndirectLocalPath &Path) {
232
return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
233
return E.Kind == IndirectLocalPathEntry::DefaultInit ||
234
E.Kind == IndirectLocalPathEntry::VarInit;
235
});
236
}
237
238
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
239
Expr *Init, LocalVisitor Visit,
240
bool RevisitSubinits,
241
bool EnableLifetimeWarnings);
242
243
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
244
Expr *Init, ReferenceKind RK,
245
LocalVisitor Visit,
246
bool EnableLifetimeWarnings);
247
248
template <typename T> static bool isRecordWithAttr(QualType Type) {
249
if (auto *RD = Type->getAsCXXRecordDecl())
250
return RD->hasAttr<T>();
251
return false;
252
}
253
254
// Decl::isInStdNamespace will return false for iterators in some STL
255
// implementations due to them being defined in a namespace outside of the std
256
// namespace.
257
static bool isInStlNamespace(const Decl *D) {
258
const DeclContext *DC = D->getDeclContext();
259
if (!DC)
260
return false;
261
if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
262
if (const IdentifierInfo *II = ND->getIdentifier()) {
263
StringRef Name = II->getName();
264
if (Name.size() >= 2 && Name.front() == '_' &&
265
(Name[1] == '_' || isUppercase(Name[1])))
266
return true;
267
}
268
269
return DC->isStdNamespace();
270
}
271
272
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
273
if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
274
if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
275
return true;
276
if (!isInStlNamespace(Callee->getParent()))
277
return false;
278
if (!isRecordWithAttr<PointerAttr>(
279
Callee->getFunctionObjectParameterType()) &&
280
!isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
281
return false;
282
if (Callee->getReturnType()->isPointerType() ||
283
isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
284
if (!Callee->getIdentifier())
285
return false;
286
return llvm::StringSwitch<bool>(Callee->getName())
287
.Cases("begin", "rbegin", "cbegin", "crbegin", true)
288
.Cases("end", "rend", "cend", "crend", true)
289
.Cases("c_str", "data", "get", true)
290
// Map and set types.
291
.Cases("find", "equal_range", "lower_bound", "upper_bound", true)
292
.Default(false);
293
} else if (Callee->getReturnType()->isReferenceType()) {
294
if (!Callee->getIdentifier()) {
295
auto OO = Callee->getOverloadedOperator();
296
return OO == OverloadedOperatorKind::OO_Subscript ||
297
OO == OverloadedOperatorKind::OO_Star;
298
}
299
return llvm::StringSwitch<bool>(Callee->getName())
300
.Cases("front", "back", "at", "top", "value", true)
301
.Default(false);
302
}
303
return false;
304
}
305
306
static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
307
if (!FD->getIdentifier() || FD->getNumParams() != 1)
308
return false;
309
const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
310
if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
311
return false;
312
if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
313
return false;
314
if (FD->getReturnType()->isPointerType() ||
315
isRecordWithAttr<PointerAttr>(FD->getReturnType())) {
316
return llvm::StringSwitch<bool>(FD->getName())
317
.Cases("begin", "rbegin", "cbegin", "crbegin", true)
318
.Cases("end", "rend", "cend", "crend", true)
319
.Case("data", true)
320
.Default(false);
321
} else if (FD->getReturnType()->isReferenceType()) {
322
return llvm::StringSwitch<bool>(FD->getName())
323
.Cases("get", "any_cast", true)
324
.Default(false);
325
}
326
return false;
327
}
328
329
static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
330
LocalVisitor Visit) {
331
auto VisitPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {
332
// We are not interested in the temporary base objects of gsl Pointers:
333
// Temp().ptr; // Here ptr might not dangle.
334
if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
335
return;
336
// Once we initialized a value with a reference, it can no longer dangle.
337
if (!Value) {
338
for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
339
if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)
340
continue;
341
if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
342
PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
343
return;
344
break;
345
}
346
}
347
Path.push_back({Value ? IndirectLocalPathEntry::GslPointerInit
348
: IndirectLocalPathEntry::GslReferenceInit,
349
Arg, D});
350
if (Arg->isGLValue())
351
visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
352
Visit,
353
/*EnableLifetimeWarnings=*/true);
354
else
355
visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
356
/*EnableLifetimeWarnings=*/true);
357
Path.pop_back();
358
};
359
360
if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
361
const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
362
if (MD && shouldTrackImplicitObjectArg(MD))
363
VisitPointerArg(MD, MCE->getImplicitObjectArgument(),
364
!MD->getReturnType()->isReferenceType());
365
return;
366
} else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
367
FunctionDecl *Callee = OCE->getDirectCallee();
368
if (Callee && Callee->isCXXInstanceMember() &&
369
shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
370
VisitPointerArg(Callee, OCE->getArg(0),
371
!Callee->getReturnType()->isReferenceType());
372
return;
373
} else if (auto *CE = dyn_cast<CallExpr>(Call)) {
374
FunctionDecl *Callee = CE->getDirectCallee();
375
if (Callee && shouldTrackFirstArgument(Callee))
376
VisitPointerArg(Callee, CE->getArg(0),
377
!Callee->getReturnType()->isReferenceType());
378
return;
379
}
380
381
if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
382
const auto *Ctor = CCE->getConstructor();
383
const CXXRecordDecl *RD = Ctor->getParent();
384
if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())
385
VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0], true);
386
}
387
}
388
389
static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
390
const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
391
if (!TSI)
392
return false;
393
// Don't declare this variable in the second operand of the for-statement;
394
// GCC miscompiles that by ending its lifetime before evaluating the
395
// third operand. See gcc.gnu.org/PR86769.
396
AttributedTypeLoc ATL;
397
for (TypeLoc TL = TSI->getTypeLoc();
398
(ATL = TL.getAsAdjusted<AttributedTypeLoc>());
399
TL = ATL.getModifiedLoc()) {
400
if (ATL.getAttrAs<LifetimeBoundAttr>())
401
return true;
402
}
403
404
// Assume that all assignment operators with a "normal" return type return
405
// *this, that is, an lvalue reference that is the same type as the implicit
406
// object parameter (or the LHS for a non-member operator$=).
407
OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator();
408
if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) {
409
QualType RetT = FD->getReturnType();
410
if (RetT->isLValueReferenceType()) {
411
ASTContext &Ctx = FD->getASTContext();
412
QualType LHST;
413
auto *MD = dyn_cast<CXXMethodDecl>(FD);
414
if (MD && MD->isCXXInstanceMember())
415
LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
416
else
417
LHST = MD->getParamDecl(0)->getType();
418
if (Ctx.hasSameType(RetT, LHST))
419
return true;
420
}
421
}
422
423
return false;
424
}
425
426
static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
427
LocalVisitor Visit) {
428
const FunctionDecl *Callee;
429
ArrayRef<Expr *> Args;
430
431
if (auto *CE = dyn_cast<CallExpr>(Call)) {
432
Callee = CE->getDirectCallee();
433
Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
434
} else {
435
auto *CCE = cast<CXXConstructExpr>(Call);
436
Callee = CCE->getConstructor();
437
Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
438
}
439
if (!Callee)
440
return;
441
442
Expr *ObjectArg = nullptr;
443
if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
444
ObjectArg = Args[0];
445
Args = Args.slice(1);
446
} else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
447
ObjectArg = MCE->getImplicitObjectArgument();
448
}
449
450
auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
451
Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
452
if (Arg->isGLValue())
453
visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
454
Visit,
455
/*EnableLifetimeWarnings=*/false);
456
else
457
visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
458
/*EnableLifetimeWarnings=*/false);
459
Path.pop_back();
460
};
461
462
bool CheckCoroCall = false;
463
if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
464
CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
465
RD->hasAttr<CoroReturnTypeAttr>() &&
466
!Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
467
}
468
469
if (ObjectArg) {
470
bool CheckCoroObjArg = CheckCoroCall;
471
// Coroutine lambda objects with empty capture list are not lifetimebound.
472
if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit());
473
LE && LE->captures().empty())
474
CheckCoroObjArg = false;
475
// Allow `get_return_object()` as the object param (__promise) is not
476
// lifetimebound.
477
if (Sema::CanBeGetReturnObject(Callee))
478
CheckCoroObjArg = false;
479
if (implicitObjectParamIsLifetimeBound(Callee) || CheckCoroObjArg)
480
VisitLifetimeBoundArg(Callee, ObjectArg);
481
}
482
483
for (unsigned I = 0,
484
N = std::min<unsigned>(Callee->getNumParams(), Args.size());
485
I != N; ++I) {
486
if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
487
VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
488
}
489
}
490
491
/// Visit the locals that would be reachable through a reference bound to the
492
/// glvalue expression \c Init.
493
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
494
Expr *Init, ReferenceKind RK,
495
LocalVisitor Visit,
496
bool EnableLifetimeWarnings) {
497
RevertToOldSizeRAII RAII(Path);
498
499
// Walk past any constructs which we can lifetime-extend across.
500
Expr *Old;
501
do {
502
Old = Init;
503
504
if (auto *FE = dyn_cast<FullExpr>(Init))
505
Init = FE->getSubExpr();
506
507
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
508
// If this is just redundant braces around an initializer, step over it.
509
if (ILE->isTransparent())
510
Init = ILE->getInit(0);
511
}
512
513
// Step over any subobject adjustments; we may have a materialized
514
// temporary inside them.
515
Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
516
517
// Per current approach for DR1376, look through casts to reference type
518
// when performing lifetime extension.
519
if (CastExpr *CE = dyn_cast<CastExpr>(Init))
520
if (CE->getSubExpr()->isGLValue())
521
Init = CE->getSubExpr();
522
523
// Per the current approach for DR1299, look through array element access
524
// on array glvalues when performing lifetime extension.
525
if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
526
Init = ASE->getBase();
527
auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
528
if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
529
Init = ICE->getSubExpr();
530
else
531
// We can't lifetime extend through this but we might still find some
532
// retained temporaries.
533
return visitLocalsRetainedByInitializer(Path, Init, Visit, true,
534
EnableLifetimeWarnings);
535
}
536
537
// Step into CXXDefaultInitExprs so we can diagnose cases where a
538
// constructor inherits one as an implicit mem-initializer.
539
if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
540
Path.push_back(
541
{IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
542
Init = DIE->getExpr();
543
}
544
} while (Init != Old);
545
546
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
547
if (Visit(Path, Local(MTE), RK))
548
visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true,
549
EnableLifetimeWarnings);
550
}
551
552
if (auto *M = dyn_cast<MemberExpr>(Init)) {
553
// Lifetime of a non-reference type field is same as base object.
554
if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
555
F && !F->getType()->isReferenceType())
556
visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true,
557
EnableLifetimeWarnings);
558
}
559
560
if (isa<CallExpr>(Init)) {
561
if (EnableLifetimeWarnings)
562
handleGslAnnotatedTypes(Path, Init, Visit);
563
return visitLifetimeBoundArguments(Path, Init, Visit);
564
}
565
566
switch (Init->getStmtClass()) {
567
case Stmt::DeclRefExprClass: {
568
// If we find the name of a local non-reference parameter, we could have a
569
// lifetime problem.
570
auto *DRE = cast<DeclRefExpr>(Init);
571
auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
572
if (VD && VD->hasLocalStorage() &&
573
!DRE->refersToEnclosingVariableOrCapture()) {
574
if (!VD->getType()->isReferenceType()) {
575
Visit(Path, Local(DRE), RK);
576
} else if (isa<ParmVarDecl>(DRE->getDecl())) {
577
// The lifetime of a reference parameter is unknown; assume it's OK
578
// for now.
579
break;
580
} else if (VD->getInit() && !isVarOnPath(Path, VD)) {
581
Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
582
visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
583
RK_ReferenceBinding, Visit,
584
EnableLifetimeWarnings);
585
}
586
}
587
break;
588
}
589
590
case Stmt::UnaryOperatorClass: {
591
// The only unary operator that make sense to handle here
592
// is Deref. All others don't resolve to a "name." This includes
593
// handling all sorts of rvalues passed to a unary operator.
594
const UnaryOperator *U = cast<UnaryOperator>(Init);
595
if (U->getOpcode() == UO_Deref)
596
visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true,
597
EnableLifetimeWarnings);
598
break;
599
}
600
601
case Stmt::ArraySectionExprClass: {
602
visitLocalsRetainedByInitializer(Path,
603
cast<ArraySectionExpr>(Init)->getBase(),
604
Visit, true, EnableLifetimeWarnings);
605
break;
606
}
607
608
case Stmt::ConditionalOperatorClass:
609
case Stmt::BinaryConditionalOperatorClass: {
610
auto *C = cast<AbstractConditionalOperator>(Init);
611
if (!C->getTrueExpr()->getType()->isVoidType())
612
visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit,
613
EnableLifetimeWarnings);
614
if (!C->getFalseExpr()->getType()->isVoidType())
615
visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit,
616
EnableLifetimeWarnings);
617
break;
618
}
619
620
case Stmt::CompoundLiteralExprClass: {
621
if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
622
if (!CLE->isFileScope())
623
Visit(Path, Local(CLE), RK);
624
}
625
break;
626
}
627
628
// FIXME: Visit the left-hand side of an -> or ->*.
629
630
default:
631
break;
632
}
633
}
634
635
/// Visit the locals that would be reachable through an object initialized by
636
/// the prvalue expression \c Init.
637
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
638
Expr *Init, LocalVisitor Visit,
639
bool RevisitSubinits,
640
bool EnableLifetimeWarnings) {
641
RevertToOldSizeRAII RAII(Path);
642
643
Expr *Old;
644
do {
645
Old = Init;
646
647
// Step into CXXDefaultInitExprs so we can diagnose cases where a
648
// constructor inherits one as an implicit mem-initializer.
649
if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
650
Path.push_back(
651
{IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
652
Init = DIE->getExpr();
653
}
654
655
if (auto *FE = dyn_cast<FullExpr>(Init))
656
Init = FE->getSubExpr();
657
658
// Dig out the expression which constructs the extended temporary.
659
Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
660
661
if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
662
Init = BTE->getSubExpr();
663
664
Init = Init->IgnoreParens();
665
666
// Step over value-preserving rvalue casts.
667
if (auto *CE = dyn_cast<CastExpr>(Init)) {
668
switch (CE->getCastKind()) {
669
case CK_LValueToRValue:
670
// If we can match the lvalue to a const object, we can look at its
671
// initializer.
672
Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
673
return visitLocalsRetainedByReferenceBinding(
674
Path, Init, RK_ReferenceBinding,
675
[&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
676
if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
677
auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
678
if (VD && VD->getType().isConstQualified() && VD->getInit() &&
679
!isVarOnPath(Path, VD)) {
680
Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
681
visitLocalsRetainedByInitializer(
682
Path, VD->getInit(), Visit, true, EnableLifetimeWarnings);
683
}
684
} else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
685
if (MTE->getType().isConstQualified())
686
visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),
687
Visit, true,
688
EnableLifetimeWarnings);
689
}
690
return false;
691
},
692
EnableLifetimeWarnings);
693
694
// We assume that objects can be retained by pointers cast to integers,
695
// but not if the integer is cast to floating-point type or to _Complex.
696
// We assume that casts to 'bool' do not preserve enough information to
697
// retain a local object.
698
case CK_NoOp:
699
case CK_BitCast:
700
case CK_BaseToDerived:
701
case CK_DerivedToBase:
702
case CK_UncheckedDerivedToBase:
703
case CK_Dynamic:
704
case CK_ToUnion:
705
case CK_UserDefinedConversion:
706
case CK_ConstructorConversion:
707
case CK_IntegralToPointer:
708
case CK_PointerToIntegral:
709
case CK_VectorSplat:
710
case CK_IntegralCast:
711
case CK_CPointerToObjCPointerCast:
712
case CK_BlockPointerToObjCPointerCast:
713
case CK_AnyPointerToBlockPointerCast:
714
case CK_AddressSpaceConversion:
715
break;
716
717
case CK_ArrayToPointerDecay:
718
// Model array-to-pointer decay as taking the address of the array
719
// lvalue.
720
Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
721
return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),
722
RK_ReferenceBinding, Visit,
723
EnableLifetimeWarnings);
724
725
default:
726
return;
727
}
728
729
Init = CE->getSubExpr();
730
}
731
} while (Old != Init);
732
733
// C++17 [dcl.init.list]p6:
734
// initializing an initializer_list object from the array extends the
735
// lifetime of the array exactly like binding a reference to a temporary.
736
if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
737
return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
738
RK_StdInitializerList, Visit,
739
EnableLifetimeWarnings);
740
741
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
742
// We already visited the elements of this initializer list while
743
// performing the initialization. Don't visit them again unless we've
744
// changed the lifetime of the initialized entity.
745
if (!RevisitSubinits)
746
return;
747
748
if (ILE->isTransparent())
749
return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
750
RevisitSubinits,
751
EnableLifetimeWarnings);
752
753
if (ILE->getType()->isArrayType()) {
754
for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
755
visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
756
RevisitSubinits,
757
EnableLifetimeWarnings);
758
return;
759
}
760
761
if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
762
assert(RD->isAggregate() && "aggregate init on non-aggregate");
763
764
// If we lifetime-extend a braced initializer which is initializing an
765
// aggregate, and that aggregate contains reference members which are
766
// bound to temporaries, those temporaries are also lifetime-extended.
767
if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
768
ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
769
visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
770
RK_ReferenceBinding, Visit,
771
EnableLifetimeWarnings);
772
else {
773
unsigned Index = 0;
774
for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
775
visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
776
RevisitSubinits,
777
EnableLifetimeWarnings);
778
for (const auto *I : RD->fields()) {
779
if (Index >= ILE->getNumInits())
780
break;
781
if (I->isUnnamedBitField())
782
continue;
783
Expr *SubInit = ILE->getInit(Index);
784
if (I->getType()->isReferenceType())
785
visitLocalsRetainedByReferenceBinding(Path, SubInit,
786
RK_ReferenceBinding, Visit,
787
EnableLifetimeWarnings);
788
else
789
// This might be either aggregate-initialization of a member or
790
// initialization of a std::initializer_list object. Regardless,
791
// we should recursively lifetime-extend that initializer.
792
visitLocalsRetainedByInitializer(
793
Path, SubInit, Visit, RevisitSubinits, EnableLifetimeWarnings);
794
++Index;
795
}
796
}
797
}
798
return;
799
}
800
801
// The lifetime of an init-capture is that of the closure object constructed
802
// by a lambda-expression.
803
if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
804
LambdaExpr::capture_iterator CapI = LE->capture_begin();
805
for (Expr *E : LE->capture_inits()) {
806
assert(CapI != LE->capture_end());
807
const LambdaCapture &Cap = *CapI++;
808
if (!E)
809
continue;
810
if (Cap.capturesVariable())
811
Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
812
if (E->isGLValue())
813
visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
814
Visit, EnableLifetimeWarnings);
815
else
816
visitLocalsRetainedByInitializer(Path, E, Visit, true,
817
EnableLifetimeWarnings);
818
if (Cap.capturesVariable())
819
Path.pop_back();
820
}
821
}
822
823
// Assume that a copy or move from a temporary references the same objects
824
// that the temporary does.
825
if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {
826
if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
827
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
828
// assert(false && "hit temporary copy path");
829
Expr *Arg = MTE->getSubExpr();
830
Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
831
CCE->getConstructor()});
832
visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
833
/*EnableLifetimeWarnings*/ false);
834
Path.pop_back();
835
}
836
}
837
}
838
839
if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {
840
if (EnableLifetimeWarnings)
841
handleGslAnnotatedTypes(Path, Init, Visit);
842
return visitLifetimeBoundArguments(Path, Init, Visit);
843
}
844
845
switch (Init->getStmtClass()) {
846
case Stmt::UnaryOperatorClass: {
847
auto *UO = cast<UnaryOperator>(Init);
848
// If the initializer is the address of a local, we could have a lifetime
849
// problem.
850
if (UO->getOpcode() == UO_AddrOf) {
851
// If this is &rvalue, then it's ill-formed and we have already diagnosed
852
// it. Don't produce a redundant warning about the lifetime of the
853
// temporary.
854
if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
855
return;
856
857
Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
858
visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
859
RK_ReferenceBinding, Visit,
860
EnableLifetimeWarnings);
861
}
862
break;
863
}
864
865
case Stmt::BinaryOperatorClass: {
866
// Handle pointer arithmetic.
867
auto *BO = cast<BinaryOperator>(Init);
868
BinaryOperatorKind BOK = BO->getOpcode();
869
if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
870
break;
871
872
if (BO->getLHS()->getType()->isPointerType())
873
visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true,
874
EnableLifetimeWarnings);
875
else if (BO->getRHS()->getType()->isPointerType())
876
visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true,
877
EnableLifetimeWarnings);
878
break;
879
}
880
881
case Stmt::ConditionalOperatorClass:
882
case Stmt::BinaryConditionalOperatorClass: {
883
auto *C = cast<AbstractConditionalOperator>(Init);
884
// In C++, we can have a throw-expression operand, which has 'void' type
885
// and isn't interesting from a lifetime perspective.
886
if (!C->getTrueExpr()->getType()->isVoidType())
887
visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true,
888
EnableLifetimeWarnings);
889
if (!C->getFalseExpr()->getType()->isVoidType())
890
visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true,
891
EnableLifetimeWarnings);
892
break;
893
}
894
895
case Stmt::BlockExprClass:
896
if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
897
// This is a local block, whose lifetime is that of the function.
898
Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
899
}
900
break;
901
902
case Stmt::AddrLabelExprClass:
903
// We want to warn if the address of a label would escape the function.
904
Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
905
break;
906
907
default:
908
break;
909
}
910
}
911
912
/// Whether a path to an object supports lifetime extension.
913
enum PathLifetimeKind {
914
/// Lifetime-extend along this path.
915
Extend,
916
/// We should lifetime-extend, but we don't because (due to technical
917
/// limitations) we can't. This happens for default member initializers,
918
/// which we don't clone for every use, so we don't have a unique
919
/// MaterializeTemporaryExpr to update.
920
ShouldExtend,
921
/// Do not lifetime extend along this path.
922
NoExtend
923
};
924
925
/// Determine whether this is an indirect path to a temporary that we are
926
/// supposed to lifetime-extend along.
927
static PathLifetimeKind
928
shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
929
PathLifetimeKind Kind = PathLifetimeKind::Extend;
930
for (auto Elem : Path) {
931
if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
932
Kind = PathLifetimeKind::ShouldExtend;
933
else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
934
return PathLifetimeKind::NoExtend;
935
}
936
return Kind;
937
}
938
939
/// Find the range for the first interesting entry in the path at or after I.
940
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
941
Expr *E) {
942
for (unsigned N = Path.size(); I != N; ++I) {
943
switch (Path[I].Kind) {
944
case IndirectLocalPathEntry::AddressOf:
945
case IndirectLocalPathEntry::LValToRVal:
946
case IndirectLocalPathEntry::LifetimeBoundCall:
947
case IndirectLocalPathEntry::TemporaryCopy:
948
case IndirectLocalPathEntry::GslReferenceInit:
949
case IndirectLocalPathEntry::GslPointerInit:
950
case IndirectLocalPathEntry::GslPointerAssignment:
951
// These exist primarily to mark the path as not permitting or
952
// supporting lifetime extension.
953
break;
954
955
case IndirectLocalPathEntry::VarInit:
956
if (cast<VarDecl>(Path[I].D)->isImplicit())
957
return SourceRange();
958
[[fallthrough]];
959
case IndirectLocalPathEntry::DefaultInit:
960
return Path[I].E->getSourceRange();
961
962
case IndirectLocalPathEntry::LambdaCaptureInit:
963
if (!Path[I].Capture->capturesVariable())
964
continue;
965
return Path[I].E->getSourceRange();
966
}
967
}
968
return E->getSourceRange();
969
}
970
971
static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
972
for (const auto &It : llvm::reverse(Path)) {
973
switch (It.Kind) {
974
case IndirectLocalPathEntry::VarInit:
975
case IndirectLocalPathEntry::AddressOf:
976
case IndirectLocalPathEntry::LifetimeBoundCall:
977
continue;
978
case IndirectLocalPathEntry::GslPointerInit:
979
case IndirectLocalPathEntry::GslReferenceInit:
980
case IndirectLocalPathEntry::GslPointerAssignment:
981
return true;
982
default:
983
return false;
984
}
985
}
986
return false;
987
}
988
989
static void checkExprLifetimeImpl(Sema &SemaRef,
990
const InitializedEntity *InitEntity,
991
const InitializedEntity *ExtendingEntity,
992
LifetimeKind LK,
993
const AssignedEntity *AEntity, Expr *Init,
994
bool EnableLifetimeWarnings) {
995
assert((AEntity && LK == LK_Assignment) ||
996
(InitEntity && LK != LK_Assignment));
997
// If this entity doesn't have an interesting lifetime, don't bother looking
998
// for temporaries within its initializer.
999
if (LK == LK_FullExpression)
1000
return;
1001
1002
// FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
1003
// functions to a dedicated class.
1004
auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
1005
ReferenceKind RK) -> bool {
1006
SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
1007
SourceLocation DiagLoc = DiagRange.getBegin();
1008
1009
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1010
1011
bool IsGslPtrValueFromGslTempOwner = false;
1012
bool IsLocalGslOwner = false;
1013
if (pathOnlyHandlesGslPointer(Path)) {
1014
if (isa<DeclRefExpr>(L)) {
1015
// We do not want to follow the references when returning a pointer
1016
// originating from a local owner to avoid the following false positive:
1017
// int &p = *localUniquePtr;
1018
// someContainer.add(std::move(localUniquePtr));
1019
// return p;
1020
IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
1021
if (pathContainsInit(Path) || !IsLocalGslOwner)
1022
return false;
1023
} else {
1024
IsGslPtrValueFromGslTempOwner =
1025
MTE && !MTE->getExtendingDecl() &&
1026
isRecordWithAttr<OwnerAttr>(MTE->getType());
1027
// Skipping a chain of initializing gsl::Pointer annotated objects.
1028
// We are looking only for the final source to find out if it was
1029
// a local or temporary owner or the address of a local variable/param.
1030
if (!IsGslPtrValueFromGslTempOwner)
1031
return true;
1032
}
1033
}
1034
1035
switch (LK) {
1036
case LK_FullExpression:
1037
llvm_unreachable("already handled this");
1038
1039
case LK_Extended: {
1040
if (!MTE) {
1041
// The initialized entity has lifetime beyond the full-expression,
1042
// and the local entity does too, so don't warn.
1043
//
1044
// FIXME: We should consider warning if a static / thread storage
1045
// duration variable retains an automatic storage duration local.
1046
return false;
1047
}
1048
1049
if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
1050
SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1051
<< DiagRange;
1052
return false;
1053
}
1054
1055
switch (shouldLifetimeExtendThroughPath(Path)) {
1056
case PathLifetimeKind::Extend:
1057
// Update the storage duration of the materialized temporary.
1058
// FIXME: Rebuild the expression instead of mutating it.
1059
MTE->setExtendingDecl(ExtendingEntity->getDecl(),
1060
ExtendingEntity->allocateManglingNumber());
1061
// Also visit the temporaries lifetime-extended by this initializer.
1062
return true;
1063
1064
case PathLifetimeKind::ShouldExtend:
1065
// We're supposed to lifetime-extend the temporary along this path (per
1066
// the resolution of DR1815), but we don't support that yet.
1067
//
1068
// FIXME: Properly handle this situation. Perhaps the easiest approach
1069
// would be to clone the initializer expression on each use that would
1070
// lifetime extend its temporaries.
1071
SemaRef.Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
1072
<< RK << DiagRange;
1073
break;
1074
1075
case PathLifetimeKind::NoExtend:
1076
// If the path goes through the initialization of a variable or field,
1077
// it can't possibly reach a temporary created in this full-expression.
1078
// We will have already diagnosed any problems with the initializer.
1079
if (pathContainsInit(Path))
1080
return false;
1081
1082
SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
1083
<< RK << !InitEntity->getParent()
1084
<< ExtendingEntity->getDecl()->isImplicit()
1085
<< ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
1086
break;
1087
}
1088
break;
1089
}
1090
1091
case LK_Assignment: {
1092
if (!MTE || pathContainsInit(Path))
1093
return false;
1094
assert(shouldLifetimeExtendThroughPath(Path) ==
1095
PathLifetimeKind::NoExtend &&
1096
"No lifetime extension for assignments");
1097
SemaRef.Diag(DiagLoc,
1098
IsGslPtrValueFromGslTempOwner
1099
? diag::warn_dangling_lifetime_pointer_assignment
1100
: diag::warn_dangling_pointer_assignment)
1101
<< AEntity->LHS << DiagRange;
1102
return false;
1103
}
1104
case LK_MemInitializer: {
1105
if (MTE) {
1106
// Under C++ DR1696, if a mem-initializer (or a default member
1107
// initializer used by the absence of one) would lifetime-extend a
1108
// temporary, the program is ill-formed.
1109
if (auto *ExtendingDecl =
1110
ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1111
if (IsGslPtrValueFromGslTempOwner) {
1112
SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1113
<< ExtendingDecl << DiagRange;
1114
SemaRef.Diag(ExtendingDecl->getLocation(),
1115
diag::note_ref_or_ptr_member_declared_here)
1116
<< true;
1117
return false;
1118
}
1119
bool IsSubobjectMember = ExtendingEntity != InitEntity;
1120
SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
1121
PathLifetimeKind::NoExtend
1122
? diag::err_dangling_member
1123
: diag::warn_dangling_member)
1124
<< ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1125
// Don't bother adding a note pointing to the field if we're inside
1126
// its default member initializer; our primary diagnostic points to
1127
// the same place in that case.
1128
if (Path.empty() ||
1129
Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1130
SemaRef.Diag(ExtendingDecl->getLocation(),
1131
diag::note_lifetime_extending_member_declared_here)
1132
<< RK << IsSubobjectMember;
1133
}
1134
} else {
1135
// We have a mem-initializer but no particular field within it; this
1136
// is either a base class or a delegating initializer directly
1137
// initializing the base-class from something that doesn't live long
1138
// enough.
1139
//
1140
// FIXME: Warn on this.
1141
return false;
1142
}
1143
} else {
1144
// Paths via a default initializer can only occur during error recovery
1145
// (there's no other way that a default initializer can refer to a
1146
// local). Don't produce a bogus warning on those cases.
1147
if (pathContainsInit(Path))
1148
return false;
1149
1150
// Suppress false positives for code like the one below:
1151
// Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}
1152
if (IsLocalGslOwner && pathOnlyHandlesGslPointer(Path))
1153
return false;
1154
1155
auto *DRE = dyn_cast<DeclRefExpr>(L);
1156
auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
1157
if (!VD) {
1158
// A member was initialized to a local block.
1159
// FIXME: Warn on this.
1160
return false;
1161
}
1162
1163
if (auto *Member =
1164
ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1165
bool IsPointer = !Member->getType()->isReferenceType();
1166
SemaRef.Diag(DiagLoc,
1167
IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1168
: diag::warn_bind_ref_member_to_parameter)
1169
<< Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1170
SemaRef.Diag(Member->getLocation(),
1171
diag::note_ref_or_ptr_member_declared_here)
1172
<< (unsigned)IsPointer;
1173
}
1174
}
1175
break;
1176
}
1177
1178
case LK_New:
1179
if (isa<MaterializeTemporaryExpr>(L)) {
1180
if (IsGslPtrValueFromGslTempOwner)
1181
SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1182
<< DiagRange;
1183
else
1184
SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
1185
? diag::warn_new_dangling_reference
1186
: diag::warn_new_dangling_initializer_list)
1187
<< !InitEntity->getParent() << DiagRange;
1188
} else {
1189
// We can't determine if the allocation outlives the local declaration.
1190
return false;
1191
}
1192
break;
1193
1194
case LK_Return:
1195
case LK_StmtExprResult:
1196
if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1197
// We can't determine if the local variable outlives the statement
1198
// expression.
1199
if (LK == LK_StmtExprResult)
1200
return false;
1201
SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1202
<< InitEntity->getType()->isReferenceType() << DRE->getDecl()
1203
<< isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
1204
} else if (isa<BlockExpr>(L)) {
1205
SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1206
} else if (isa<AddrLabelExpr>(L)) {
1207
// Don't warn when returning a label from a statement expression.
1208
// Leaving the scope doesn't end its lifetime.
1209
if (LK == LK_StmtExprResult)
1210
return false;
1211
SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1212
} else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1213
SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1214
<< InitEntity->getType()->isReferenceType() << CLE->getInitializer()
1215
<< 2 << DiagRange;
1216
} else {
1217
// P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
1218
// [stmt.return]/p6: In a function whose return type is a reference,
1219
// other than an invented function for std::is_convertible ([meta.rel]),
1220
// a return statement that binds the returned reference to a temporary
1221
// expression ([class.temporary]) is ill-formed.
1222
if (SemaRef.getLangOpts().CPlusPlus26 &&
1223
InitEntity->getType()->isReferenceType())
1224
SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
1225
<< InitEntity->getType()->isReferenceType() << DiagRange;
1226
else
1227
SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1228
<< InitEntity->getType()->isReferenceType() << DiagRange;
1229
}
1230
break;
1231
}
1232
1233
for (unsigned I = 0; I != Path.size(); ++I) {
1234
auto Elem = Path[I];
1235
1236
switch (Elem.Kind) {
1237
case IndirectLocalPathEntry::AddressOf:
1238
case IndirectLocalPathEntry::LValToRVal:
1239
// These exist primarily to mark the path as not permitting or
1240
// supporting lifetime extension.
1241
break;
1242
1243
case IndirectLocalPathEntry::LifetimeBoundCall:
1244
case IndirectLocalPathEntry::TemporaryCopy:
1245
case IndirectLocalPathEntry::GslPointerInit:
1246
case IndirectLocalPathEntry::GslReferenceInit:
1247
case IndirectLocalPathEntry::GslPointerAssignment:
1248
// FIXME: Consider adding a note for these.
1249
break;
1250
1251
case IndirectLocalPathEntry::DefaultInit: {
1252
auto *FD = cast<FieldDecl>(Elem.D);
1253
SemaRef.Diag(FD->getLocation(),
1254
diag::note_init_with_default_member_initializer)
1255
<< FD << nextPathEntryRange(Path, I + 1, L);
1256
break;
1257
}
1258
1259
case IndirectLocalPathEntry::VarInit: {
1260
const VarDecl *VD = cast<VarDecl>(Elem.D);
1261
SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
1262
<< VD->getType()->isReferenceType() << VD->isImplicit()
1263
<< VD->getDeclName() << nextPathEntryRange(Path, I + 1, L);
1264
break;
1265
}
1266
1267
case IndirectLocalPathEntry::LambdaCaptureInit:
1268
if (!Elem.Capture->capturesVariable())
1269
break;
1270
// FIXME: We can't easily tell apart an init-capture from a nested
1271
// capture of an init-capture.
1272
const ValueDecl *VD = Elem.Capture->getCapturedVar();
1273
SemaRef.Diag(Elem.Capture->getLocation(),
1274
diag::note_lambda_capture_initializer)
1275
<< VD << VD->isInitCapture() << Elem.Capture->isExplicit()
1276
<< (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
1277
<< nextPathEntryRange(Path, I + 1, L);
1278
break;
1279
}
1280
}
1281
1282
// We didn't lifetime-extend, so don't go any further; we don't need more
1283
// warnings or errors on inner temporaries within this one's initializer.
1284
return false;
1285
};
1286
1287
llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
1288
if (EnableLifetimeWarnings && LK == LK_Assignment &&
1289
isRecordWithAttr<PointerAttr>(AEntity->LHS->getType()))
1290
Path.push_back({IndirectLocalPathEntry::GslPointerAssignment, Init});
1291
1292
if (Init->isGLValue())
1293
visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
1294
TemporaryVisitor,
1295
EnableLifetimeWarnings);
1296
else
1297
visitLocalsRetainedByInitializer(
1298
Path, Init, TemporaryVisitor,
1299
// Don't revisit the sub inits for the intialization case.
1300
/*RevisitSubinits=*/!InitEntity, EnableLifetimeWarnings);
1301
}
1302
1303
void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity,
1304
Expr *Init) {
1305
auto LTResult = getEntityLifetime(&Entity);
1306
LifetimeKind LK = LTResult.getInt();
1307
const InitializedEntity *ExtendingEntity = LTResult.getPointer();
1308
bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
1309
diag::warn_dangling_lifetime_pointer, SourceLocation());
1310
checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK,
1311
/*AEntity*/ nullptr, Init, EnableLifetimeWarnings);
1312
}
1313
1314
void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity,
1315
Expr *Init) {
1316
bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
1317
diag::warn_dangling_lifetime_pointer, SourceLocation());
1318
bool RunAnalysis = Entity.LHS->getType()->isPointerType() ||
1319
(EnableLifetimeWarnings &&
1320
isRecordWithAttr<PointerAttr>(Entity.LHS->getType()));
1321
1322
if (!RunAnalysis)
1323
return;
1324
1325
checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
1326
/*ExtendingEntity=*/nullptr, LK_Assignment, &Entity,
1327
Init, EnableLifetimeWarnings);
1328
}
1329
1330
} // namespace clang::sema
1331
1332