15#ifndef LLVM_CLANG_LIB_SEMA_SEMALIFETIMESAFETY_H
16#define LLVM_CLANG_LIB_SEMA_SEMALIFETIMESAFETY_H
51 constexpr unsigned DiagIDs[] = {
52 diag::warn_lifetime_safety_use_after_scope,
53 diag::warn_lifetime_safety_use_after_scope_moved,
54 diag::warn_lifetime_safety_use_after_free,
55 diag::warn_lifetime_safety_return_stack_addr,
56 diag::warn_lifetime_safety_return_stack_addr_moved,
57 diag::warn_lifetime_safety_invalidation,
58 diag::warn_lifetime_safety_dangling_field,
59 diag::warn_lifetime_safety_dangling_field_moved,
60 diag::warn_lifetime_safety_dangling_global,
61 diag::warn_lifetime_safety_dangling_global_moved,
62 diag::warn_lifetime_safety_noescape_escapes,
63 diag::warn_lifetime_safety_lifetimebound_violation,
64 diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound,
65 diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound,
66 diag::warn_lifetime_safety_invalidated_field,
67 diag::warn_lifetime_safety_invalidated_global,
68 diag::warn_lifetime_safety_cross_tu_param_suggestion,
69 diag::warn_lifetime_safety_intra_tu_param_suggestion,
70 diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion,
71 diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion,
72 diag::warn_lifetime_safety_cross_tu_this_suggestion,
73 diag::warn_lifetime_safety_intra_tu_this_suggestion,
74 diag::warn_lifetime_safety_inapplicable_lifetimebound};
75 for (
unsigned DiagID : DiagIDs)
83 constexpr unsigned DiagIDs[] = {
84 diag::warn_lifetime_safety_intra_tu_param_suggestion,
85 diag::warn_lifetime_safety_cross_tu_param_suggestion,
86 diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion,
87 diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion,
88 diag::warn_lifetime_safety_intra_tu_this_suggestion,
89 diag::warn_lifetime_safety_cross_tu_this_suggestion};
90 for (
unsigned DiagID : DiagIDs)
111 unsigned DiagID = MovedExpr
112 ? diag::warn_lifetime_safety_use_after_scope_moved
113 : diag::warn_lifetime_safety_use_after_scope;
114 std::string DestroyedSubject = getDiagSubjectDescription(IssueExpr);
119 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
121 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here)
124 reportAliasingChain(ExprChain);
126 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
131 const Expr *MovedExpr)
override {
132 unsigned DiagID = MovedExpr
133 ? diag::warn_lifetime_safety_return_stack_addr_moved
134 : diag::warn_lifetime_safety_return_stack_addr;
137 << getDiagSubjectDescription(IssueExpr) << IssueExpr->
getSourceRange();
140 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
142 S.Diag(ReturnExpr->
getExprLoc(), diag::note_lifetime_safety_returned_here)
148 const Expr *MovedExpr,
bool IsCapturedByLambda,
152 ? diag::warn_lifetime_safety_dangling_field_lambda_capture
153 : (MovedExpr ? diag::warn_lifetime_safety_dangling_field_moved
154 : diag::warn_lifetime_safety_dangling_field);
157 << getDiagSubjectDescription(IssueExpr)
158 << getDiagSubjectDescription(DanglingField)
161 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
164 diag::note_lifetime_safety_dangling_field_here)
170 const Expr *MovedExpr,
172 unsigned DiagID = MovedExpr
173 ? diag::warn_lifetime_safety_dangling_global_moved
174 : diag::warn_lifetime_safety_dangling_global;
177 << getDiagSubjectDescription(IssueExpr)
178 << getDiagSubjectDescription(DanglingGlobal)
181 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
185 diag::note_lifetime_safety_dangling_static_here)
189 diag::note_lifetime_safety_dangling_global_here)
195 const Expr *InvalidationExpr,
198 ? diag::warn_lifetime_safety_use_after_free
199 : diag::warn_lifetime_safety_invalidation;
200 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
203 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
204 reportAliasingChain(ExprChain);
205 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
210 const Expr *InvalidationExpr,
214 ? diag::warn_lifetime_safety_use_after_free
215 : diag::warn_lifetime_safety_invalidation;
216 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
220 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
221 reportAliasingChain(ExprChain);
222 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
228 const Expr *InvalidationExpr)
override {
229 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
231 diag::warn_lifetime_safety_invalidated_field)
232 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
234 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
236 diag::note_lifetime_safety_dangling_field_here)
242 const Expr *InvalidationExpr)
override {
243 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
245 diag::warn_lifetime_safety_invalidated_field)
246 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
248 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
250 diag::note_lifetime_safety_dangling_field_here)
256 const Expr *InvalidationExpr)
override {
257 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
259 diag::warn_lifetime_safety_invalidated_global)
260 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
262 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
265 diag::note_lifetime_safety_dangling_static_here)
269 diag::note_lifetime_safety_dangling_global_here)
275 const Expr *InvalidationExpr)
override {
276 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
278 diag::warn_lifetime_safety_invalidated_global)
279 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
281 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
284 diag::note_lifetime_safety_dangling_static_here)
288 diag::note_lifetime_safety_dangling_global_here)
298 ? diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion
299 : diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion;
302 ? diag::warn_lifetime_safety_cross_tu_param_suggestion
303 : diag::warn_lifetime_safety_intra_tu_param_suggestion;
305 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(ParmToAnnotate);
307 S.Diag(InsertionPoint, DiagID)
311 if (
const auto *EscapeExpr =
Target.dyn_cast<
const Expr *>())
312 S.Diag(EscapeExpr->getBeginLoc(),
313 diag::note_lifetime_safety_suggestion_returned_here)
314 << EscapeExpr->getSourceRange();
315 else if (
const auto *EscapeField =
Target.dyn_cast<
const FieldDecl *>())
316 S.Diag(EscapeField->getLocation(),
317 diag::note_lifetime_safety_escapes_to_field_here)
318 << EscapeField->getSourceRange();
322 const ParmVarDecl *ParmWithLifetimebound)
override {
323 const auto *
Attr = ParmWithLifetimebound->
getAttr<LifetimeBoundAttr>();
324 StringRef ParamName = ParmWithLifetimebound->
getName();
325 bool HasName = ParamName.size() > 0;
327 diag::warn_lifetime_safety_lifetimebound_violation)
335 assert(
Attr &&
"Expected lifetimebound attribute");
337 diag::warn_lifetime_safety_lifetimebound_violation)
345 assert(
Attr &&
"Expected lifetimebound attribute");
348 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
349 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
351 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(FDecl);
357 if (IsMacro || InsertionPoint.isInvalid())
360 S.Diag(InsertionPoint, DiagID)
363 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
371 const auto *
Attr = PVDDef->
getAttr<LifetimeBoundAttr>();
372 assert(
Attr &&
"Expected lifetimebound attribute");
375 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
376 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
378 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(PVDDecl);
384 if (IsMacro || InsertionPoint.isInvalid())
387 S.Diag(InsertionPoint, DiagID)
391 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
396 assert(PVD->
hasAttr<LifetimeBoundAttr>() &&
397 "Expected parameter to have lifetimebound attribute");
398 const auto *
Attr = PVD->
getAttr<LifetimeBoundAttr>();
400 diag::warn_lifetime_safety_inapplicable_lifetimebound)
406 const Expr *EscapeExpr)
override {
408 ? diag::warn_lifetime_safety_cross_tu_this_suggestion
409 : diag::warn_lifetime_safety_intra_tu_this_suggestion;
411 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(MD);
413 S.Diag(InsertionPoint, DiagID)
418 diag::note_lifetime_safety_suggestion_returned_here)
423 const Expr *EscapeExpr)
override {
425 diag::warn_lifetime_safety_noescape_escapes)
429 diag::note_lifetime_safety_suggestion_returned_here)
436 diag::warn_lifetime_safety_noescape_escapes)
440 diag::note_lifetime_safety_escapes_to_field_here)
445 const VarDecl *EscapeGlobal)
override {
447 diag::warn_lifetime_safety_noescape_escapes)
451 diag::note_lifetime_safety_escapes_to_static_storage_here)
455 diag::note_lifetime_safety_escapes_to_global_here)
460 S.addLifetimeBoundToImplicitThis(
const_cast<CXXMethodDecl *
>(MD));
464 struct LifetimeBoundMacroCache {
465 bool IsBuilt =
false;
469 void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &
Cache,
476 for (
const auto &M : PP.
macros()) {
485 const MacroInfo *MI = Def.getMacroInfo();
487 std::equal(Tokens.begin(), Tokens.end(), MI->
tokens_begin())) {
488 Cache.Candidates.push_back(II);
493 Cache.IsBuilt =
true;
496 StringRef getLastCachedMacroWithSpelling(SourceLocation Loc,
497 llvm::ArrayRef<TokenValue> Tokens,
498 LifetimeBoundMacroCache &
Cache) {
502 buildLifetimeBoundMacroCache(
Cache, Tokens);
504 const Preprocessor &PP = S.getPreprocessor();
506 SourceLocation BestLocation;
507 StringRef BestSpelling;
508 for (
const IdentifierInfo *II :
Cache.Candidates) {
509 const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
511 if (!Def || !Def.getMacroInfo())
515 const MacroInfo *MI = Def.getMacroInfo();
516 if (!MI->isObjectLike() || Tokens.size() != MI->getNumTokens() ||
517 !std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()))
521 SourceLocation Location = Def.getLocation();
522 assert(Location.isInvalid() ||
523 SM.isBeforeInTranslationUnit(Location, Loc));
524 if (BestLocation.isInvalid() ||
525 (Location.isValid() &&
526 SM.isBeforeInTranslationUnit(BestLocation, Location))) {
527 BestLocation = Location;
528 BestSpelling = II->getName();
534 void reportInvalidationSite(
const Expr *InvalidationExpr,
535 StringRef InvalidatedSubject) {
537 ? diag::note_lifetime_safety_freed_here
538 : diag::note_lifetime_safety_invalidated_here;
539 S.Diag(InvalidationExpr->getExprLoc(),
Diag)
540 << InvalidatedSubject << InvalidationExpr->getSourceRange();
543 std::string getLifetimeBoundFixItText(SourceLocation Loc,
bool LeadingSpace,
544 bool AllowGNUAttrMacro =
true) {
545 const bool UseCXX11AttrSpelling =
546 S.getLangOpts().CPlusPlus || S.getLangOpts().C23;
547 const StringRef Fallback = UseCXX11AttrSpelling
548 ?
"[[clang::lifetimebound]]"
549 :
"__attribute__((lifetimebound))";
550 StringRef Spelling = S.getLangOpts().LifetimeSafetyLifetimeBoundMacro;
551 if (Spelling.empty() && Loc.isValid()) {
552 const Preprocessor &PP = S.getPreprocessor();
553 if (UseCXX11AttrSpelling)
554 Spelling = getLastCachedMacroWithSpelling(
556 {tok::l_square, tok::l_square, PP.getIdentifierInfo(
"clang"),
557 tok::coloncolon, PP.getIdentifierInfo(
"lifetimebound"),
558 tok::r_square, tok::r_square},
559 ClangLifetimeBoundMacroCache);
561 if (Spelling.empty() && AllowGNUAttrMacro)
562 Spelling = getLastCachedMacroWithSpelling(
564 {tok::kw___attribute, tok::l_paren, tok::l_paren,
565 PP.getIdentifierInfo(
"lifetimebound"), tok::r_paren, tok::r_paren},
566 GNULifetimeBoundMacroCache);
568 const std::string
Text = Spelling.empty() ? Fallback.str() : Spelling.str();
569 return LeadingSpace ?
" " +
Text :
Text +
" ";
572 std::pair<SourceLocation, std::string>
573 getLifetimeBoundFixIt(
const ParmVarDecl *Decl) {
575 Decl->getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
576 bool LeadingSpace =
true;
578 if (!
Decl->getIdentifier()) {
581 InsertionPoint =
Decl->getBeginLoc();
582 LeadingSpace =
false;
583 }
else if (
Decl->hasDefaultArg()) {
587 Decl->getLocation(), 0, S.getSourceManager(), S.getLangOpts());
589 return {InsertionPoint,
590 getLifetimeBoundFixItText(InsertionPoint, LeadingSpace)};
593 std::pair<SourceLocation, std::string>
594 getLifetimeBoundFixIt(
const CXXMethodDecl *MD) {
595 const auto MDL = MD->getTypeSourceInfo()->getTypeLoc();
597 MDL.getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
599 if (
const auto *FPT = MD->getType()->getAs<FunctionProtoType>();
600 FPT && FPT->hasTrailingReturn()) {
605 const auto FTL = MDL.getAs<FunctionTypeLoc>();
612 0, S.getSourceManager(), S.getLangOpts());
614 return {InsertionPoint,
615 getLifetimeBoundFixItText(InsertionPoint,
true,
619 std::string getDiagSubjectDescription(
const ValueDecl *VD) {
621 llvm::raw_string_ostream
OS(Res);
626 }
else if (
const auto *Var = dyn_cast<VarDecl>(VD)) {
627 if (Var->isStaticLocal() || Var->isStaticDataMember())
628 OS <<
"static variable";
629 else if (Var->hasGlobalStorage())
630 OS <<
"global variable";
632 OS <<
"local variable";
637 VD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
false);
642 std::string getDiagSubjectDescription(
const Expr *E) {
643 E = E->IgnoreImpCasts();
645 return "temporary object";
647 return "allocated object";
648 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
649 return getDiagSubjectDescription(DRE->getDecl());
651 if (
const auto *CE = dyn_cast<CallExpr>(E)) {
652 const auto *FD = CE->getDirectCallee();
654 return "result of call";
658 llvm::raw_string_ostream
OS(Name);
659 FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
661 return "result of call to '" + Name +
"'";
668 bool shouldShowInAliasChain(
const Expr *CurrExpr,
const Expr *LastExpr) {
669 CurrExpr = CurrExpr->IgnoreImpCasts();
670 LastExpr = LastExpr->IgnoreImpCasts();
677 return CurrExpr->getSourceRange() != LastExpr->getSourceRange();
680 void reportAliasingChain(llvm::ArrayRef<const Expr *> OriginExprChain) {
681 if (OriginExprChain.empty())
684 const Expr *LastExpr = OriginExprChain.back();
685 std::string IssueStr = getDiagSubjectDescription(LastExpr);
687 for (
const Expr *CurrExpr : reverse(OriginExprChain.drop_back())) {
688 if (!shouldShowInAliasChain(CurrExpr, LastExpr))
690 S.Diag(CurrExpr->getBeginLoc(),
691 diag::note_lifetime_safety_aliases_storage)
692 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
698 LifetimeBoundMacroCache ClangLifetimeBoundMacroCache;
699 LifetimeBoundMacroCache GNULifetimeBoundMacroCache;
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Defines the clang::Preprocessor interface.
Attr - This represents one attribute.
SourceLocation getLocation() const
SourceRange getRange() const
Represents a static or instance method of a struct/union/class.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
Concrete class used by the front-end to report problems and issues.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
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.
DeclarationNameInfo getNameInfo() const
One of these records is kept for each identifier that is lexed.
static std::optional< Token > findPreviousToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeComments)
Finds the token that comes before the given location.
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.
DefInfo getPreviousDefinition()
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
const DefInfo findDirectiveAtLoc(SourceLocation L, const SourceManager &SM) const
Find macro definition active in the specified source location.
DefInfo getDefinition()
Traverses the macro directives history and returns the next macro definition directive along with inf...
Encapsulates the data about a macro definition (e.g.
const_tokens_iterator tokens_begin() const
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
bool isObjectLike() const
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represents a parameter to a function.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
MacroDirective * getLocalMacroDirectiveHistory(const IdentifierInfo *II) const
Given an identifier, return the latest non-imported macro directive for that identifier.
llvm::iterator_range< macro_iterator > macros(bool IncludeExternalMacros=true) const
SourceManager & getSourceManager() const
Scope - A scope is a transient data structure that is used while parsing the program.
Sema - This implements semantic analysis and AST building for C.
Preprocessor & getPreprocessor() const
DiagnosticsEngine & getDiagnostics() const
const LangOptions & getLangOpts() const
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...
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a variable declaration or definition.
bool isStaticDataMember() const
Determines whether this is a static data member.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
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 reportDanglingField(const Expr *IssueExpr, const FieldDecl *DanglingField, const Expr *MovedExpr, bool IsCapturedByLambda, SourceLocation ExpiryLoc) 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
LifetimeSafetySemaHelperImpl(Sema &S)
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 reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain) override
void reportInapplicableLifetimebound(const ParmVarDecl *PVD) override
void reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain) override
void addLifetimeBoundToImplicitThis(const CXXMethodDecl *MD) 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
LifetimeSafetySemaHelper()=default
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
const LifetimeBoundAttr * getDirectImplicitObjectLifetimeBoundAttr(const FunctionDecl *FD)
LifetimeSafetyOpts GetLifetimeSafetyOpts(Sema &S, const Decl *D)
WarningScope
Enum to track functions visible across or within TU.
const LifetimeBoundAttr * getImplicitObjectParamLifetimeBoundAttr(const FunctionDecl *FD)
bool ShouldSuggestLifetimeAnnotations(Sema &S, const Decl *D)
bool IsLifetimeSafetyEnabled(Sema &S, const Decl *D)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
bool isa(CodeGen::Address addr)
SourceRange getSourceRange() const LLVM_READONLY
getSourceRange - The range of the declaration name.
bool SuggestAnnotations
Whether to suggest lifetime annotations.
size_t MaxCFGBlocks
Maximum number of CFG blocks to analyze.