clang 24.0.0git
LifetimeSafety.h
Go to the documentation of this file.
1//===- LifetimeSafety.h - C++ Lifetime Safety Analysis -*----------- C++-*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the main entry point and orchestrator for the C++ Lifetime
10// Safety Analysis. It coordinates the entire analysis pipeline: fact
11// generation, loan propagation, live origins analysis, and enforcement of
12// lifetime safety policy.
13//
14// The analysis is based on the concepts of "origins" and "loans" to track
15// pointer lifetimes and detect issues like use-after-free and dangling
16// pointers. See the RFC for more details:
17// https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291
18//
19//===----------------------------------------------------------------------===//
20#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
21#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
22
23#include "clang/AST/Decl.h"
31#include "llvm/ADT/PointerUnion.h"
32#include <cstddef>
33#include <memory>
34
35namespace clang::lifetimes {
36
38 /// Maximum number of CFG blocks to analyze. Functions with larger CFGs will
39 /// be skipped.
40 size_t MaxCFGBlocks = 0;
41
42 /// Whether to suggest lifetime annotations.
43 bool SuggestAnnotations = false;
44
50};
51
52/// Enum to track functions visible across or within TU.
53enum class WarningScope {
54 CrossTU, // For warnings on declarations visible across Translation Units.
55 IntraTU // For warnings on functions local to a Translation Unit.
56};
57
58/// Abstract interface for operations requiring Sema access.
59///
60/// This class exists to break a circular dependency: the LifetimeSafety
61/// analysis target cannot directly depend on clangSema (which would create the
62/// cycle: clangSema -> clangAnalysis -> clangAnalysisLifetimeSafety ->
63/// clangSema).
64///
65/// Instead, this interface is implemented in AnalysisBasedWarnings.cpp (part of
66/// clangSema), allowing the analysis to report diagnostics and modify the AST
67/// through Sema without introducing a circular dependency.
69public:
71 virtual ~LifetimeSafetySemaHelper() = default;
72
73 virtual void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
74 const Expr *MovedExpr,
75 SourceLocation FreeLoc,
77
78 // Overload for a use with only a location and no expression (e.g. a borrow
79 // captured into the object and still held at the capturing method's exit).
80 virtual void reportUseAfterScope(const Expr *IssueExpr, SourceLocation UseLoc,
81 const Expr *MovedExpr,
82 SourceLocation FreeLoc,
84
85 // TODO: Report where the object was destroyed when that happens before the
86 // return (inner scopes, temporaries).
87 virtual void reportUseAfterReturn(const Expr *IssueExpr,
88 const Expr *ReturnExpr,
89 const Expr *MovedExpr,
91
92 virtual void reportDanglingField(const Expr *IssueExpr,
93 const FieldDecl *Field,
94 const Expr *MovedExpr,
95 bool IsCapturedByLambda,
96 SourceLocation ExpiryLoc) {}
97
98 virtual void reportDanglingGlobal(const Expr *IssueExpr,
99 const VarDecl *DanglingGlobal,
100 const Expr *MovedExpr,
101 SourceLocation ExpiryLoc,
102 bool IsMain = false) {}
103
104 // Reports when a reference/iterator is used after the container operation
105 // that invalidated it.
106 virtual void
107 reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr,
108 const Expr *InvalidationExpr,
109 llvm::ArrayRef<const Expr *> ExprChain) {}
110 virtual void
111 reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr,
112 const Expr *InvalidationExpr,
113 llvm::ArrayRef<const Expr *> ExprChain) {}
114 virtual void
116 const Expr *InvalidationExpr,
117 llvm::ArrayRef<const Expr *> ExprChain) {}
118 virtual void
120 const Expr *InvalidationExpr,
121 llvm::ArrayRef<const Expr *> ExprChain) {}
122 virtual void reportInvalidatedField(const Expr *IssueExpr,
123 const FieldDecl *Field,
124 const Expr *InvalidationExpr) {}
125 virtual void reportInvalidatedField(const ParmVarDecl *PVD,
126 const FieldDecl *Field,
127 const Expr *InvalidationExpr) {}
128 virtual void reportInvalidatedGlobal(const Expr *IssueExpr,
129 const VarDecl *Global,
130 const Expr *InvalidationExpr) {}
131 virtual void reportInvalidatedGlobal(const ParmVarDecl *PVD,
132 const VarDecl *Global,
133 const Expr *InvalidationExpr) {}
134
136 llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>;
137
138 // Suggests lifetime bound annotations for function parameters.
140 const ParmVarDecl *ParmToAnnotate,
142
143 // Reports misuse of [[clang::noescape]] when parameter escapes through return
144 virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
145 const Expr *EscapeExpr) {}
146 // Reports misuse of [[clang::noescape]] when parameter escapes through field
147 virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
148 const FieldDecl *EscapeField) {}
149 // Reports misuse of [[clang::noescape]] when parameter escapes through
150 // assignment to a global variable
151 virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
152 const VarDecl *EscapeGlobal) {}
153
154 // Reports misuse of [[clang::lifetimebound]] when parameter doesn't escape
155 // through return.
156 virtual void
157 reportLifetimeboundViolation(const ParmVarDecl *ParmWithLifetimebound) {}
158
159 // Reports misuse of [[clang::lifetimebound]] when implicit this parameter
160 // doesn't escape through return.
161 virtual void
162 reportLifetimeboundViolation(const CXXMethodDecl *MDWithLifetimebound) {}
163
164 // Reports a member function definition that has [[clang::lifetimebound]] on
165 // the implicit this parameter when the canonical declaration does not.
167 const CXXMethodDecl *FDef,
168 const CXXMethodDecl *FDecl) {}
169
170 // Reports a function definition parameter that has [[clang::lifetimebound]]
171 // when the corresponding parameter in the canonical declaration.
173 const ParmVarDecl *PVDDef,
174 const ParmVarDecl *PVDDecl) {}
175
177
178 // Suggests lifetime bound annotations for implicit this.
180 const CXXMethodDecl *MD,
181 const Expr *EscapeExpr) {}
182
183 // Reports when a member function returns an origin of a field.
185 const FieldDecl *FD,
186 const Expr *EscapeExpr) {}
187
188 // Adds inferred lifetime bound attribute for implicit this to its
189 // TypeSourceInfo.
191};
192
193/// The main entry point for the analysis.
195 LifetimeSafetySemaHelper *SemaHelper,
196 const LifetimeSafetyOpts &Opts,
197 LifetimeSafetyStats &Stats, bool CollectStats);
198
199namespace internal {
200
201void collectLifetimeStats(AnalysisDeclContext &AC, OriginManager &OM,
202 LifetimeSafetyStats &Stats);
203
204/// An object to hold the factories for immutable collections, ensuring
205/// that all created states share the same underlying memory management.
207 OriginLoanMap::Factory OriginMapFactory;
208 LoanSet::Factory LoanSetFactory;
209 MovedLoansMap::Factory MovedLoansMapFactory;
210 LivenessMap::Factory LivenessMapFactory;
211};
212
213/// Running the lifetime safety analysis and querying its results. It
214/// encapsulates the various dataflow analyses.
216public:
218 LifetimeSafetySemaHelper *SemaHelper,
219 const LifetimeSafetyOpts &LSOpts);
220
221 void run();
222
223 /// \note These are provided only for testing purposes.
225 return *LoanPropagation;
226 }
227 LiveOriginsAnalysis &getLiveOrigins() const { return *LiveOrigins; }
228 FactManager &getFactManager() { return *FactMgr; }
229
230private:
232 LifetimeSafetySemaHelper *SemaHelper;
233 const LifetimeSafetyOpts LSOpts;
234 LifetimeFactory Factory;
235 std::unique_ptr<FactManager> FactMgr;
236 std::unique_ptr<LiveOriginsAnalysis> LiveOrigins;
237 std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
238 std::unique_ptr<MovedLoansAnalysis> MovedLoans;
239};
240} // namespace internal
241} // namespace clang::lifetimes
242
243#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2150
This represents one expression.
Definition Expr.h:114
Represents a member of a struct/union/class.
Definition Decl.h:3311
Represents a parameter to a function.
Definition Decl.h:1832
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
Encodes a location in the source.
Represents a variable declaration or definition.
Definition Decl.h:934
Abstract interface for operations requiring Sema access.
virtual void reportInapplicableLifetimebound(const ParmVarDecl *PVD)
virtual void reportUseAfterInvalidation(const Expr *IssueExpr, SourceLocation UseLoc, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain)
virtual void reportDanglingGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal, const Expr *MovedExpr, SourceLocation ExpiryLoc, bool IsMain=false)
virtual void reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain)
llvm::PointerUnion< const Expr *, const FieldDecl *, const VarDecl * > EscapingTarget
virtual void reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain)
virtual void suggestLifetimeboundToParmVar(WarningScope Scope, const ParmVarDecl *ParmToAnnotate, EscapingTarget Target)
virtual void reportUseAfterInvalidation(const ParmVarDecl *PVD, SourceLocation UseLoc, const Expr *InvalidationExpr, llvm::ArrayRef< const Expr * > ExprChain)
virtual void reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *Field, const Expr *InvalidationExpr)
virtual void reportMisplacedLifetimebound(WarningScope Scope, const ParmVarDecl *PVDDef, const ParmVarDecl *PVDDecl)
virtual void reportDanglingField(const Expr *IssueExpr, const FieldDecl *Field, const Expr *MovedExpr, bool IsCapturedByLambda, SourceLocation ExpiryLoc)
virtual void reportFieldOriginEscape(const CXXMethodDecl *MD, const FieldDecl *FD, const Expr *EscapeExpr)
virtual void reportUseAfterScope(const Expr *IssueExpr, SourceLocation UseLoc, const Expr *MovedExpr, SourceLocation FreeLoc, llvm::ArrayRef< const Expr * > ExprChain)
virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, const VarDecl *EscapeGlobal)
virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, const FieldDecl *EscapeField)
virtual void reportLifetimeboundViolation(const ParmVarDecl *ParmWithLifetimebound)
virtual void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr, const Expr *MovedExpr, SourceLocation FreeLoc, llvm::ArrayRef< const Expr * > ExprChain)
virtual void addLifetimeBoundToImplicitThis(const CXXMethodDecl *MD)
virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, const Expr *EscapeExpr)
virtual void reportMisplacedLifetimebound(WarningScope Scope, const CXXMethodDecl *FDef, const CXXMethodDecl *FDecl)
virtual void suggestLifetimeboundToImplicitThis(WarningScope Scope, const CXXMethodDecl *MD, const Expr *EscapeExpr)
virtual void reportLifetimeboundViolation(const CXXMethodDecl *MDWithLifetimebound)
virtual void reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *Global, const Expr *InvalidationExpr)
virtual void reportInvalidatedGlobal(const Expr *IssueExpr, const VarDecl *Global, const Expr *InvalidationExpr)
virtual void reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *Field, const Expr *InvalidationExpr)
virtual void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr, const Expr *MovedExpr, llvm::ArrayRef< const Expr * > ExprChain)
LifetimeSafetyAnalysis(AnalysisDeclContext &AC, LifetimeSafetySemaHelper *SemaHelper, const LifetimeSafetyOpts &LSOpts)
LoanPropagationAnalysis & getLoanPropagation() const
void collectLifetimeStats(AnalysisDeclContext &AC, OriginManager &OM, LifetimeSafetyStats &Stats)
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC, LifetimeSafetySemaHelper *SemaHelper, const LifetimeSafetyOpts &Opts, LifetimeSafetyStats &Stats, bool CollectStats)
The main entry point for the analysis.
WarningScope
Enum to track functions visible across or within TU.
bool SuggestAnnotations
Whether to suggest lifetime annotations.
size_t MaxCFGBlocks
Maximum number of CFG blocks to analyze.
An object to hold the factories for immutable collections, ensuring that all created states share the...