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)
override {
162 unsigned DiagID = MovedExpr
163 ? diag::warn_lifetime_safety_return_stack_addr_moved
164 : diag::warn_lifetime_safety_return_stack_addr;
167 << getDiagSubjectDescription(IssueExpr) << IssueExpr->
getSourceRange();
170 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
172 S.Diag(ReturnExpr->
getExprLoc(), diag::note_lifetime_safety_returned_here)
178 const Expr *MovedExpr,
bool IsCapturedByLambda,
182 ? diag::warn_lifetime_safety_dangling_field_lambda_capture
183 : (MovedExpr ? diag::warn_lifetime_safety_dangling_field_moved
184 : diag::warn_lifetime_safety_dangling_field);
187 << getDiagSubjectDescription(IssueExpr)
188 << getDiagSubjectDescription(DanglingField)
191 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
194 diag::note_lifetime_safety_dangling_field_here)
201 bool IsMain =
false)
override {
204 DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved
205 : diag::warn_lifetime_safety_dangling_global_in_main;
207 DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved
208 : diag::warn_lifetime_safety_dangling_global;
212 << getDiagSubjectDescription(IssueExpr)
213 << getDiagSubjectDescription(DanglingGlobal)
216 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
220 diag::note_lifetime_safety_dangling_static_here)
224 diag::note_lifetime_safety_dangling_global_here)
230 const Expr *InvalidationExpr,
233 ? diag::warn_lifetime_safety_use_after_free
234 : diag::warn_lifetime_safety_invalidation;
235 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
238 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
239 reportAliasingChain(ExprChain);
240 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
245 const Expr *InvalidationExpr,
249 ? diag::warn_lifetime_safety_use_after_free
250 : diag::warn_lifetime_safety_invalidation;
251 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
255 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
256 reportAliasingChain(ExprChain);
257 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
263 const Expr *InvalidationExpr)
override {
264 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
266 diag::warn_lifetime_safety_invalidated_field)
267 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
269 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
271 diag::note_lifetime_safety_dangling_field_here)
277 const Expr *InvalidationExpr)
override {
278 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
280 diag::warn_lifetime_safety_invalidated_field)
281 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
283 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
285 diag::note_lifetime_safety_dangling_field_here)
291 const Expr *InvalidationExpr)
override {
292 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
294 diag::warn_lifetime_safety_invalidated_global)
295 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
297 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
300 diag::note_lifetime_safety_dangling_static_here)
304 diag::note_lifetime_safety_dangling_global_here)
310 const Expr *InvalidationExpr)
override {
311 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
313 diag::warn_lifetime_safety_invalidated_global)
314 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
316 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
319 diag::note_lifetime_safety_dangling_static_here)
323 diag::note_lifetime_safety_dangling_global_here)
333 ? diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion
334 : diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion;
337 ? diag::warn_lifetime_safety_cross_tu_param_suggestion
338 : diag::warn_lifetime_safety_intra_tu_param_suggestion;
340 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(ParmToAnnotate);
342 S.Diag(InsertionPoint, DiagID)
346 if (
const auto *EscapeExpr =
Target.dyn_cast<
const Expr *>())
347 S.Diag(EscapeExpr->getBeginLoc(),
348 diag::note_lifetime_safety_suggestion_returned_here)
349 << EscapeExpr->getSourceRange();
350 else if (
const auto *EscapeField =
Target.dyn_cast<
const FieldDecl *>())
351 S.Diag(EscapeField->getLocation(),
352 diag::note_lifetime_safety_escapes_to_field_here)
353 << EscapeField->getSourceRange();
357 const ParmVarDecl *ParmWithLifetimebound)
override {
358 const auto *
Attr = ParmWithLifetimebound->
getAttr<LifetimeBoundAttr>();
359 StringRef ParamName = ParmWithLifetimebound->
getName();
360 bool HasName = ParamName.size() > 0;
362 diag::warn_lifetime_safety_lifetimebound_violation)
370 assert(
Attr &&
"Expected lifetimebound attribute");
372 diag::warn_lifetime_safety_lifetimebound_violation)
380 assert(
Attr &&
"Expected lifetimebound attribute");
383 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
384 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
386 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(FDecl);
392 if (IsMacro || InsertionPoint.isInvalid())
395 S.Diag(InsertionPoint, DiagID)
398 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
406 const auto *
Attr = PVDDef->
getAttr<LifetimeBoundAttr>();
407 assert(
Attr &&
"Expected lifetimebound attribute");
410 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
411 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
413 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(PVDDecl);
419 if (IsMacro || InsertionPoint.isInvalid())
422 S.Diag(InsertionPoint, DiagID)
426 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
431 assert(PVD->
hasAttr<LifetimeBoundAttr>() &&
432 "Expected parameter to have lifetimebound attribute");
433 const auto *
Attr = PVD->
getAttr<LifetimeBoundAttr>();
435 diag::warn_lifetime_safety_inapplicable_lifetimebound)
441 const Expr *EscapeExpr)
override {
443 ? diag::warn_lifetime_safety_cross_tu_this_suggestion
444 : diag::warn_lifetime_safety_intra_tu_this_suggestion;
446 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(MD);
448 S.Diag(InsertionPoint, DiagID)
453 diag::note_lifetime_safety_suggestion_returned_here)
458 const Expr *EscapeExpr)
override {
460 diag::warn_lifetime_safety_noescape_escapes)
464 diag::note_lifetime_safety_suggestion_returned_here)
471 diag::warn_lifetime_safety_noescape_escapes)
475 diag::note_lifetime_safety_escapes_to_field_here)
480 const VarDecl *EscapeGlobal)
override {
482 diag::warn_lifetime_safety_noescape_escapes)
486 diag::note_lifetime_safety_escapes_to_static_storage_here)
490 diag::note_lifetime_safety_escapes_to_global_here)
495 S.addLifetimeBoundToImplicitThis(
const_cast<CXXMethodDecl *
>(MD));
499 struct LifetimeBoundMacroCache {
500 bool IsBuilt =
false;
504 void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &
Cache,
511 for (
const auto &M : PP.
macros()) {
520 const MacroInfo *MI = Def.getMacroInfo();
522 std::equal(Tokens.begin(), Tokens.end(), MI->
tokens_begin())) {
523 Cache.Candidates.push_back(II);
528 Cache.IsBuilt =
true;
531 StringRef getLastCachedMacroWithSpelling(SourceLocation Loc,
532 llvm::ArrayRef<TokenValue> Tokens,
533 LifetimeBoundMacroCache &
Cache) {
537 buildLifetimeBoundMacroCache(
Cache, Tokens);
539 const Preprocessor &PP = S.getPreprocessor();
541 SourceLocation BestLocation;
542 StringRef BestSpelling;
543 for (
const IdentifierInfo *II :
Cache.Candidates) {
544 const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
546 if (!Def || !Def.getMacroInfo())
550 const MacroInfo *MI = Def.getMacroInfo();
551 if (!MI->isObjectLike() || Tokens.size() != MI->getNumTokens() ||
552 !std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()))
556 SourceLocation Location = Def.getLocation();
557 assert(Location.isInvalid() ||
558 SM.isBeforeInTranslationUnit(Location, Loc));
559 if (BestLocation.isInvalid() ||
560 (Location.isValid() &&
561 SM.isBeforeInTranslationUnit(BestLocation, Location))) {
562 BestLocation = Location;
563 BestSpelling = II->getName();
569 void reportInvalidationSite(
const Expr *InvalidationExpr,
570 StringRef InvalidatedSubject) {
572 ? diag::note_lifetime_safety_freed_here
573 : diag::note_lifetime_safety_invalidated_here;
574 S.Diag(InvalidationExpr->getExprLoc(),
Diag)
575 << InvalidatedSubject << InvalidationExpr->getSourceRange();
578 std::string getLifetimeBoundFixItText(SourceLocation Loc,
bool LeadingSpace,
579 bool AllowGNUAttrMacro =
true) {
580 const bool UseCXX11AttrSpelling =
581 S.getLangOpts().CPlusPlus || S.getLangOpts().C23;
582 const StringRef Fallback = UseCXX11AttrSpelling
583 ?
"[[clang::lifetimebound]]"
584 :
"__attribute__((lifetimebound))";
585 StringRef Spelling = S.getLangOpts().LifetimeSafetyLifetimeBoundMacro;
586 if (Spelling.empty() && Loc.isValid()) {
587 const Preprocessor &PP = S.getPreprocessor();
588 if (UseCXX11AttrSpelling)
589 Spelling = getLastCachedMacroWithSpelling(
591 {tok::l_square, tok::l_square, PP.getIdentifierInfo(
"clang"),
592 tok::coloncolon, PP.getIdentifierInfo(
"lifetimebound"),
593 tok::r_square, tok::r_square},
594 ClangLifetimeBoundMacroCache);
596 if (Spelling.empty() && AllowGNUAttrMacro)
597 Spelling = getLastCachedMacroWithSpelling(
599 {tok::kw___attribute, tok::l_paren, tok::l_paren,
600 PP.getIdentifierInfo(
"lifetimebound"), tok::r_paren, tok::r_paren},
601 GNULifetimeBoundMacroCache);
603 const std::string
Text = Spelling.empty() ? Fallback.str() : Spelling.str();
604 return LeadingSpace ?
" " +
Text :
Text +
" ";
607 std::pair<SourceLocation, std::string>
608 getLifetimeBoundFixIt(
const ParmVarDecl *Decl) {
610 Decl->getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
611 bool LeadingSpace =
true;
613 if (!
Decl->getIdentifier()) {
616 InsertionPoint =
Decl->getBeginLoc();
617 LeadingSpace =
false;
618 }
else if (
Decl->hasDefaultArg()) {
622 Decl->getLocation(), 0, S.getSourceManager(), S.getLangOpts());
624 return {InsertionPoint,
625 getLifetimeBoundFixItText(InsertionPoint, LeadingSpace)};
628 std::pair<SourceLocation, std::string>
629 getLifetimeBoundFixIt(
const CXXMethodDecl *MD) {
630 const auto MDL = MD->getTypeSourceInfo()->getTypeLoc();
632 MDL.getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
634 if (
const auto *FPT = MD->getType()->getAs<FunctionProtoType>();
635 FPT && FPT->hasTrailingReturn()) {
640 const auto FTL = MDL.getAs<FunctionTypeLoc>();
647 0, S.getSourceManager(), S.getLangOpts());
649 return {InsertionPoint,
650 getLifetimeBoundFixItText(InsertionPoint,
true,
654 std::string getDiagSubjectDescription(
const ValueDecl *VD) {
656 llvm::raw_string_ostream
OS(Res);
661 }
else if (
const auto *Var = dyn_cast<VarDecl>(VD)) {
662 if (Var->isStaticLocal() || Var->isStaticDataMember())
663 OS <<
"static variable";
664 else if (Var->hasGlobalStorage())
665 OS <<
"global variable";
667 OS <<
"local variable";
672 VD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
false);
677 std::string getDiagSubjectDescription(
const Expr *E) {
678 E = E->IgnoreImpCasts();
680 return "temporary object";
682 return "allocated object";
683 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
684 return getDiagSubjectDescription(DRE->getDecl());
686 if (
const auto *CE = dyn_cast<CallExpr>(E)) {
687 const auto *FD = CE->getDirectCallee();
689 return "result of call";
691 llvm::raw_string_ostream
OS(Name);
692 FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
694 return "result of call to '" + Name +
"'";
701 bool shouldShowInAliasChain(
const Expr *CurrExpr,
const Expr *LastExpr) {
702 CurrExpr = CurrExpr->IgnoreImpCasts();
703 LastExpr = LastExpr->IgnoreImpCasts();
710 return CurrExpr->getSourceRange() != LastExpr->getSourceRange();
713 void reportAliasingChain(llvm::ArrayRef<const Expr *> OriginExprChain) {
714 if (OriginExprChain.empty())
717 const Expr *LastExpr = OriginExprChain.back();
718 const Expr *VisibleLastExpr = LastExpr;
719 std::string IssueStr = getDiagSubjectDescription(VisibleLastExpr);
721 for (
const Expr *CurrExpr : reverse(OriginExprChain.drop_back())) {
722 if (!shouldShowInAliasChain(CurrExpr, VisibleLastExpr)) {
726 std::optional<LifetimeBoundParamInfo> ParamInfo =
731 bool IsInferred =
true;
732 std::string ParamName;
733 if (!IsImplicitObject) {
735 if (
const auto *Attr = Param->getAttr<LifetimeBoundAttr>())
736 IsInferred = Attr->isImplicit();
737 ParamName = Param->getIdentifier()
738 ?
"'" + Param->getNameAsString() +
"'"
742 IsInferred = Attr->isImplicit();
744 S.Diag(CurrExpr->getBeginLoc(),
745 diag::note_lifetime_safety_aliases_storage_lifetimebound)
746 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
747 << IssueStr << IsImplicitObject << ParamName << IsInferred;
749 S.Diag(CurrExpr->getBeginLoc(),
750 diag::note_lifetime_safety_aliases_storage)
751 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
753 VisibleLastExpr = CurrExpr;
757 LifetimeBoundMacroCache ClangLifetimeBoundMacroCache;
758 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, 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