15#ifndef LLVM_CLANG_LIB_SEMA_SEMALIFETIMESAFETY_H
16#define LLVM_CLANG_LIB_SEMA_SEMALIFETIMESAFETY_H
30 constexpr unsigned DiagIDs[] = {
31 diag::warn_lifetime_safety_use_after_scope,
32 diag::warn_lifetime_safety_use_after_scope_moved,
33 diag::warn_lifetime_safety_use_after_free,
34 diag::warn_lifetime_safety_return_stack_addr,
35 diag::warn_lifetime_safety_return_stack_addr_moved,
36 diag::warn_lifetime_safety_invalidation,
37 diag::warn_lifetime_safety_dangling_field,
38 diag::warn_lifetime_safety_dangling_field_moved,
39 diag::warn_lifetime_safety_dangling_global,
40 diag::warn_lifetime_safety_dangling_global_moved,
41 diag::warn_lifetime_safety_invalidated_field,
42 diag::warn_lifetime_safety_invalidated_global};
43 for (
unsigned DiagID : DiagIDs)
51 diag::warn_lifetime_safety_noescape_escapes, D->
getBeginLoc());
56 diag::warn_lifetime_safety_lifetimebound_violation, D->
getBeginLoc());
61 constexpr unsigned DiagIDs[] = {
62 diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound,
63 diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound};
64 for (
unsigned DiagID : DiagIDs)
72 diag::warn_lifetime_safety_inapplicable_lifetimebound, D->
getBeginLoc());
77 constexpr unsigned DiagIDs[] = {
78 diag::warn_lifetime_safety_intra_tu_param_suggestion,
79 diag::warn_lifetime_safety_cross_tu_param_suggestion,
80 diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion,
81 diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion,
82 diag::warn_lifetime_safety_intra_tu_this_suggestion,
83 diag::warn_lifetime_safety_cross_tu_this_suggestion};
84 for (
unsigned DiagID : DiagIDs)
101 if (S.
getLangOpts().EnableLifetimeSafetyTUAnalysis)
141 unsigned DiagID = MovedExpr
142 ? diag::warn_lifetime_safety_use_after_scope_moved
143 : diag::warn_lifetime_safety_use_after_scope;
144 std::string DestroyedSubject = getDiagSubjectDescription(IssueExpr);
149 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
151 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here)
154 reportAliasingChain(ExprChain);
156 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
161 const Expr *MovedExpr,
163 unsigned DiagID = MovedExpr
164 ? diag::warn_lifetime_safety_return_stack_addr_moved
165 : diag::warn_lifetime_safety_return_stack_addr;
168 << getDiagSubjectDescription(IssueExpr) << IssueExpr->
getSourceRange();
171 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
174 reportAliasingChain(ExprChain);
176 S.Diag(ReturnExpr->
getExprLoc(), diag::note_lifetime_safety_returned_here)
182 const Expr *MovedExpr,
bool IsCapturedByLambda,
186 ? diag::warn_lifetime_safety_dangling_field_lambda_capture
187 : (MovedExpr ? diag::warn_lifetime_safety_dangling_field_moved
188 : diag::warn_lifetime_safety_dangling_field);
191 << getDiagSubjectDescription(IssueExpr)
192 << getDiagSubjectDescription(DanglingField)
195 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
198 diag::note_lifetime_safety_dangling_field_here)
205 bool IsMain =
false)
override {
208 DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved
209 : diag::warn_lifetime_safety_dangling_global_in_main;
211 DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved
212 : diag::warn_lifetime_safety_dangling_global;
216 << getDiagSubjectDescription(IssueExpr)
217 << getDiagSubjectDescription(DanglingGlobal)
220 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
224 diag::note_lifetime_safety_dangling_static_here)
228 diag::note_lifetime_safety_dangling_global_here)
234 const Expr *InvalidationExpr,
237 ? diag::warn_lifetime_safety_use_after_free
238 : diag::warn_lifetime_safety_invalidation;
239 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
242 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
243 reportAliasingChain(ExprChain);
244 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
249 const Expr *InvalidationExpr,
253 ? diag::warn_lifetime_safety_use_after_free
254 : diag::warn_lifetime_safety_invalidation;
255 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
259 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
260 reportAliasingChain(ExprChain);
261 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
267 const Expr *InvalidationExpr)
override {
268 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
270 diag::warn_lifetime_safety_invalidated_field)
271 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
273 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
275 diag::note_lifetime_safety_dangling_field_here)
281 const Expr *InvalidationExpr)
override {
282 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
284 diag::warn_lifetime_safety_invalidated_field)
285 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
287 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
289 diag::note_lifetime_safety_dangling_field_here)
295 const Expr *InvalidationExpr)
override {
296 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
298 diag::warn_lifetime_safety_invalidated_global)
299 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
301 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
304 diag::note_lifetime_safety_dangling_static_here)
308 diag::note_lifetime_safety_dangling_global_here)
314 const Expr *InvalidationExpr)
override {
315 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
317 diag::warn_lifetime_safety_invalidated_global)
318 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
320 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
323 diag::note_lifetime_safety_dangling_static_here)
327 diag::note_lifetime_safety_dangling_global_here)
337 ? diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion
338 : diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion;
341 ? diag::warn_lifetime_safety_cross_tu_param_suggestion
342 : diag::warn_lifetime_safety_intra_tu_param_suggestion;
344 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(ParmToAnnotate);
346 S.Diag(InsertionPoint, DiagID)
350 if (
const auto *EscapeExpr = dyn_cast<const Expr *>(
Target))
351 S.Diag(EscapeExpr->getBeginLoc(),
352 diag::note_lifetime_safety_suggestion_returned_here)
353 << EscapeExpr->getSourceRange();
354 else if (
const auto *EscapeField = dyn_cast<const FieldDecl *>(
Target))
355 S.Diag(EscapeField->getLocation(),
356 diag::note_lifetime_safety_escapes_to_field_here)
357 << EscapeField->getSourceRange();
361 const ParmVarDecl *ParmWithLifetimebound)
override {
362 const auto *
Attr = ParmWithLifetimebound->
getAttr<LifetimeBoundAttr>();
363 StringRef ParamName = ParmWithLifetimebound->
getName();
364 bool HasName = ParamName.size() > 0;
366 diag::warn_lifetime_safety_lifetimebound_violation)
374 assert(
Attr &&
"Expected lifetimebound attribute");
376 diag::warn_lifetime_safety_lifetimebound_violation)
384 assert(
Attr &&
"Expected lifetimebound attribute");
387 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
388 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
390 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(FDecl);
396 if (IsMacro || InsertionPoint.isInvalid())
399 S.Diag(InsertionPoint, DiagID)
402 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
410 const auto *
Attr = PVDDef->
getAttr<LifetimeBoundAttr>();
411 assert(
Attr &&
"Expected lifetimebound attribute");
414 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
415 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
417 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(PVDDecl);
423 if (IsMacro || InsertionPoint.isInvalid())
426 S.Diag(InsertionPoint, DiagID)
430 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
435 assert(PVD->
hasAttr<LifetimeBoundAttr>() &&
436 "Expected parameter to have lifetimebound attribute");
437 const auto *
Attr = PVD->
getAttr<LifetimeBoundAttr>();
439 diag::warn_lifetime_safety_inapplicable_lifetimebound)
445 const Expr *EscapeExpr)
override {
447 ? diag::warn_lifetime_safety_cross_tu_this_suggestion
448 : diag::warn_lifetime_safety_intra_tu_this_suggestion;
450 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(MD);
452 S.Diag(InsertionPoint, DiagID)
457 diag::note_lifetime_safety_suggestion_returned_here)
462 const Expr *EscapeExpr)
override {
464 diag::warn_lifetime_safety_noescape_escapes)
468 diag::note_lifetime_safety_suggestion_returned_here)
475 diag::warn_lifetime_safety_noescape_escapes)
479 diag::note_lifetime_safety_escapes_to_field_here)
484 const VarDecl *EscapeGlobal)
override {
486 diag::warn_lifetime_safety_noescape_escapes)
490 diag::note_lifetime_safety_escapes_to_static_storage_here)
494 diag::note_lifetime_safety_escapes_to_global_here)
499 S.addLifetimeBoundToImplicitThis(
const_cast<CXXMethodDecl *
>(MD));
503 struct LifetimeBoundMacroCache {
504 bool IsBuilt =
false;
508 void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &
Cache,
515 for (
const auto &M : PP.
macros()) {
524 const MacroInfo *MI = Def.getMacroInfo();
526 std::equal(Tokens.begin(), Tokens.end(), MI->
tokens_begin())) {
527 Cache.Candidates.push_back(II);
532 Cache.IsBuilt =
true;
535 StringRef getLastCachedMacroWithSpelling(SourceLocation Loc,
536 llvm::ArrayRef<TokenValue> Tokens,
537 LifetimeBoundMacroCache &
Cache) {
541 buildLifetimeBoundMacroCache(
Cache, Tokens);
543 const Preprocessor &PP = S.getPreprocessor();
545 SourceLocation BestLocation;
546 StringRef BestSpelling;
547 for (
const IdentifierInfo *II :
Cache.Candidates) {
548 const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
550 if (!Def || !Def.getMacroInfo())
554 const MacroInfo *MI = Def.getMacroInfo();
555 if (!MI->isObjectLike() || Tokens.size() != MI->getNumTokens() ||
556 !std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()))
560 SourceLocation Location = Def.getLocation();
561 assert(Location.isInvalid() ||
562 SM.isBeforeInTranslationUnit(Location, Loc));
563 if (BestLocation.isInvalid() ||
564 (Location.isValid() &&
565 SM.isBeforeInTranslationUnit(BestLocation, Location))) {
566 BestLocation = Location;
567 BestSpelling = II->getName();
573 void reportInvalidationSite(
const Expr *InvalidationExpr,
574 StringRef InvalidatedSubject) {
576 ? diag::note_lifetime_safety_freed_here
577 : diag::note_lifetime_safety_invalidated_here;
578 S.Diag(InvalidationExpr->getExprLoc(),
Diag)
579 << InvalidatedSubject << InvalidationExpr->getSourceRange();
582 std::string getLifetimeBoundFixItText(SourceLocation Loc,
bool LeadingSpace,
583 bool AllowGNUAttrMacro =
true) {
584 const bool UseCXX11AttrSpelling =
585 S.getLangOpts().CPlusPlus || S.getLangOpts().C23;
586 const StringRef Fallback = UseCXX11AttrSpelling
587 ?
"[[clang::lifetimebound]]"
588 :
"__attribute__((lifetimebound))";
589 StringRef Spelling = S.getLangOpts().LifetimeSafetyLifetimeBoundMacro;
590 if (Spelling.empty() && Loc.isValid()) {
591 const Preprocessor &PP = S.getPreprocessor();
592 if (UseCXX11AttrSpelling)
593 Spelling = getLastCachedMacroWithSpelling(
595 {tok::l_square, tok::l_square, PP.getIdentifierInfo(
"clang"),
596 tok::coloncolon, PP.getIdentifierInfo(
"lifetimebound"),
597 tok::r_square, tok::r_square},
598 ClangLifetimeBoundMacroCache);
600 if (Spelling.empty() && AllowGNUAttrMacro)
601 Spelling = getLastCachedMacroWithSpelling(
603 {tok::kw___attribute, tok::l_paren, tok::l_paren,
604 PP.getIdentifierInfo(
"lifetimebound"), tok::r_paren, tok::r_paren},
605 GNULifetimeBoundMacroCache);
607 const std::string
Text = Spelling.empty() ? Fallback.str() : Spelling.str();
608 return LeadingSpace ?
" " +
Text :
Text +
" ";
611 std::pair<SourceLocation, std::string>
612 getLifetimeBoundFixIt(
const ParmVarDecl *Decl) {
614 Decl->getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
615 bool LeadingSpace =
true;
617 if (!
Decl->getIdentifier()) {
620 InsertionPoint =
Decl->getBeginLoc();
621 LeadingSpace =
false;
622 }
else if (
Decl->hasDefaultArg()) {
626 Decl->getLocation(), 0, S.getSourceManager(), S.getLangOpts());
628 return {InsertionPoint,
629 getLifetimeBoundFixItText(InsertionPoint, LeadingSpace)};
632 std::pair<SourceLocation, std::string>
633 getLifetimeBoundFixIt(
const CXXMethodDecl *MD) {
634 const auto MDL = MD->getTypeSourceInfo()->getTypeLoc();
636 MDL.getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
638 if (
const auto *FPT = MD->getType()->getAs<FunctionProtoType>();
639 FPT && FPT->hasTrailingReturn()) {
644 const auto FTL = MDL.getAs<FunctionTypeLoc>();
651 0, S.getSourceManager(), S.getLangOpts());
653 return {InsertionPoint,
654 getLifetimeBoundFixItText(InsertionPoint,
true,
658 std::string getDiagSubjectDescription(
const ValueDecl *VD) {
660 llvm::raw_string_ostream
OS(Res);
665 }
else if (
const auto *Var = dyn_cast<VarDecl>(VD)) {
666 if (Var->isStaticLocal() || Var->isStaticDataMember())
667 OS <<
"static variable";
668 else if (Var->hasGlobalStorage())
669 OS <<
"global variable";
671 OS <<
"local variable";
676 VD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
false);
681 std::string getDiagSubjectDescription(
const Expr *E) {
682 E = E->IgnoreImpCasts();
684 return "temporary object";
686 return "allocated object";
687 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
688 return getDiagSubjectDescription(DRE->getDecl());
690 if (
const auto *CE = dyn_cast<CallExpr>(E)) {
691 const auto *FD = CE->getDirectCallee();
693 return "result of call";
695 llvm::raw_string_ostream
OS(Name);
696 FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
698 return "result of call to '" + Name +
"'";
705 bool shouldShowInAliasChain(
const Expr *CurrExpr,
const Expr *LastExpr) {
706 CurrExpr = CurrExpr->IgnoreImpCasts();
707 LastExpr = LastExpr->IgnoreImpCasts();
714 return CurrExpr->getSourceRange() != LastExpr->getSourceRange();
717 void reportAliasingChain(llvm::ArrayRef<const Expr *> OriginExprChain) {
718 if (OriginExprChain.empty())
721 const Expr *LastExpr = OriginExprChain.back();
722 const Expr *VisibleLastExpr = LastExpr;
723 std::string IssueStr = getDiagSubjectDescription(VisibleLastExpr);
725 for (
const Expr *CurrExpr : reverse(OriginExprChain.drop_back())) {
726 if (!shouldShowInAliasChain(CurrExpr, VisibleLastExpr)) {
730 std::optional<LifetimeBoundParamInfo> ParamInfo =
735 bool IsInferred =
true;
736 std::string ParamName;
737 if (!IsImplicitObject) {
739 if (
const auto *Attr = Param->getAttr<LifetimeBoundAttr>())
740 IsInferred = Attr->isImplicit();
741 ParamName = Param->getIdentifier()
742 ?
"'" + Param->getNameAsString() +
"'"
746 IsInferred = Attr->isImplicit();
748 S.Diag(CurrExpr->getBeginLoc(),
749 diag::note_lifetime_safety_aliases_storage_lifetimebound)
750 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
751 << IssueStr << IsImplicitObject << ParamName << IsInferred;
753 S.Diag(CurrExpr->getBeginLoc(),
754 diag::note_lifetime_safety_aliases_storage)
755 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
757 VisibleLastExpr = CurrExpr;
761 LifetimeBoundMacroCache ClangLifetimeBoundMacroCache;
762 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 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 reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr, const Expr *MovedExpr, llvm::ArrayRef< const Expr * > ExprChain) 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, bool IsMain=false) 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)
bool ShouldCheckLifetimeboundViolations(Sema &S, const Decl *D)
LifetimeSafetyOpts GetLifetimeSafetyOpts(Sema &S, const Decl *D)
WarningScope
Enum to track functions visible across or within TU.
bool ShouldCheckNoescapeViolations(Sema &S, const Decl *D)
bool ShouldCheckInapplicableLifetimebound(Sema &S, const Decl *D)
const LifetimeBoundAttr * getImplicitObjectParamLifetimeBoundAttr(const FunctionDecl *FD)
std::optional< LifetimeBoundParamInfo > getTrackingInfoForCallArg(const Expr *Call, const Expr *Source)
bool ShouldSuggestLifetimeAnnotations(Sema &S, const Decl *D)
bool ShouldCheckMisplacedLifetimebound(Sema &S, const Decl *D)
bool ShouldCheckSafety(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)
U cast(CodeGen::Address addr)
SourceRange getSourceRange() const LLVM_READONLY
getSourceRange - The range of the declaration name.
bool SuggestAnnotations
Whether to suggest lifetime annotations.
bool CheckNoescapeViolations
size_t MaxCFGBlocks
Maximum number of CFG blocks to analyze.
bool CheckMisplacedLifetimebound
bool CheckInapplicableLifetimebound
bool CheckLifetimeboundViolations