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,
150 unsigned DiagID = MovedExpr
151 ? diag::warn_lifetime_safety_dangling_field_moved
152 : diag::warn_lifetime_safety_dangling_field;
155 << getDiagSubjectDescription(IssueExpr)
156 << getDiagSubjectDescription(DanglingField)
159 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
162 diag::note_lifetime_safety_dangling_field_here)
168 const Expr *MovedExpr,
170 unsigned DiagID = MovedExpr
171 ? diag::warn_lifetime_safety_dangling_global_moved
172 : diag::warn_lifetime_safety_dangling_global;
175 << getDiagSubjectDescription(IssueExpr)
176 << getDiagSubjectDescription(DanglingGlobal)
179 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
183 diag::note_lifetime_safety_dangling_static_here)
187 diag::note_lifetime_safety_dangling_global_here)
193 const Expr *InvalidationExpr,
196 ? diag::warn_lifetime_safety_use_after_free
197 : diag::warn_lifetime_safety_invalidation;
198 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
201 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
202 reportAliasingChain(ExprChain);
203 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
208 const Expr *InvalidationExpr,
212 ? diag::warn_lifetime_safety_use_after_free
213 : diag::warn_lifetime_safety_invalidation;
214 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
218 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
219 reportAliasingChain(ExprChain);
220 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
226 const Expr *InvalidationExpr)
override {
227 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
229 diag::warn_lifetime_safety_invalidated_field)
230 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
232 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
234 diag::note_lifetime_safety_dangling_field_here)
240 const Expr *InvalidationExpr)
override {
241 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
243 diag::warn_lifetime_safety_invalidated_field)
244 << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
246 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
248 diag::note_lifetime_safety_dangling_field_here)
254 const Expr *InvalidationExpr)
override {
255 std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
257 diag::warn_lifetime_safety_invalidated_global)
258 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
260 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
263 diag::note_lifetime_safety_dangling_static_here)
267 diag::note_lifetime_safety_dangling_global_here)
273 const Expr *InvalidationExpr)
override {
274 std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
276 diag::warn_lifetime_safety_invalidated_global)
277 << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
279 reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
282 diag::note_lifetime_safety_dangling_static_here)
286 diag::note_lifetime_safety_dangling_global_here)
296 ? diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion
297 : diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion;
300 ? diag::warn_lifetime_safety_cross_tu_param_suggestion
301 : diag::warn_lifetime_safety_intra_tu_param_suggestion;
303 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(ParmToAnnotate);
305 S.Diag(InsertionPoint, DiagID)
309 if (
const auto *EscapeExpr =
Target.dyn_cast<
const Expr *>())
310 S.Diag(EscapeExpr->getBeginLoc(),
311 diag::note_lifetime_safety_suggestion_returned_here)
312 << EscapeExpr->getSourceRange();
313 else if (
const auto *EscapeField =
Target.dyn_cast<
const FieldDecl *>())
314 S.Diag(EscapeField->getLocation(),
315 diag::note_lifetime_safety_escapes_to_field_here)
316 << EscapeField->getSourceRange();
320 const ParmVarDecl *ParmWithLifetimebound)
override {
321 const auto *
Attr = ParmWithLifetimebound->
getAttr<LifetimeBoundAttr>();
322 StringRef ParamName = ParmWithLifetimebound->
getName();
323 bool HasName = ParamName.size() > 0;
325 diag::warn_lifetime_safety_lifetimebound_violation)
333 assert(
Attr &&
"Expected lifetimebound attribute");
335 diag::warn_lifetime_safety_lifetimebound_violation)
343 assert(
Attr &&
"Expected lifetimebound attribute");
346 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
347 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
349 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(FDecl);
355 if (IsMacro || InsertionPoint.isInvalid())
358 S.Diag(InsertionPoint, DiagID)
361 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
369 const auto *
Attr = PVDDef->
getAttr<LifetimeBoundAttr>();
370 assert(
Attr &&
"Expected lifetimebound attribute");
373 ? diag::warn_lifetime_safety_cross_tu_misplaced_lifetimebound
374 : diag::warn_lifetime_safety_intra_tu_misplaced_lifetimebound;
376 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(PVDDecl);
382 if (IsMacro || InsertionPoint.isInvalid())
385 S.Diag(InsertionPoint, DiagID)
389 S.Diag(
Attr->
getLocation(), diag::note_lifetime_safety_lifetimebound_here)
394 assert(PVD->
hasAttr<LifetimeBoundAttr>() &&
395 "Expected parameter to have lifetimebound attribute");
396 const auto *
Attr = PVD->
getAttr<LifetimeBoundAttr>();
398 diag::warn_lifetime_safety_inapplicable_lifetimebound)
404 const Expr *EscapeExpr)
override {
406 ? diag::warn_lifetime_safety_cross_tu_this_suggestion
407 : diag::warn_lifetime_safety_intra_tu_this_suggestion;
409 auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(MD);
411 S.Diag(InsertionPoint, DiagID)
416 diag::note_lifetime_safety_suggestion_returned_here)
421 const Expr *EscapeExpr)
override {
423 diag::warn_lifetime_safety_noescape_escapes)
427 diag::note_lifetime_safety_suggestion_returned_here)
434 diag::warn_lifetime_safety_noescape_escapes)
438 diag::note_lifetime_safety_escapes_to_field_here)
443 const VarDecl *EscapeGlobal)
override {
445 diag::warn_lifetime_safety_noescape_escapes)
449 diag::note_lifetime_safety_escapes_to_static_storage_here)
453 diag::note_lifetime_safety_escapes_to_global_here)
458 S.addLifetimeBoundToImplicitThis(
const_cast<CXXMethodDecl *
>(MD));
462 struct LifetimeBoundMacroCache {
463 bool IsBuilt =
false;
467 void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &
Cache,
474 for (
const auto &M : PP.
macros()) {
483 const MacroInfo *MI = Def.getMacroInfo();
485 std::equal(Tokens.begin(), Tokens.end(), MI->
tokens_begin())) {
486 Cache.Candidates.push_back(II);
491 Cache.IsBuilt =
true;
494 StringRef getLastCachedMacroWithSpelling(SourceLocation Loc,
495 llvm::ArrayRef<TokenValue> Tokens,
496 LifetimeBoundMacroCache &
Cache) {
500 buildLifetimeBoundMacroCache(
Cache, Tokens);
502 const Preprocessor &PP = S.getPreprocessor();
504 SourceLocation BestLocation;
505 StringRef BestSpelling;
506 for (
const IdentifierInfo *II :
Cache.Candidates) {
507 const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
509 if (!Def || !Def.getMacroInfo())
513 const MacroInfo *MI = Def.getMacroInfo();
514 if (!MI->isObjectLike() || Tokens.size() != MI->getNumTokens() ||
515 !std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()))
519 SourceLocation Location = Def.getLocation();
520 assert(Location.isInvalid() ||
521 SM.isBeforeInTranslationUnit(Location, Loc));
522 if (BestLocation.isInvalid() ||
523 (Location.isValid() &&
524 SM.isBeforeInTranslationUnit(BestLocation, Location))) {
525 BestLocation = Location;
526 BestSpelling = II->getName();
532 void reportInvalidationSite(
const Expr *InvalidationExpr,
533 StringRef InvalidatedSubject) {
535 ? diag::note_lifetime_safety_freed_here
536 : diag::note_lifetime_safety_invalidated_here;
537 S.Diag(InvalidationExpr->getExprLoc(),
Diag)
538 << InvalidatedSubject << InvalidationExpr->getSourceRange();
541 std::string getLifetimeBoundFixItText(SourceLocation Loc,
bool LeadingSpace,
542 bool AllowGNUAttrMacro =
true) {
543 const bool UseCXX11AttrSpelling =
544 S.getLangOpts().CPlusPlus || S.getLangOpts().C23;
545 const StringRef Fallback = UseCXX11AttrSpelling
546 ?
"[[clang::lifetimebound]]"
547 :
"__attribute__((lifetimebound))";
548 StringRef Spelling = S.getLangOpts().LifetimeSafetyLifetimeBoundMacro;
549 if (Spelling.empty() && Loc.isValid()) {
550 const Preprocessor &PP = S.getPreprocessor();
551 if (UseCXX11AttrSpelling)
552 Spelling = getLastCachedMacroWithSpelling(
554 {tok::l_square, tok::l_square, PP.getIdentifierInfo(
"clang"),
555 tok::coloncolon, PP.getIdentifierInfo(
"lifetimebound"),
556 tok::r_square, tok::r_square},
557 ClangLifetimeBoundMacroCache);
559 if (Spelling.empty() && AllowGNUAttrMacro)
560 Spelling = getLastCachedMacroWithSpelling(
562 {tok::kw___attribute, tok::l_paren, tok::l_paren,
563 PP.getIdentifierInfo(
"lifetimebound"), tok::r_paren, tok::r_paren},
564 GNULifetimeBoundMacroCache);
566 const std::string
Text = Spelling.empty() ? Fallback.str() : Spelling.str();
567 return LeadingSpace ?
" " +
Text :
Text +
" ";
570 std::pair<SourceLocation, std::string>
571 getLifetimeBoundFixIt(
const ParmVarDecl *Decl) {
573 Decl->getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
574 bool LeadingSpace =
true;
576 if (!
Decl->getIdentifier()) {
579 InsertionPoint =
Decl->getBeginLoc();
580 LeadingSpace =
false;
581 }
else if (
Decl->hasDefaultArg()) {
585 Decl->getLocation(), 0, S.getSourceManager(), S.getLangOpts());
587 return {InsertionPoint,
588 getLifetimeBoundFixItText(InsertionPoint, LeadingSpace)};
591 std::pair<SourceLocation, std::string>
592 getLifetimeBoundFixIt(
const CXXMethodDecl *MD) {
593 const auto MDL = MD->getTypeSourceInfo()->getTypeLoc();
595 MDL.getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
597 if (
const auto *FPT = MD->getType()->getAs<FunctionProtoType>();
598 FPT && FPT->hasTrailingReturn()) {
603 const auto FTL = MDL.getAs<FunctionTypeLoc>();
610 0, S.getSourceManager(), S.getLangOpts());
612 return {InsertionPoint,
613 getLifetimeBoundFixItText(InsertionPoint,
true,
617 std::string getDiagSubjectDescription(
const ValueDecl *VD) {
619 llvm::raw_string_ostream
OS(Res);
624 }
else if (
const auto *Var = dyn_cast<VarDecl>(VD)) {
625 if (Var->isStaticLocal() || Var->isStaticDataMember())
626 OS <<
"static variable";
627 else if (Var->hasGlobalStorage())
628 OS <<
"global variable";
630 OS <<
"local variable";
635 VD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
false);
640 std::string getDiagSubjectDescription(
const Expr *E) {
641 E = E->IgnoreImpCasts();
643 return "temporary object";
645 return "allocated object";
646 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
647 return getDiagSubjectDescription(DRE->getDecl());
649 if (
const auto *CE = dyn_cast<CallExpr>(E)) {
650 const auto *FD = CE->getDirectCallee();
652 return "result of call";
656 llvm::raw_string_ostream
OS(Name);
657 FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
659 return "result of call to '" + Name +
"'";
666 bool shouldShowInAliasChain(
const Expr *CurrExpr,
const Expr *LastExpr) {
667 CurrExpr = CurrExpr->IgnoreImpCasts();
668 LastExpr = LastExpr->IgnoreImpCasts();
675 return CurrExpr->getSourceRange() != LastExpr->getSourceRange();
678 void reportAliasingChain(llvm::ArrayRef<const Expr *> OriginExprChain) {
679 if (OriginExprChain.empty())
682 const Expr *LastExpr = OriginExprChain.back();
683 std::string IssueStr = getDiagSubjectDescription(LastExpr);
685 for (
const Expr *CurrExpr : reverse(OriginExprChain.drop_back())) {
686 if (!shouldShowInAliasChain(CurrExpr, LastExpr))
688 S.Diag(CurrExpr->getBeginLoc(),
689 diag::note_lifetime_safety_aliases_storage)
690 << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr)
696 LifetimeBoundMacroCache ClangLifetimeBoundMacroCache;
697 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 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 reportDanglingField(const Expr *IssueExpr, const FieldDecl *DanglingField, const Expr *MovedExpr, SourceLocation ExpiryLoc) 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.