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_field_lambda_capture,
40 diag::warn_lifetime_safety_dangling_global,
41 diag::warn_lifetime_safety_dangling_global_moved,
42 diag::warn_lifetime_safety_dangling_global_in_main,
43 diag::warn_lifetime_safety_invalidated_field,
44 diag::warn_lifetime_safety_invalidated_global};
45 for (
unsigned DiagID : DiagIDs)
53 diag::warn_lifetime_safety_noescape_escapes, D->
getBeginLoc());
58 diag::warn_lifetime_safety_lifetimebound_violation, D->
getBeginLoc());
63 constexpr unsigned DiagIDs[] = {
64 diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound,
65 diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound};
66 for (
unsigned DiagID : DiagIDs)
74 diag::warn_lifetime_safety_inapplicable_lifetimebound, D->
getBeginLoc());
79 diag::warn_lifetime_safety_field_origin_escape, D->
getBeginLoc());
84 constexpr unsigned DiagIDs[] = {
85 diag::warn_lifetime_safety_intra_tu_param_suggestion,
86 diag::warn_lifetime_safety_cross_tu_param_suggestion,
87 diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion,
88 diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion,
89 diag::warn_lifetime_safety_intra_tu_this_suggestion,
90 diag::warn_lifetime_safety_cross_tu_this_suggestion};
91 for (
unsigned DiagID : DiagIDs)
108 if (S.
getLangOpts().EnableLifetimeSafetyTUAnalysis)
150 unsigned DiagID = MovedExpr
151 ? diag::warn_lifetime_safety_use_after_scope_moved
152 : diag::warn_lifetime_safety_use_after_scope;
153 std::string DestroyedSubject = getDiagSubjectDescription(IssueExpr);
158 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
160 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here)
163 reportAliasingChain(ExprChain);
165 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
172 unsigned DiagID = MovedExpr
173 ? diag::warn_lifetime_safety_use_after_scope_moved
174 : diag::warn_lifetime_safety_use_after_scope;
175 std::string DestroyedSubject = getDiagSubjectDescription(IssueExpr);
180 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
182 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here)
185 reportAliasingChain(ExprChain);
187 S.Diag(UseLoc, diag::note_lifetime_safety_used_here);
191 const Expr *MovedExpr,
193 unsigned DiagID = MovedExpr
194 ? diag::warn_lifetime_safety_return_stack_addr_moved
195 : diag::warn_lifetime_safety_return_stack_addr;
198 << getDiagSubjectDescription(IssueExpr) << IssueExpr->
getSourceRange();
201 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
204 reportAliasingChain(ExprChain);
206 S.Diag(ReturnExpr->
getExprLoc(), diag::note_lifetime_safety_returned_here)
212 const Expr *MovedExpr,
bool IsCapturedByLambda,
216 ? diag::warn_lifetime_safety_dangling_field_lambda_capture
217 : (MovedExpr ? diag::warn_lifetime_safety_dangling_field_moved
218 : diag::warn_lifetime_safety_dangling_field);
221 << getDiagSubjectDescription(IssueExpr)
222 << getDiagSubjectDescription(DanglingField)
225 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
228 diag::note_lifetime_safety_dangling_field_here)
235 bool IsMain =
false)
override {
238 DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved
239 : diag::warn_lifetime_safety_dangling_global_in_main;
241 DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved
242 : diag::warn_lifetime_safety_dangling_global;
246 << getDiagSubjectDescription(IssueExpr)
247 << getDiagSubjectDescription(DanglingGlobal)
250 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
254 diag::note_lifetime_safety_dangling_static_here)
258 diag::note_lifetime_safety_dangling_global_here)
264 const Expr *InvalidationExpr,
266 reportUseAfterInvalidationImpl(
268 getDiagSubjectDescription(IssueExpr), InvalidationExpr, ExprChain,
273 const Expr *InvalidationExpr,
275 reportUseAfterInvalidationImpl(
277 getDiagSubjectDescription(PVD), InvalidationExpr, ExprChain,
282 const Expr *InvalidationExpr,
284 reportUseAfterInvalidationImpl(
286 getDiagSubjectDescription(IssueExpr), InvalidationExpr, ExprChain,
291 const Expr *InvalidationExpr,
293 reportUseAfterInvalidationImpl(
295 getDiagSubjectDescription(PVD), InvalidationExpr, ExprChain, UseLoc,
301 const Expr *InvalidationExpr)
override {
302 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
304 diag::warn_lifetime_safety_invalidated_field)
305 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
307 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
309 diag::note_lifetime_safety_dangling_field_here)
315 const Expr *InvalidationExpr)
override {
316 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
318 diag::warn_lifetime_safety_invalidated_field)
319 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
321 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
323 diag::note_lifetime_safety_dangling_field_here)
329 const Expr *InvalidationExpr)
override {
330 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
332 diag::warn_lifetime_safety_invalidated_global)
333 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
335 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
338 diag::note_lifetime_safety_dangling_static_here)
342 diag::note_lifetime_safety_dangling_global_here)
348 const Expr *InvalidationExpr)
override {
349 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
351 diag::warn_lifetime_safety_invalidated_global)
352 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
354 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
357 diag::note_lifetime_safety_dangling_static_here)
361 diag::note_lifetime_safety_dangling_global_here)
371 ? diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion
372 : diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion;
375 ? diag::warn_lifetime_safety_cross_tu_param_suggestion
376 : diag::warn_lifetime_safety_intra_tu_param_suggestion;
378 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(ParmToAnnotate);
380 S.Diag(InsertionPoint, DiagID)
384 if (
const auto *EscapeExpr = dyn_cast<const Expr *>(
Target))
385 S.Diag(EscapeExpr->getBeginLoc(),
386 diag::note_lifetime_safety_suggestion_returned_here)
387 << EscapeExpr->getSourceRange();
388 else if (
const auto *EscapeField = dyn_cast<const FieldDecl *>(
Target))
389 S.Diag(EscapeField->getLocation(),
390 diag::note_lifetime_safety_escapes_to_field_here)
391 << EscapeField->getSourceRange();
395 const ParmVarDecl *ParmWithLifetimebound)
override {
396 const auto *
Attr = ParmWithLifetimebound->
getAttr<LifetimeBoundAttr>();
397 StringRef ParamName = ParmWithLifetimebound->
getName();
398 bool HasName = ParamName.size() > 0;
400 diag::warn_lifetime_safety_lifetimebound_violation)
408 assert(
Attr &&
"Expected lifetimebound attribute");
410 diag::warn_lifetime_safety_lifetimebound_violation)
418 assert(
Attr &&
"Expected lifetimebound attribute");
421 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
422 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
424 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(FDecl);
430 if (IsMacro || InsertionPoint.isInvalid())
433 S.Diag(InsertionPoint, DiagID)
436 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
444 const auto *
Attr = PVDDef->
getAttr<LifetimeBoundAttr>();
445 assert(
Attr &&
"Expected lifetimebound attribute");
448 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
449 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
451 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(PVDDecl);
457 if (IsMacro || InsertionPoint.isInvalid())
460 S.Diag(InsertionPoint, DiagID)
464 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
469 assert(PVD->
hasAttr<LifetimeBoundAttr>() &&
470 "Expected parameter to have lifetimebound attribute");
471 const auto *
Attr = PVD->
getAttr<LifetimeBoundAttr>();
473 diag::warn_lifetime_safety_inapplicable_lifetimebound)
479 const Expr *EscapeExpr)
override {
481 ? diag::warn_lifetime_safety_cross_tu_this_suggestion
482 : diag::warn_lifetime_safety_intra_tu_this_suggestion;
484 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(MD);
486 S.Diag(InsertionPoint, DiagID)
491 diag::note_lifetime_safety_suggestion_returned_here)
496 const Expr *EscapeExpr)
override {
497 std::string FieldDesc = getDiagSubjectDescription(FD);
498 S.Diag(MD->
getLocation(), diag::warn_lifetime_safety_field_origin_escape)
501 S.Diag(EscapeExpr->
getBeginLoc(), diag::note_lifetime_safety_returned_here)
507 diag::note_lifetime_safety_owned_field_suggestion)
512 const Expr *EscapeExpr)
override {
514 diag::warn_lifetime_safety_noescape_escapes)
518 diag::note_lifetime_safety_suggestion_returned_here)
525 diag::warn_lifetime_safety_noescape_escapes)
529 diag::note_lifetime_safety_escapes_to_field_here)
534 const VarDecl *EscapeGlobal)
override {
536 diag::warn_lifetime_safety_noescape_escapes)
540 diag::note_lifetime_safety_escapes_to_static_storage_here)
544 diag::note_lifetime_safety_escapes_to_global_here)
549 S.addLifetimeBoundToImplicitThis(
const_cast<CXXMethodDecl *
>(MD));
553 struct LifetimeBoundMacroCache {
554 bool IsBuilt =
false;
558 void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &
Cache,
565 for (
const auto &M : PP.
macros()) {
574 const MacroInfo *MI = Def.getMacroInfo();
576 std::equal(Tokens.begin(), Tokens.end(), MI->
tokens_begin())) {
577 Cache.Candidates.push_back(II);
582 Cache.IsBuilt =
true;
585 StringRef getLastCachedMacroWithSpelling(SourceLocation Loc,
586 llvm::ArrayRef<TokenValue> Tokens,
587 LifetimeBoundMacroCache &
Cache) {
591 buildLifetimeBoundMacroCache(
Cache, Tokens);
593 const Preprocessor &PP = S.getPreprocessor();
595 SourceLocation BestLocation;
596 StringRef BestSpelling;
597 for (
const IdentifierInfo *II :
Cache.Candidates) {
598 const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
600 if (!Def || !Def.getMacroInfo())
604 const MacroInfo *MI = Def.getMacroInfo();
605 if (!MI->isObjectLike() || Tokens.size() != MI->getNumTokens() ||
606 !std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()))
610 SourceLocation Location = Def.getLocation();
611 assert(Location.isInvalid() ||
612 SM.isBeforeInTranslationUnit(Location, Loc));
613 if (BestLocation.isInvalid() ||
614 (Location.isValid() &&
615 SM.isBeforeInTranslationUnit(BestLocation, Location))) {
616 BestLocation = Location;
617 BestSpelling = II->getName();
623 void reportInvalidationSite(
const Expr *InvalidationExpr,
624 StringRef InvalidatedSubject) {
626 ? diag::note_lifetime_safety_freed_here
627 : diag::note_lifetime_safety_invalidated_here;
628 S.Diag(InvalidationExpr->getExprLoc(),
Diag)
629 << InvalidatedSubject << InvalidationExpr->getSourceRange();
632 void reportUseAfterInvalidationImpl(SourceLocation IssueLoc,
633 SourceRange IssueRange,
634 StringRef InvalidatedSubject,
635 const Expr *InvalidationExpr,
636 llvm::ArrayRef<const Expr *> ExprChain,
637 SourceLocation UseLoc,
638 SourceRange UseRange) {
640 ? diag::warn_lifetime_safety_use_after_free
641 : diag::warn_lifetime_safety_invalidation;
642 S.Diag(IssueLoc, WarnDiag) << InvalidatedSubject << IssueRange;
643 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
644 reportAliasingChain(ExprChain);
645 S.Diag(UseLoc, diag::note_lifetime_safety_used_here) << UseRange;
648 std::string getLifetimeBoundFixItText(SourceLocation Loc,
bool LeadingSpace,
649 bool AllowGNUAttrMacro =
true) {
650 const bool UseCXX11AttrSpelling =
651 S.getLangOpts().CPlusPlus || S.getLangOpts().C23;
652 const StringRef Fallback = UseCXX11AttrSpelling
653 ?
"[[clang::lifetimebound]]"
654 :
"__attribute__((lifetimebound))";
655 StringRef Spelling = S.getLangOpts().LifetimeSafetyLifetimeBoundMacro;
656 if (Spelling.empty() && Loc.isValid()) {
657 const Preprocessor &PP = S.getPreprocessor();
658 if (UseCXX11AttrSpelling)
659 Spelling = getLastCachedMacroWithSpelling(
661 {tok::l_square, tok::l_square, PP.getIdentifierInfo(
"clang"),
662 tok::coloncolon, PP.getIdentifierInfo(
"lifetimebound"),
663 tok::r_square, tok::r_square},
664 ClangLifetimeBoundMacroCache);
666 if (Spelling.empty() && AllowGNUAttrMacro)
667 Spelling = getLastCachedMacroWithSpelling(
669 {tok::kw___attribute, tok::l_paren, tok::l_paren,
670 PP.getIdentifierInfo(
"lifetimebound"), tok::r_paren, tok::r_paren},
671 GNULifetimeBoundMacroCache);
673 const std::string
Text = Spelling.empty() ? Fallback.str() : Spelling.str();
674 return LeadingSpace ?
" " +
Text :
Text +
" ";
677 std::pair<SourceLocation, std::string>
678 getLifetimeBoundFixIt(
const ParmVarDecl *Decl) {
680 Decl->getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
681 bool LeadingSpace =
true;
683 if (!
Decl->getIdentifier()) {
686 InsertionPoint =
Decl->getBeginLoc();
687 LeadingSpace =
false;
688 }
else if (
Decl->hasDefaultArg()) {
692 Decl->getLocation(), 0, S.getSourceManager(), S.getLangOpts());
694 return {InsertionPoint,
695 getLifetimeBoundFixItText(InsertionPoint, LeadingSpace)};
698 std::pair<SourceLocation, std::string>
699 getLifetimeBoundFixIt(
const CXXMethodDecl *MD) {
700 const auto MDL = MD->getTypeSourceInfo()->getTypeLoc();
702 MDL.getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
704 if (
const auto *FPT = MD->getType()->getAs<FunctionProtoType>();
705 FPT && FPT->hasTrailingReturn()) {
710 const auto FTL = MDL.getAs<FunctionTypeLoc>();
717 0, S.getSourceManager(), S.getLangOpts());
719 return {InsertionPoint,
720 getLifetimeBoundFixItText(InsertionPoint,
true,
724 std::string getDiagSubjectDescription(
const ValueDecl *VD) {
726 llvm::raw_string_ostream
OS(Res);
731 }
else if (
const auto *Var = dyn_cast<VarDecl>(VD)) {
732 if (Var->isStaticLocal() || Var->isStaticDataMember())
733 OS <<
"static variable";
734 else if (Var->hasGlobalStorage())
735 OS <<
"global variable";
737 OS <<
"local variable";
742 VD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
false);
747 std::string getDiagSubjectDescription(
const Expr *E) {
748 E = E->IgnoreImpCasts();
750 return "temporary object";
752 return "allocated object";
753 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
754 return getDiagSubjectDescription(DRE->getDecl());
756 if (
const auto *CE = dyn_cast<CallExpr>(E)) {
757 const auto *FD = CE->getDirectCallee();
759 return "result of call";
761 llvm::raw_string_ostream
OS(Name);
762 FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
764 return "result of call to '" + Name +
"'";
771 bool shouldShowInAliasChain(
const Expr *CurrExpr,
const Expr *LastExpr) {
772 CurrExpr = CurrExpr->IgnoreImpCasts();
773 LastExpr = LastExpr->IgnoreImpCasts();
780 return CurrExpr->getSourceRange() != LastExpr->getSourceRange();
783 void reportAliasingChain(llvm::ArrayRef<const Expr *> OriginExprChain) {
784 if (OriginExprChain.empty())
787 const Expr *LastExpr = OriginExprChain.back();
788 const Expr *VisibleLastExpr = LastExpr;
789 std::string IssueStr = getDiagSubjectDescription(VisibleLastExpr);
791 for (
const Expr *CurrExpr : reverse(OriginExprChain.drop_back())) {
792 if (!shouldShowInAliasChain(CurrExpr, VisibleLastExpr)) {
796 std::optional<LifetimeBoundParamInfo> ParamInfo =
801 bool IsInferred =
true;
802 std::string ParamName;
803 if (!IsImplicitObject) {
805 if (
const auto *Attr = Param->getAttr<LifetimeBoundAttr>())
806 IsInferred = Attr->isImplicit();
807 ParamName = Param->getIdentifier()
808 ?
"'" + Param->getNameAsString() +
"'"
812 IsInferred = Attr->isImplicit();
814 S.Diag(CurrExpr->getBeginLoc(),
815 diag::note_lifetime_safety_aliases_storage_lifetimebound)
816 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
817 << IssueStr << IsImplicitObject << ParamName << IsInferred;
819 S.Diag(CurrExpr->getBeginLoc(),
820 diag::note_lifetime_safety_aliases_storage)
821 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
823 VisibleLastExpr = CurrExpr;
827 LifetimeBoundMacroCache ClangLifetimeBoundMacroCache;
828 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.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
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.
A trivial tuple used to represent a source range.
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
bool isPointerType() const
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 reportUseAfterInvalidation(const ParmVarDecl *PVD, SourceLocation UseLoc, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain) override
void reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *DanglingGlobal, const Expr *InvalidationExpr) override
void reportUseAfterScope(const Expr *IssueExpr, SourceLocation UseLoc, const Expr *MovedExpr, SourceLocation FreeLoc, llvm::ArrayRef< const Expr * > ExprChain) override
void reportFieldOriginEscape(const CXXMethodDecl *MD, const FieldDecl *FD, const Expr *EscapeExpr) 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 reportUseAfterInvalidation(const Expr *IssueExpr, SourceLocation UseLoc, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain) 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)
bool ShouldCheckFieldOriginEscape(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 CheckFieldOriginEscape
bool CheckInapplicableLifetimebound
bool CheckLifetimeboundViolations