clang 23.0.0git
SemaLifetimeSafety.h
Go to the documentation of this file.
1//===--- SemaLifetimeSafety.h - Sema support for lifetime safety =---------==//
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// This file defines the Sema-specific implementation for lifetime safety
10// analysis. It provides diagnostic reporting and helper functions that bridge
11// the lifetime safety analysis framework with Sema's diagnostic engine.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_LIB_SEMA_SEMALIFETIMESAFETY_H
16#define LLVM_CLANG_LIB_SEMA_SEMALIFETIMESAFETY_H
17
21#include "clang/Lex/Lexer.h"
22#include "clang/Sema/Sema.h"
23#include <string>
24
25namespace clang::lifetimes {
26
27inline bool IsLifetimeSafetyEnabled(Sema &S, const Decl *D) {
28 if (S.getLangOpts().DebugRunLifetimeSafety)
29 return true;
31 constexpr unsigned DiagIDs[] = {
32 diag::warn_lifetime_safety_use_after_scope,
33 diag::warn_lifetime_safety_use_after_scope_moved,
34 diag::warn_lifetime_safety_use_after_free,
35 diag::warn_lifetime_safety_return_stack_addr,
36 diag::warn_lifetime_safety_return_stack_addr_moved,
37 diag::warn_lifetime_safety_invalidation,
38 diag::warn_lifetime_safety_dangling_field,
39 diag::warn_lifetime_safety_dangling_field_moved,
40 diag::warn_lifetime_safety_dangling_global,
41 diag::warn_lifetime_safety_dangling_global_moved,
42 diag::warn_lifetime_safety_noescape_escapes,
43 diag::warn_lifetime_safety_lifetimebound_violation,
44 diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound,
45 diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound,
46 diag::warn_lifetime_safety_invalidated_field,
47 diag::warn_lifetime_safety_invalidated_global,
48 diag::warn_lifetime_safety_cross_tu_param_suggestion,
49 diag::warn_lifetime_safety_intra_tu_param_suggestion,
50 diag::warn_lifetime_safety_cross_tu_this_suggestion,
51 diag::warn_lifetime_safety_intra_tu_this_suggestion,
52 diag::warn_lifetime_safety_inapplicable_lifetimebound};
53 for (unsigned DiagID : DiagIDs)
54 if (!Diags.isIgnored(DiagID, D->getBeginLoc()))
55 return true;
56 return false;
57}
58
60
61public:
63
64 void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
65 const Expr *MovedExpr, SourceLocation FreeLoc,
66 llvm::ArrayRef<const Expr *> ExprChain) override {
67 unsigned DiagID = MovedExpr
68 ? diag::warn_lifetime_safety_use_after_scope_moved
69 : diag::warn_lifetime_safety_use_after_scope;
70
71 S.Diag(IssueExpr->getExprLoc(), DiagID)
72 << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange();
73 if (MovedExpr)
74 S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
75 << MovedExpr->getSourceRange();
76 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here);
77
78 reportAliasingChain(ExprChain);
79
80 S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
81 << UseExpr->getSourceRange();
82 }
83
84 void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr,
85 const Expr *MovedExpr) override {
86 unsigned DiagID = MovedExpr
87 ? diag::warn_lifetime_safety_return_stack_addr_moved
88 : diag::warn_lifetime_safety_return_stack_addr;
89
90 S.Diag(IssueExpr->getExprLoc(), DiagID)
91 << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange();
92
93 if (MovedExpr)
94 S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
95 << MovedExpr->getSourceRange();
96 S.Diag(ReturnExpr->getExprLoc(), diag::note_lifetime_safety_returned_here)
97 << ReturnExpr->getSourceRange();
98 }
99
100 void reportDanglingField(const Expr *IssueExpr,
101 const FieldDecl *DanglingField,
102 const Expr *MovedExpr,
103 SourceLocation ExpiryLoc) override {
104 unsigned DiagID = MovedExpr
105 ? diag::warn_lifetime_safety_dangling_field_moved
106 : diag::warn_lifetime_safety_dangling_field;
107
108 S.Diag(IssueExpr->getExprLoc(), DiagID)
109 << getDiagSubjectDescription(IssueExpr)
110 << getDiagSubjectDescription(DanglingField)
111 << IssueExpr->getSourceRange();
112 if (MovedExpr)
113 S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
114 << MovedExpr->getSourceRange();
115 S.Diag(DanglingField->getLocation(),
116 diag::note_lifetime_safety_dangling_field_here)
117 << DanglingField->getEndLoc();
118 }
119
120 void reportDanglingGlobal(const Expr *IssueExpr,
121 const VarDecl *DanglingGlobal,
122 const Expr *MovedExpr,
123 SourceLocation ExpiryLoc) override {
124 unsigned DiagID = MovedExpr
125 ? diag::warn_lifetime_safety_dangling_global_moved
126 : diag::warn_lifetime_safety_dangling_global;
127
128 S.Diag(IssueExpr->getExprLoc(), DiagID)
129 << getDiagSubjectDescription(IssueExpr)
130 << getDiagSubjectDescription(DanglingGlobal)
131 << IssueExpr->getSourceRange();
132 if (MovedExpr)
133 S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
134 << MovedExpr->getSourceRange();
135 if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
136 S.Diag(DanglingGlobal->getLocation(),
137 diag::note_lifetime_safety_dangling_static_here)
138 << DanglingGlobal->getEndLoc();
139 else
140 S.Diag(DanglingGlobal->getLocation(),
141 diag::note_lifetime_safety_dangling_global_here)
142 << DanglingGlobal->getEndLoc();
143 }
144
145 void reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr,
146 const Expr *InvalidationExpr) override {
147 auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
148 ? diag::warn_lifetime_safety_use_after_free
149 : diag::warn_lifetime_safety_invalidation;
150 auto UseDiag = isa<CXXDeleteExpr>(InvalidationExpr)
151 ? diag::note_lifetime_safety_freed_here
152 : diag::note_lifetime_safety_invalidated_here;
153 S.Diag(IssueExpr->getExprLoc(), WarnDiag)
154 << false << IssueExpr->getSourceRange();
155 S.Diag(InvalidationExpr->getExprLoc(), UseDiag)
156 << InvalidationExpr->getSourceRange();
157 S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
158 << UseExpr->getSourceRange();
159 }
160 void reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr,
161 const Expr *InvalidationExpr) override {
162
163 auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
164 ? diag::warn_lifetime_safety_use_after_free
165 : diag::warn_lifetime_safety_invalidation;
166 auto UseDiag = isa<CXXDeleteExpr>(InvalidationExpr)
167 ? diag::note_lifetime_safety_freed_here
168 : diag::note_lifetime_safety_invalidated_here;
169
170 S.Diag(PVD->getSourceRange().getBegin(), WarnDiag)
171 << true << PVD->getSourceRange();
172 S.Diag(InvalidationExpr->getExprLoc(), UseDiag)
173 << InvalidationExpr->getSourceRange();
174 S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
175 << UseExpr->getSourceRange();
176 }
177
178 void reportInvalidatedField(const Expr *IssueExpr,
179 const FieldDecl *DanglingField,
180 const Expr *InvalidationExpr) override {
181 auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
182 ? diag::note_lifetime_safety_freed_here
183 : diag::note_lifetime_safety_invalidated_here;
184 S.Diag(IssueExpr->getExprLoc(),
185 diag::warn_lifetime_safety_invalidated_field)
186 << false << IssueExpr->getSourceRange();
187 S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
188 << InvalidationExpr->getSourceRange();
189 S.Diag(DanglingField->getLocation(),
190 diag::note_lifetime_safety_dangling_field_here)
191 << DanglingField->getEndLoc();
192 }
193
195 const FieldDecl *DanglingField,
196 const Expr *InvalidationExpr) override {
197 auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
198 ? diag::note_lifetime_safety_freed_here
199 : diag::note_lifetime_safety_invalidated_here;
200 S.Diag(PVD->getSourceRange().getBegin(),
201 diag::warn_lifetime_safety_invalidated_field)
202 << true << PVD->getSourceRange();
203 S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
204 << InvalidationExpr->getSourceRange();
205 S.Diag(DanglingField->getLocation(),
206 diag::note_lifetime_safety_dangling_field_here)
207 << DanglingField->getEndLoc();
208 }
209
210 void reportInvalidatedGlobal(const Expr *IssueExpr,
211 const VarDecl *DanglingGlobal,
212 const Expr *InvalidationExpr) override {
213 auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
214 ? diag::note_lifetime_safety_freed_here
215 : diag::note_lifetime_safety_invalidated_here;
216 S.Diag(IssueExpr->getExprLoc(),
217 diag::warn_lifetime_safety_invalidated_global)
218 << false << IssueExpr->getSourceRange();
219 S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
220 << InvalidationExpr->getSourceRange();
221 if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
222 S.Diag(DanglingGlobal->getLocation(),
223 diag::note_lifetime_safety_dangling_static_here)
224 << DanglingGlobal->getEndLoc();
225 else
226 S.Diag(DanglingGlobal->getLocation(),
227 diag::note_lifetime_safety_dangling_global_here)
228 << DanglingGlobal->getEndLoc();
229 }
230
232 const VarDecl *DanglingGlobal,
233 const Expr *InvalidationExpr) override {
234 auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
235 ? diag::note_lifetime_safety_freed_here
236 : diag::note_lifetime_safety_invalidated_here;
237 S.Diag(PVD->getSourceRange().getBegin(),
238 diag::warn_lifetime_safety_invalidated_global)
239 << true << PVD->getSourceRange();
240 S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
241 << InvalidationExpr->getSourceRange();
242 if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
243 S.Diag(DanglingGlobal->getLocation(),
244 diag::note_lifetime_safety_dangling_static_here)
245 << DanglingGlobal->getEndLoc();
246 else
247 S.Diag(DanglingGlobal->getLocation(),
248 diag::note_lifetime_safety_dangling_global_here)
249 << DanglingGlobal->getEndLoc();
250 }
251
253 const ParmVarDecl *ParmToAnnotate,
254 EscapingTarget Target) override {
255 unsigned DiagID =
257 ? diag::warn_lifetime_safety_cross_tu_param_suggestion
258 : diag::warn_lifetime_safety_intra_tu_param_suggestion;
259
260 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(ParmToAnnotate);
261
262 S.Diag(ParmToAnnotate->getBeginLoc(), DiagID)
263 << ParmToAnnotate->getSourceRange()
264 << FixItHint::CreateInsertion(InsertionPoint, FixItText);
265
266 if (const auto *EscapeExpr = Target.dyn_cast<const Expr *>())
267 S.Diag(EscapeExpr->getBeginLoc(),
268 diag::note_lifetime_safety_suggestion_returned_here)
269 << EscapeExpr->getSourceRange();
270 else if (const auto *EscapeField = Target.dyn_cast<const FieldDecl *>())
271 S.Diag(EscapeField->getLocation(),
272 diag::note_lifetime_safety_escapes_to_field_here)
273 << EscapeField->getSourceRange();
274 }
275
277 const ParmVarDecl *ParmWithLifetimebound) override {
278 const auto *Attr = ParmWithLifetimebound->getAttr<LifetimeBoundAttr>();
279 StringRef ParamName = ParmWithLifetimebound->getName();
280 bool HasName = ParamName.size() > 0;
281 S.Diag(Attr->getLocation(),
282 diag::warn_lifetime_safety_lifetimebound_violation)
283 << HasName << ParamName << Attr->getRange();
284 }
285
287 const CXXMethodDecl *MDWithLifetimebound) override {
288 const auto *Attr =
289 getImplicitObjectParamLifetimeBoundAttr(MDWithLifetimebound);
290 assert(Attr && "Expected lifetimebound attribute");
291 S.Diag(Attr->getLocation(),
292 diag::warn_lifetime_safety_lifetimebound_violation)
293 << 2 << "" << Attr->getRange();
294 }
295
297 const CXXMethodDecl *FDef,
298 const CXXMethodDecl *FDecl) override {
300 assert(Attr && "Expected lifetimebound attribute");
301 unsigned DiagID =
303 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
304 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
305
306 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(FDecl);
307
308 // Do not emit fix-its in macros or at invalid locations.
309 bool IsMacro =
310 FDecl->getBeginLoc().isMacroID() || InsertionPoint.isMacroID();
311
312 if (IsMacro || InsertionPoint.isInvalid())
313 S.Diag(FDecl->getLocation(), DiagID);
314 else
315 S.Diag(InsertionPoint, DiagID)
316 << FixItHint::CreateInsertion(InsertionPoint, FixItText);
317
318 S.Diag(Attr->getLocation(), diag::note_lifetime_safety_lifetimebound_here)
319 << Attr->getRange();
320 }
321
323 const ParmVarDecl *PVDDef,
324 const ParmVarDecl *PVDDecl) override {
325
326 const auto *Attr = PVDDef->getAttr<LifetimeBoundAttr>();
327 assert(Attr && "Expected lifetimebound attribute");
328 unsigned DiagID =
330 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
331 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
332
333 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(PVDDecl);
334
335 // Do not emit fix-its in macros or at invalid locations.
336 bool IsMacro =
337 PVDDecl->getBeginLoc().isMacroID() || InsertionPoint.isMacroID();
338
339 if (IsMacro || InsertionPoint.isInvalid())
340 S.Diag(PVDDecl->getBeginLoc(), DiagID) << PVDDecl->getSourceRange();
341 else
342 S.Diag(PVDDecl->getBeginLoc(), DiagID)
343 << PVDDecl->getSourceRange()
344 << FixItHint::CreateInsertion(InsertionPoint, FixItText);
345
346 S.Diag(Attr->getLocation(), diag::note_lifetime_safety_lifetimebound_here)
347 << Attr->getRange();
348 }
349
351 assert(PVD->hasAttr<LifetimeBoundAttr>() &&
352 "Expected parameter to have lifetimebound attribute");
353 const auto *Attr = PVD->getAttr<LifetimeBoundAttr>();
354 S.Diag(Attr->getLocation(),
355 diag::warn_lifetime_safety_inapplicable_lifetimebound)
356 << PVD->getType() << Attr->getRange();
357 }
358
360 const CXXMethodDecl *MD,
361 const Expr *EscapeExpr) override {
362 unsigned DiagID = (Scope == WarningScope::CrossTU)
363 ? diag::warn_lifetime_safety_cross_tu_this_suggestion
364 : diag::warn_lifetime_safety_intra_tu_this_suggestion;
365
366 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(MD);
367
368 S.Diag(InsertionPoint, DiagID)
369 << MD->getNameInfo().getSourceRange()
370 << FixItHint::CreateInsertion(InsertionPoint, FixItText);
371
372 S.Diag(EscapeExpr->getBeginLoc(),
373 diag::note_lifetime_safety_suggestion_returned_here)
374 << EscapeExpr->getSourceRange();
375 }
376
377 void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
378 const Expr *EscapeExpr) override {
379 S.Diag(ParmWithNoescape->getBeginLoc(),
380 diag::warn_lifetime_safety_noescape_escapes)
381 << ParmWithNoescape->getSourceRange();
382
383 S.Diag(EscapeExpr->getBeginLoc(),
384 diag::note_lifetime_safety_suggestion_returned_here)
385 << EscapeExpr->getSourceRange();
386 }
387
388 void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
389 const FieldDecl *EscapeField) override {
390 S.Diag(ParmWithNoescape->getBeginLoc(),
391 diag::warn_lifetime_safety_noescape_escapes)
392 << ParmWithNoescape->getSourceRange();
393
394 S.Diag(EscapeField->getLocation(),
395 diag::note_lifetime_safety_escapes_to_field_here)
396 << EscapeField->getEndLoc();
397 }
398
399 void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
400 const VarDecl *EscapeGlobal) override {
401 S.Diag(ParmWithNoescape->getBeginLoc(),
402 diag::warn_lifetime_safety_noescape_escapes)
403 << ParmWithNoescape->getSourceRange();
404 if (EscapeGlobal->isStaticLocal() || EscapeGlobal->isStaticDataMember())
405 S.Diag(EscapeGlobal->getLocation(),
406 diag::note_lifetime_safety_escapes_to_static_storage_here)
407 << EscapeGlobal->getEndLoc();
408 else
409 S.Diag(EscapeGlobal->getLocation(),
410 diag::note_lifetime_safety_escapes_to_global_here)
411 << EscapeGlobal->getEndLoc();
412 }
413
415 S.addLifetimeBoundToImplicitThis(const_cast<CXXMethodDecl *>(MD));
416 }
417
418private:
419 std::pair<SourceLocation, StringRef>
420 getLifetimeBoundFixIt(const ParmVarDecl *Decl) {
423 StringRef FixItText = " [[clang::lifetimebound]]";
424
425 if (!Decl->getIdentifier()) {
426 // For unnamed parameters, placing attributes after the type would be
427 // parsed as a type attribute, not a parameter attribute.
428 InsertionPoint = Decl->getBeginLoc();
429 FixItText = "[[clang::lifetimebound]] ";
430 } else if (Decl->hasDefaultArg()) {
431 // If the parameter has a default argument, place the attribute after the
432 // named argument.
433 InsertionPoint = Lexer::getLocForEndOfToken(
435 }
436 return {InsertionPoint, FixItText};
437 }
438
439 std::pair<SourceLocation, StringRef>
440 getLifetimeBoundFixIt(const CXXMethodDecl *MD) {
441 const auto MDL = MD->getTypeSourceInfo()->getTypeLoc();
442 SourceLocation InsertionPoint = Lexer::getLocForEndOfToken(
443 MDL.getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
444
445 if (const auto *FPT = MD->getType()->getAs<FunctionProtoType>();
446 FPT && FPT->hasTrailingReturn()) {
447 // For trailing return types, 'getEndLoc()' includes the return type
448 // after '->', placing the attribute in an invalid position.
449 // Instead use 'getLocalRangeEnd()' which gives the '->' location
450 // for trailing returns, so find the last token before it.
451 const auto FTL = MDL.getAs<FunctionTypeLoc>();
452 assert(FTL);
453 InsertionPoint = Lexer::getLocForEndOfToken(
454 Lexer::findPreviousToken(FTL.getLocalRangeEnd(), S.getSourceManager(),
455 S.getLangOpts(),
456 /*IncludeComments=*/false)
457 ->getLocation(),
458 0, S.getSourceManager(), S.getLangOpts());
459 }
460 return {InsertionPoint, " [[clang::lifetimebound]]"};
461 }
462
463 std::string getDiagSubjectDescription(const ValueDecl *VD) {
464 std::string Res;
465 llvm::raw_string_ostream OS(Res);
466 if (isa<FieldDecl>(VD)) {
467 OS << "field";
468 } else if (isa<ParmVarDecl>(VD)) {
469 OS << "parameter";
470 } else if (const auto *Var = dyn_cast<VarDecl>(VD)) {
471 if (Var->isStaticLocal() || Var->isStaticDataMember())
472 OS << "static variable";
473 else if (Var->hasGlobalStorage())
474 OS << "global variable";
475 else
476 OS << "local variable";
477 } else {
478 OS << "variable";
479 }
480 OS << " '";
481 VD->getNameForDiagnostic(OS, S.getPrintingPolicy(), /*Qualified=*/false);
482 OS << "'";
483 return Res;
484 }
485
486 std::string getDiagSubjectDescription(const Expr *E) {
487 E = E->IgnoreImpCasts();
489 return "temporary object";
490
491 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
492 return getDiagSubjectDescription(DRE->getDecl());
493 // TODO: Handle other expression types.
494 return "expression";
495 }
496
497 bool shouldShowInAliasChain(const Expr *CurrExpr, const Expr *LastExpr) {
498 CurrExpr = CurrExpr->IgnoreImpCasts();
499 LastExpr = LastExpr->IgnoreImpCasts();
500
501 if (!isa<CallExpr, DeclRefExpr>(CurrExpr))
502 return false;
503 // Source ranges can be used to filter out many implicit expressions,
504 // because operations between class objects often involve numerous implicit
505 // conversions, yet they share the same source range.
506 return CurrExpr->getSourceRange() != LastExpr->getSourceRange();
507 }
508
509 void reportAliasingChain(llvm::ArrayRef<const Expr *> OriginExprChain) {
510 if (OriginExprChain.empty())
511 return;
512
513 const Expr *LastExpr = OriginExprChain.back();
514 std::string IssueStr = getDiagSubjectDescription(LastExpr);
515
516 for (const Expr *CurrExpr : reverse(OriginExprChain.drop_back())) {
517 if (!shouldShowInAliasChain(CurrExpr, LastExpr))
518 continue;
519 S.Diag(CurrExpr->getBeginLoc(),
520 diag::note_lifetime_safety_aliases_storage)
521 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
522 << IssueStr;
523 LastExpr = CurrExpr;
524 }
525 }
526
527 Sema &S;
528};
529
530} // namespace clang::lifetimes
531
532#endif // LLVM_CLANG_LIB_SEMA_SEMALIFETIMESAFETY_H
Attr - This represents one attribute.
Definition Attr.h:46
SourceLocation getLocation() const
Definition Attr.h:99
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2132
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition DeclBase.h:443
T * getAttr() const
Definition DeclBase.h:581
SourceLocation getLocation() const
Definition DeclBase.h:447
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
bool hasAttr() const
Definition DeclBase.h:585
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:233
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition Diagnostic.h:960
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
Represents a member of a struct/union/class.
Definition Decl.h:3182
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition Diagnostic.h:104
DeclarationNameInfo getNameInfo() const
Definition Decl.h:2229
static std::optional< Token > findPreviousToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeComments)
Finds the token that comes before the given location.
Definition Lexer.cpp:1406
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
Definition Lexer.cpp:881
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
Represents a parameter to a function.
Definition Decl.h:1808
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2954
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
DiagnosticsEngine & getDiagnostics() const
Definition Sema.h:936
const LangOptions & getLangOpts() const
Definition Sema.h:932
SourceManager & getSourceManager() const
Definition Sema.h:937
Encodes a location in the source.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:924
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1296
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1206
void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr, const Expr *MovedExpr) override
void reportMisplacedLifetimebound(WarningScope Scope, const ParmVarDecl *PVDDef, const ParmVarDecl *PVDDecl) override
void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, const Expr *EscapeExpr) override
void reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr, const Expr *InvalidationExpr) override
void reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *DanglingField, const Expr *InvalidationExpr) override
void reportLifetimeboundViolation(const CXXMethodDecl *MDWithLifetimebound) override
void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, const VarDecl *EscapeGlobal) override
void suggestLifetimeboundToImplicitThis(WarningScope Scope, const CXXMethodDecl *MD, const Expr *EscapeExpr) override
void reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *DanglingGlobal, const Expr *InvalidationExpr) override
void suggestLifetimeboundToParmVar(WarningScope Scope, const ParmVarDecl *ParmToAnnotate, EscapingTarget Target) override
void reportDanglingGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal, const Expr *MovedExpr, SourceLocation ExpiryLoc) override
void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr, const Expr *MovedExpr, SourceLocation FreeLoc, llvm::ArrayRef< const Expr * > ExprChain) override
void reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *DanglingField, const Expr *InvalidationExpr) override
void reportInapplicableLifetimebound(const ParmVarDecl *PVD) override
void reportDanglingField(const Expr *IssueExpr, const FieldDecl *DanglingField, const Expr *MovedExpr, SourceLocation ExpiryLoc) override
void addLifetimeBoundToImplicitThis(const CXXMethodDecl *MD) override
void reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr, const Expr *InvalidationExpr) override
void reportMisplacedLifetimebound(WarningScope Scope, const CXXMethodDecl *FDef, const CXXMethodDecl *FDecl) override
void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, const FieldDecl *EscapeField) override
void reportInvalidatedGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal, const Expr *InvalidationExpr) override
void reportLifetimeboundViolation(const ParmVarDecl *ParmWithLifetimebound) override
llvm::PointerUnion< const Expr *, const FieldDecl *, const VarDecl * > EscapingTarget
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
const LifetimeBoundAttr * getDirectImplicitObjectLifetimeBoundAttr(const FunctionDecl *FD)
WarningScope
Enum to track functions visible across or within TU.
const LifetimeBoundAttr * getImplicitObjectParamLifetimeBoundAttr(const FunctionDecl *FD)
bool IsLifetimeSafetyEnabled(Sema &S, const Decl *D)
bool isa(CodeGen::Address addr)
Definition Address.h:330
SourceRange getSourceRange() const LLVM_READONLY
getSourceRange - The range of the declaration name.