clang 24.0.0git
Loans.h
Go to the documentation of this file.
1//===- Loans.h - Loan and Access Path Definitions --------------*- 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 Loan and AccessPath structures, which represent
10// borrows of storage locations, and the LoanManager, which manages the
11// creation and retrieval of loans during lifetime analysis.
12//
13//===----------------------------------------------------------------------===//
14#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LOANS_H
15#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LOANS_H
16
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/ExprCXX.h"
21#include "llvm/ADT/FoldingSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/Support/raw_ostream.h"
24
26
28inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, LoanID ID) {
29 return OS << ID.Value;
30}
31
32/// Represents one step in an access path: either a field access or an
33/// access to an unnamed interior region (denoted by '*').
34///
35/// Examples:
36/// - Field access: `obj.field` has PathElement 'field'
37/// - Interior access: `owner.*` has '*'
38/// - In `std::string s; std::string_view v = s;`, v has loan to s.*
39/// - Array element: `arr[i]` has PathElement '*' (same as interior access)
40class PathElement {
41public:
42 enum class Kind { Field, Interior };
43
44 static PathElement getField(const FieldDecl &FD) {
45 return PathElement(Kind::Field, &FD);
46 }
47 static PathElement getInterior() {
48 return PathElement(Kind::Interior, nullptr);
49 }
50
51 bool isField() const { return K == Kind::Field; }
52 bool isInterior() const { return K == Kind::Interior; }
53 const FieldDecl *getFieldDecl() const { return FD; }
54
55 bool operator==(const PathElement &Other) const {
56 return K == Other.K && FD == Other.FD;
57 }
58 bool operator!=(const PathElement &Other) const { return !(*this == Other); }
59
60 void dump(llvm::raw_ostream &OS) const {
61 if (isField())
62 OS << "." << FD->getNameAsString();
63 else
64 OS << ".*";
65 }
66
67private:
68 PathElement(Kind K, const FieldDecl *FD) : K(K), FD(FD) {}
69 Kind K;
70 const FieldDecl *FD;
71};
72
73/// Represents the base of a placeholder access path, which is either a
74/// function parameter or the implicit 'this' object of an instance method.
75/// Placeholder paths never expire within the function scope, as they represent
76/// storage from the caller's scope.
77class PlaceholderBase : public llvm::FoldingSetNode {
78 llvm::PointerUnion<const ParmVarDecl *, const CXXMethodDecl *> ParamOrMethod;
79
80public:
81 PlaceholderBase(const ParmVarDecl *PVD) : ParamOrMethod(PVD) {}
82 PlaceholderBase(const CXXMethodDecl *MD) : ParamOrMethod(MD) {}
83
84 const ParmVarDecl *getParmVarDecl() const {
85 return ParamOrMethod.dyn_cast<const ParmVarDecl *>();
86 }
87
89 return ParamOrMethod.dyn_cast<const CXXMethodDecl *>();
90 }
91
92 void Profile(llvm::FoldingSetNodeID &ID) const {
93 ID.AddPointer(ParamOrMethod.getOpaqueValue());
94 }
95};
96
97/// Represents the storage location being borrowed, e.g., a specific stack
98/// variable or a field within it: var.field.*
99///
100/// An AccessPath consists of:
101/// - A base: either a ValueDecl, MaterializeTemporaryExpr, or PlaceholderBase
102/// - A sequence of PathElements representing field accesses or interior
103/// regions
104///
105/// Examples:
106/// - `x` -> Base=x, Elements=[]
107/// - `x.field` -> Base=x, Elements=[.field]
108/// - `x.*` (e.g., string_view from string) -> Base=x, Elements=[.*]
109/// - `x.field.*` -> Base=x, Elements=[.field, .*]
110/// - `$param.field` -> Base=$param, Elements=[.field]
111///
112/// TODO: Model access paths of other types, e.g. heap and globals.
114 /// The base of the access path: a variable, temporary, or placeholder.
115 const llvm::PointerUnion<const clang::ValueDecl *,
117 const PlaceholderBase *, const clang::CXXNewExpr *>
118 Base;
119 /// The path elements representing field accesses and access to unnamed
120 /// interior regions.
122
123public:
124 AccessPath(const clang::ValueDecl *D) : Base(D) {}
126 AccessPath(const PlaceholderBase *PB) : Base(PB) {}
128
129 /// Creates an extended access path by appending a path element.
130 /// Example: AccessPath(x_path, field) creates path to `x.field`.
132 : Base(Other.Base), Elements(Other.Elements) {
133 Elements.push_back(E);
134 }
135
137 return Base.dyn_cast<const clang::ValueDecl *>();
138 }
139
141 return Base.dyn_cast<const clang::MaterializeTemporaryExpr *>();
142 }
143
145 return Base.dyn_cast<const PlaceholderBase *>();
146 }
147
149 return Base.dyn_cast<const clang::CXXNewExpr *>();
150 }
151
152 bool operator==(const AccessPath &RHS) const {
153 return Base == RHS.Base && Elements == RHS.Elements;
154 }
155 bool operator!=(const AccessPath &RHS) const { return !(*this == RHS); }
156
157 /// Returns true if this path is a prefix of Other (or same as Other).
158 /// Examples:
159 /// - `x` is a prefix of `x`, `x.field`, `x.field.*`
160 /// - `x.field` is a prefix of `x.field` and `x.field.nested`
161 /// - `x.field` is NOT a prefix of `x.other_field`
162 bool isPrefixOf(const AccessPath &Other) const {
163 if (Base != Other.Base || Elements.size() > Other.Elements.size())
164 return false;
165 return std::equal(Elements.begin(), Elements.end(), Other.Elements.begin());
166 }
167
168 /// Returns true if this path is a strict prefix of Other.
169 /// Example:
170 /// - `x` is a strict prefix of `x.field` but NOT of `x`
171 bool isStrictPrefixOf(const AccessPath &Other) const {
172 return Elements.size() < Other.Elements.size() && isPrefixOf(Other);
173 }
174 llvm::ArrayRef<PathElement> getElements() const { return Elements; }
175
176 void dump(llvm::raw_ostream &OS) const;
177};
178
179/// Represents a component of an access path: either a named field access or an
180/// abstract unnamed interior region (denoted by '*').
181///
182/// The interior access (`*`) represents the borrowable content of an object
183/// without exposing its internal implementation details. It may abstract over
184/// multiple underlying fields or memory regions.
185///
186/// Examples:
187/// - `int* p = &x;` creates a loan to `x`
188/// - `std::string_view v = s;` creates a loan to `s.*` (interior)
189/// - `int* p = &obj.field;` creates a loan to `obj.field`
190/// - Parameter loans have no IssueExpr (created at function entry)
191class Loan {
192 const LoanID ID;
193 const AccessPath Path;
194 /// The expression that creates the loan, e.g., &x. Optional for placeholder
195 /// loans.
196 const Expr *IssueExpr;
197
198public:
199 Loan(LoanID ID, AccessPath Path, const Expr *IssueExpr = nullptr)
200 : ID(ID), Path(Path), IssueExpr(IssueExpr) {}
201
202 LoanID getID() const { return ID; }
203 const AccessPath &getAccessPath() const { return Path; }
204 const Expr *getIssueExpr() const { return IssueExpr; }
205
206 void dump(llvm::raw_ostream &OS) const;
207};
208
209/// Manages the creation, storage and retrieval of loans.
211
212public:
213 LoanManager() = default;
214
215 Loan *createLoan(AccessPath Path, const Expr *IssueExpr = nullptr) {
216 void *Mem = LoanAllocator.Allocate<Loan>();
217 auto *NewLoan = new (Mem) Loan(getNextLoanID(), Path, IssueExpr);
218 AllLoans.push_back(NewLoan);
219 return NewLoan;
220 }
221
223 return createLoan(AccessPath(getOrCreatePlaceholderBase(PVD)));
224 }
226 return createLoan(AccessPath(getOrCreatePlaceholderBase(MD)));
227 }
228
229 const Loan *getLoan(LoanID ID) const {
230 assert(ID.Value < AllLoans.size());
231 return AllLoans[ID.Value];
232 }
233
234 llvm::ArrayRef<const Loan *> getLoans() const { return AllLoans; }
235
236private:
237 LoanID getNextLoanID() { return NextLoanID++; }
238
239 /// Gets or creates a placeholder base for a given parameter or method.
240 const PlaceholderBase *getOrCreatePlaceholderBase(const ParmVarDecl *PVD);
241 const PlaceholderBase *getOrCreatePlaceholderBase(const CXXMethodDecl *MD);
242
243 LoanID NextLoanID{0};
244
245 llvm::FoldingSet<PlaceholderBase> PlaceholderBases;
246
247 /// TODO(opt): Profile and evaluate the usefullness of small buffer
248 /// optimisation.
250 llvm::BumpPtrAllocator LoanAllocator;
251};
252} // namespace clang::lifetimes::internal
253
254#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LOANS_H
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2358
This represents one expression.
Definition Expr.h:112
Represents a member of a struct/union/class.
Definition Decl.h:3204
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4919
Represents a parameter to a function.
Definition Decl.h:1819
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
Represents the storage location being borrowed, e.g., a specific stack variable or a field within it:...
Definition Loans.h:113
bool isStrictPrefixOf(const AccessPath &Other) const
Returns true if this path is a strict prefix of Other.
Definition Loans.h:171
const clang::CXXNewExpr * getAsNewAllocation() const
Definition Loans.h:148
bool isPrefixOf(const AccessPath &Other) const
Returns true if this path is a prefix of Other (or same as Other).
Definition Loans.h:162
bool operator!=(const AccessPath &RHS) const
Definition Loans.h:155
AccessPath(const clang::ValueDecl *D)
Definition Loans.h:124
const clang::ValueDecl * getAsValueDecl() const
Definition Loans.h:136
bool operator==(const AccessPath &RHS) const
Definition Loans.h:152
AccessPath(const clang::MaterializeTemporaryExpr *MTE)
Definition Loans.h:125
const clang::MaterializeTemporaryExpr * getAsMaterializeTemporaryExpr() const
Definition Loans.h:140
llvm::ArrayRef< PathElement > getElements() const
Definition Loans.h:174
const PlaceholderBase * getAsPlaceholderBase() const
Definition Loans.h:144
void dump(llvm::raw_ostream &OS) const
Definition Loans.cpp:13
AccessPath(const PlaceholderBase *PB)
Definition Loans.h:126
AccessPath(const AccessPath &Other, PathElement E)
Creates an extended access path by appending a path element.
Definition Loans.h:131
AccessPath(const clang::CXXNewExpr *New)
Definition Loans.h:127
Loan * createPlaceholderLoan(const ParmVarDecl *PVD)
Definition Loans.h:222
llvm::ArrayRef< const Loan * > getLoans() const
Definition Loans.h:234
const Loan * getLoan(LoanID ID) const
Definition Loans.h:229
Loan * createLoan(AccessPath Path, const Expr *IssueExpr=nullptr)
Definition Loans.h:215
Loan * createPlaceholderLoan(const CXXMethodDecl *MD)
Definition Loans.h:225
Represents a component of an access path: either a named field access or an abstract unnamed interior...
Definition Loans.h:191
const Expr * getIssueExpr() const
Definition Loans.h:204
Loan(LoanID ID, AccessPath Path, const Expr *IssueExpr=nullptr)
Definition Loans.h:199
const AccessPath & getAccessPath() const
Definition Loans.h:203
void dump(llvm::raw_ostream &OS) const
Definition Loans.cpp:32
Represents one step in an access path: either a field access or an access to an unnamed interior regi...
Definition Loans.h:40
static PathElement getInterior()
Definition Loans.h:47
const FieldDecl * getFieldDecl() const
Definition Loans.h:53
void dump(llvm::raw_ostream &OS) const
Definition Loans.h:60
bool operator==(const PathElement &Other) const
Definition Loans.h:55
bool operator!=(const PathElement &Other) const
Definition Loans.h:58
static PathElement getField(const FieldDecl &FD)
Definition Loans.h:44
Represents the base of a placeholder access path, which is either a function parameter or the implici...
Definition Loans.h:77
PlaceholderBase(const ParmVarDecl *PVD)
Definition Loans.h:81
PlaceholderBase(const CXXMethodDecl *MD)
Definition Loans.h:82
const ParmVarDecl * getParmVarDecl() const
Definition Loans.h:84
const CXXMethodDecl * getImplicitThisParent() const
Definition Loans.h:88
void Profile(llvm::FoldingSetNodeID &ID) const
Definition Loans.h:92
utils::ID< struct LoanTag > LoanID
Definition Loans.h:27
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, LoanID ID)
Definition Loans.h:28
@ Other
Other implicit parameter.
Definition Decl.h:1774
A generic, type-safe wrapper for an ID, distinguished by its Tag type.
Definition Utils.h:21