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_noescape_escapes,
42 diag::warn_lifetime_safety_lifetimebound_violation,
44 for (
unsigned DiagID : DiagIDs)
56 const Expr *MovedExpr,
59 MovedExpr ? diag::warn_lifetime_safety_use_after_scope_moved
60 : diag::warn_lifetime_safety_use_after_scope)
63 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
65 S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here);
66 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
71 const Expr *MovedExpr,
74 MovedExpr ? diag::warn_lifetime_safety_return_stack_addr_moved
75 : diag::warn_lifetime_safety_return_stack_addr)
78 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
80 S.Diag(ReturnExpr->
getExprLoc(), diag::note_lifetime_safety_returned_here)
86 const Expr *MovedExpr,
89 MovedExpr ? diag::warn_lifetime_safety_dangling_field_moved
90 : diag::warn_lifetime_safety_dangling_field)
93 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
96 diag::note_lifetime_safety_dangling_field_here)
102 const Expr *MovedExpr,
105 MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved
106 : diag::warn_lifetime_safety_dangling_global)
109 S.Diag(MovedExpr->
getExprLoc(), diag::note_lifetime_safety_moved_here)
113 diag::note_lifetime_safety_dangling_static_here)
117 diag::note_lifetime_safety_dangling_global_here)
122 const Expr *InvalidationExpr)
override {
124 ? diag::warn_lifetime_safety_use_after_free
125 : diag::warn_lifetime_safety_invalidation;
127 ? diag::note_lifetime_safety_freed_here
128 : diag::note_lifetime_safety_invalidated_here;
131 S.Diag(InvalidationExpr->
getExprLoc(), UseDiag)
133 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
137 const Expr *InvalidationExpr)
override {
140 ? diag::warn_lifetime_safety_use_after_free
141 : diag::warn_lifetime_safety_invalidation;
143 ? diag::note_lifetime_safety_freed_here
144 : diag::note_lifetime_safety_invalidated_here;
148 S.Diag(InvalidationExpr->
getExprLoc(), UseDiag)
150 S.Diag(UseExpr->
getExprLoc(), diag::note_lifetime_safety_used_here)
156 const Expr *InvalidationExpr)
override {
158 ? diag::note_lifetime_safety_freed_here
159 : diag::note_lifetime_safety_invalidated_here;
161 diag::warn_lifetime_safety_invalidated_field)
163 S.Diag(InvalidationExpr->
getExprLoc(), InvalidationDiag)
166 diag::note_lifetime_safety_dangling_field_here)
172 const Expr *InvalidationExpr)
override {
174 ? diag::note_lifetime_safety_freed_here
175 : diag::note_lifetime_safety_invalidated_here;
177 diag::warn_lifetime_safety_invalidated_field)
179 S.Diag(InvalidationExpr->
getExprLoc(), InvalidationDiag)
182 diag::note_lifetime_safety_dangling_field_here)
188 const Expr *InvalidationExpr)
override {
190 ? diag::note_lifetime_safety_freed_here
191 : diag::note_lifetime_safety_invalidated_here;
193 diag::warn_lifetime_safety_invalidated_global)
195 S.Diag(InvalidationExpr->
getExprLoc(), InvalidationDiag)
199 diag::note_lifetime_safety_dangling_static_here)
203 diag::note_lifetime_safety_dangling_global_here)
209 const Expr *InvalidationExpr)
override {
211 ? diag::note_lifetime_safety_freed_here
212 : diag::note_lifetime_safety_invalidated_here;
214 diag::warn_lifetime_safety_invalidated_global)
216 S.Diag(InvalidationExpr->
getExprLoc(), InvalidationDiag)
220 diag::note_lifetime_safety_dangling_static_here)
224 diag::note_lifetime_safety_dangling_global_here)
233 ? diag::warn_lifetime_safety_cross_tu_param_suggestion
234 : diag::warn_lifetime_safety_intra_tu_param_suggestion;
236 ParmToAnnotate->
getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
237 StringRef FixItText =
" [[clang::lifetimebound]]";
242 FixItText =
"[[clang::lifetimebound]] ";
248 if (
const auto *EscapeExpr =
Target.dyn_cast<
const Expr *>())
249 S.Diag(EscapeExpr->getBeginLoc(),
250 diag::note_lifetime_safety_suggestion_returned_here)
251 << EscapeExpr->getSourceRange();
252 else if (
const auto *EscapeField =
Target.dyn_cast<
const FieldDecl *>())
253 S.Diag(EscapeField->getLocation(),
254 diag::note_lifetime_safety_escapes_to_field_here)
255 << EscapeField->getSourceRange();
259 const ParmVarDecl *ParmWithLifetimebound)
override {
260 const auto *
Attr = ParmWithLifetimebound->
getAttr<LifetimeBoundAttr>();
261 StringRef ParamName = ParmWithLifetimebound->
getName();
262 bool HasName = ParamName.size() > 0;
264 diag::warn_lifetime_safety_lifetimebound_violation)
272 assert(
Attr &&
"Expected lifetimebound attribute");
274 diag::warn_lifetime_safety_lifetimebound_violation)
280 const Expr *EscapeExpr)
override {
282 ? diag::warn_lifetime_safety_cross_tu_this_suggestion
283 : diag::warn_lifetime_safety_intra_tu_this_suggestion;
286 MDL.getEndLoc(), 0, S.getSourceManager(), S.getLangOpts());
300 0, S.getSourceManager(), S.getLangOpts());
302 S.Diag(InsertionPoint, DiagID)
305 " [[clang::lifetimebound]]");
307 diag::note_lifetime_safety_suggestion_returned_here)
312 const Expr *EscapeExpr)
override {
314 diag::warn_lifetime_safety_noescape_escapes)
318 diag::note_lifetime_safety_suggestion_returned_here)
325 diag::warn_lifetime_safety_noescape_escapes)
329 diag::note_lifetime_safety_escapes_to_field_here)
334 const VarDecl *EscapeGlobal)
override {
336 diag::warn_lifetime_safety_noescape_escapes)
340 diag::note_lifetime_safety_escapes_to_static_storage_here)
344 diag::note_lifetime_safety_escapes_to_global_here)
349 S.addLifetimeBoundToImplicitThis(
const_cast<CXXMethodDecl *
>(MD));
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
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
TypeSourceInfo * getTypeSourceInfo() const
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
Represents a prototype with parameter type info, e.g.
bool hasTrailingReturn() const
Whether this function prototype has a trailing return type.
Wrapper for source info for functions.
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.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
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.
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.
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
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
const T * getAs() const
Member-template getAs<specific type>'.
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 reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, const Expr *EscapeExpr) override
void reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr, const Expr *InvalidationExpr) 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 reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *DanglingGlobal, const Expr *InvalidationExpr) override
LifetimeSafetySemaHelperImpl(Sema &S)
void suggestLifetimeboundToImplicitThis(SuggestionScope Scope, const CXXMethodDecl *MD, const Expr *EscapeExpr) override
void reportDanglingGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal, const Expr *MovedExpr, SourceLocation ExpiryLoc) override
void reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *DanglingField, const Expr *InvalidationExpr) override
void reportDanglingField(const Expr *IssueExpr, const FieldDecl *DanglingField, const Expr *MovedExpr, SourceLocation ExpiryLoc) override
void suggestLifetimeboundToParmVar(SuggestionScope Scope, const ParmVarDecl *ParmToAnnotate, EscapingTarget Target) override
void addLifetimeBoundToImplicitThis(const CXXMethodDecl *MD) override
void reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr, const Expr *InvalidationExpr) override
void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr, const Expr *MovedExpr, SourceLocation FreeLoc) 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
void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr, const Expr *MovedExpr, SourceLocation ExpiryLoc) override
llvm::PointerUnion< const Expr *, const FieldDecl *, const VarDecl * > EscapingTarget
LifetimeSafetySemaHelper()=default
SuggestionScope
Enum to track functions visible across or within TU.
const LifetimeBoundAttr * getImplicitObjectParamLifetimeBoundAttr(const FunctionDecl *FD)
bool IsLifetimeSafetyEnabled(Sema &S, const Decl *D)
bool isa(CodeGen::Address addr)
SourceRange getSourceRange() const LLVM_READONLY
getSourceRange - The range of the declaration name.