blob: f0e7d07c5ea32141d98ac42cb65672552bbbaf51 [file] [log] [blame]
Luca Versari99fddff2022-05-25 10:22:32 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef DEVTOOLS_RUST_CC_INTEROP_LIFETIME_ANALYSIS_OBJECT_REPOSITORY_H_
6#define DEVTOOLS_RUST_CC_INTEROP_LIFETIME_ANALYSIS_OBJECT_REPOSITORY_H_
7
Dmitri Gribenkoa087d232023-07-10 08:03:46 -07008#include <cstddef>
Luca Versari99fddff2022-05-25 10:22:32 -07009#include <optional>
10#include <string>
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070011#include <utility>
Luca Versari99fddff2022-05-25 10:22:32 -070012
13#include "lifetime_analysis/object.h"
14#include "lifetime_analysis/object_set.h"
15#include "lifetime_analysis/points_to_map.h"
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070016#include "lifetime_annotations/function_lifetimes.h"
17#include "lifetime_annotations/lifetime.h"
Luca Versari99fddff2022-05-25 10:22:32 -070018#include "lifetime_annotations/type_lifetimes.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/Expr.h"
21#include "clang/AST/ExprCXX.h"
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070022#include "clang/AST/Type.h"
Luca Versari99fddff2022-05-25 10:22:32 -070023#include "llvm/ADT/DenseMap.h"
Martin Brænne4a1231d2022-07-01 01:45:44 -070024#include "llvm/Support/Allocator.h"
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070025#include "llvm/Support/Error.h"
Luca Versari99fddff2022-05-25 10:22:32 -070026
27namespace clang {
28namespace tidy {
29namespace lifetimes {
30
31// A record-type expression has 2 modes:
32// 1. If it's being assigned to a reference, then the contents of the expression
33// are a glvalue. This is because references require an object to point to.
34// 2. If it's being assigned to a record object, then the expression itself is
35// not creating an object, but initializing it. So the expression's type is
36// a pure value, and it acts _on_ the initializing object instead of
37// producing an object.
38inline bool IsInitExprInitializingARecordObject(const clang::Expr* expr) {
39 return expr->getType()->isRecordType() && expr->isPRValue();
40}
41
Luca Versaria12c9d52023-02-23 08:40:48 -080042// Returns the lifetimes of the given FunctionDecl, or an error if they are
43// unknown or analysis failed on that FunctionDecl.
44FunctionLifetimesOrError GetFunctionLifetimes(
45 const FunctionDecl* decl,
46 const llvm::DenseMap<const FunctionDecl*, FunctionLifetimesOrError>&
47 known_lifetimes);
48
Luca Versari99fddff2022-05-25 10:22:32 -070049// A repository for the objects used in the lifetime analysis of a single
50// function.
Martin Brænnefb8153d2022-06-28 04:05:14 -070051// This class establishes a relationship between AST nodes (e.g. variable
52// declarations) and the objects that represent them. It also stores additional
53// information about objects that does not change during the analysis.
54// The `ObjectRepository` only stores state that does not change during the
55// analysis; it is therefore not part of the lattice.
Luca Versari99fddff2022-05-25 10:22:32 -070056class ObjectRepository {
Martin Brænne57405822022-07-01 01:36:46 -070057 private:
Martin Brænnee9a4a472022-07-01 02:26:55 -070058 using MapType = llvm::DenseMap<const clang::ValueDecl*, const Object*>;
Martin Brænne57405822022-07-01 01:36:46 -070059
Luca Versari99fddff2022-05-25 10:22:32 -070060 public:
Luca Versari99fddff2022-05-25 10:22:32 -070061 // Tag struct for InitializedObject: the object being initialized is the
62 // return value of the function.
63 struct ReturnValue {};
64
65 // Maps a given struct-Object to the Object for each of its fields.
66 // TODO(veluca): this approach does not produce correct results when
67 // diamond-problem-style multiple inheritance happens.
68 using FieldObjects =
Martin Brænne1b98ac62022-07-01 06:24:52 -070069 llvm::DenseMap<std::pair<const Object*, const clang::FieldDecl*>,
70 const Object*>;
Luca Versari99fddff2022-05-25 10:22:32 -070071
72 // Maps a given struct-Object to the Object for each of its bases.
73 using BaseObjects =
Martin Brænne1b98ac62022-07-01 06:24:52 -070074 llvm::DenseMap<std::pair<const Object*, const clang::Type*>,
75 const Object*>;
Luca Versari99fddff2022-05-25 10:22:32 -070076
Martin Brænned7f20092022-06-28 04:04:33 -070077 // Iterator refers to a pair consisting of a variable declaration and the
78 // object representing that variable.
Luca Versari99fddff2022-05-25 10:22:32 -070079 using const_iterator = MapType::const_iterator;
80 using value_type = MapType::value_type;
81
Luca Versaria12c9d52023-02-23 08:40:48 -080082 // Creates an ObjectRepository with all relevant objects for the analysis
83 // of `func`. This includes:
84 // - Variables that are declared or referenced in `func`.
85 // - Functions that have their address taken in `func`.
86 // - String literals.
87 static llvm::Expected<ObjectRepository> Create(
88 const clang::FunctionDecl* func,
89 const llvm::DenseMap<const clang::FunctionDecl*,
90 FunctionLifetimesOrError>& callee_lifetimes);
Luca Versari99fddff2022-05-25 10:22:32 -070091
92 // Move-only.
93 ObjectRepository(ObjectRepository&&) = default;
94 ObjectRepository& operator=(ObjectRepository&&) = default;
95
96 // Returns a human-readable representation of the mapping.
97 std::string DebugString() const;
98
99 const_iterator begin() const { return object_repository_.begin(); }
100 const_iterator end() const { return object_repository_.end(); }
101
102 // Returns the object associated with a variable or function.
Martin Brænne46b5f072022-07-01 02:29:16 -0700103 const Object* GetDeclObject(const clang::ValueDecl* decl) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700104
105 // Returns the object associated with a materialize temporary expression.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700106 const Object* GetTemporaryObject(
107 const clang::MaterializeTemporaryExpr* expr) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700108
109 // Returns the object representing the value of a function parameter at
110 // function entry.
111 // Note: This `Object` does not represent the parameter variable itself;
112 // use GetDeclObject() to retrieve that. We're using an `Object` here
113 // because we don't have a dedicated "value" class, but you should not
114 // use this object's identity in any way; i.e. no other `Object` in the
115 // points-to map should ever point to the object returned by this
116 // function.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700117 const Object* GetOriginalParameterValue(
118 const clang::ParmVarDecl* var_decl) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700119
Luca Versari91a56ff2022-08-22 01:58:33 -0700120 // Synthetizes a FunctionLifetimes that has as lifetimes the initial lifetimes
121 // of the function currently being analyzed, before any analysis runs.
122 FunctionLifetimes GetOriginalFunctionLifetimes() const;
123
Luca Versari99fddff2022-05-25 10:22:32 -0700124 // Returns the object associated with an argument to a CallExpr.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700125 const Object* GetCallExprArgumentObject(const clang::CallExpr* expr,
126 size_t arg_index) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700127
Luca Versariefeaf272023-01-16 10:19:28 -0800128 // Returns the object associated with the return value of a CallExpr.
129 const Object* GetCallExprRetObject(const clang::Expr* expr) const;
130
131 // Returns the "virtual" lifetimes for a given function call.
132 const FunctionLifetimes& GetCallExprVirtualLifetimes(
133 const clang::Expr* expr) const;
134
Luca Versari99fddff2022-05-25 10:22:32 -0700135 // Returns the object associated with the `this` argument to a CallExpr that
136 // represents a method call. Note that this object represents the `this`
137 // pointer, not the object that the method is being called on.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700138 const Object* GetCallExprThisPointer(const clang::CallExpr* expr) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700139
140 // Returns the object associated with an argument to a CXXConstructExpr.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700141 const Object* GetCXXConstructExprArgumentObject(
142 const clang::CXXConstructExpr* expr, size_t arg_index) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700143
144 // Returns the object associated with the `this` argument to a
145 // CXXConstructExpr. Note that this object represents the `this` pointer, not
Martin Brænne7b0a9d12023-07-10 06:07:50 -0700146 // the object that the method is being called on (which is represented by the
147 // object from GetResultObject()).
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700148 const Object* GetCXXConstructExprThisPointer(
Luca Versari99fddff2022-05-25 10:22:32 -0700149 const clang::CXXConstructExpr* expr) const;
150
151 // Returns the object associated with, and initialized by, a constructor call
152 // (CXXConstructExpr) or a initializer list (CXXInitListExpr). Note that this
153 // represents the actual class object being initialized, not the `this`
154 // pointer to it that is passed to methods of the class, and which is
155 // represented by the object from GetCXXConstructExprThisPointer().
Martin Brænne7b0a9d12023-07-10 06:07:50 -0700156 const Object* GetResultObject(const clang::Expr* initializer_expr) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700157
Luca Versari99fddff2022-05-25 10:22:32 -0700158 // Returns the object that represents `*this`, if in a member function.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700159 std::optional<const Object*> GetThisObject() const { return this_object_; }
Luca Versari99fddff2022-05-25 10:22:32 -0700160
161 // Returns the `Object` associated with the return value of the function.
162 // Unlike the `Object`s for variables, the "return value object" is a fiction
163 // -- there is not, in general, going to be a single object associated with
164 // the return value, and it will not, in general, be possible to take the
165 // address of the return value object. It's still a useful fiction, however,
166 // because it allows us to treat return values the same way as other values.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700167 const Object* GetReturnObject() const { return return_object_; }
Luca Versari99fddff2022-05-25 10:22:32 -0700168
Luca Versaria12c9d52023-02-23 08:40:48 -0800169 // Returns an object that represents (the lifetimes of) any string literal.
170 const Object* GetStringLiteralObject() const {
171 return string_literal_object_;
172 }
173
Luca Versari99fddff2022-05-25 10:22:32 -0700174 // Returns the object associated with a given field in the struct
175 // represented by `struct_object`.
Martin Brænneaf594682022-07-01 06:12:16 -0700176 const Object* GetFieldObject(const Object* struct_object,
Martin Brænne1b98ac62022-07-01 06:24:52 -0700177 const clang::FieldDecl* field) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700178
179 // Returns the objects associated with a given field in the structs
180 // represented by `struct_objects`.
181 ObjectSet GetFieldObject(const ObjectSet& struct_objects,
182 const clang::FieldDecl* field) const;
183
184 // Returns FieldObjects; useful for producing debugging output.
185 const FieldObjects& GetFieldObjects() const { return field_object_map_; }
186
187 // Returns the object associated with a given base of the struct
188 // represented by `struct_object`.
Martin Brænne1b98ac62022-07-01 06:24:52 -0700189 const Object* GetBaseClassObject(const Object* struct_object,
Martin Brænnee08ac882022-07-01 02:24:49 -0700190 const clang::Type* base) const;
Martin Brænneaf594682022-07-01 06:12:16 -0700191 const Object* GetBaseClassObject(const Object* struct_object,
Martin Brænnee08ac882022-07-01 02:24:49 -0700192 const clang::QualType base) const {
Luca Versari99fddff2022-05-25 10:22:32 -0700193 return GetBaseClassObject(struct_object, base.getTypePtr());
194 }
195
196 // Returns the objects associated with a given base of the structs
197 // represented by `struct_object`.
198 ObjectSet GetBaseClassObject(const ObjectSet& struct_objects,
199 const clang::Type* base) const;
Luca Versari1f9fc2e2022-08-17 07:06:00 -0700200 ObjectSet GetBaseClassObject(const ObjectSet& struct_objects,
201 const clang::QualType base) const {
202 return GetBaseClassObject(struct_objects, base.getTypePtr());
203 }
Luca Versari99fddff2022-05-25 10:22:32 -0700204
205 // Returns BaseObjects; useful for producing debugging output.
206 const BaseObjects& GetBaseObjects() const { return base_object_map_; }
207
208 // Returns the PointsToMap implied by variable declarations, i.e. assuming
209 // that no code has been executed yet.
210 const PointsToMap& InitialPointsToMap() const {
211 return initial_points_to_map_;
212 }
213
Luca Versari53a2f582023-01-16 10:09:29 -0800214 // Returns the single-valued object set implied by variable declarations, i.e.
215 // assuming that no code has been executed yet.
216 const ObjectSet& InitialSingleValuedObjects() const {
217 return initial_single_valued_objects_;
218 }
219
Luca Versaria12c9d52023-02-23 08:40:48 -0800220 // Creates an object (and its related objects, such as objects for its fields,
221 // bases or pointees) with the given lifetimes. Points-to relations will be
222 // added to the given points_to_map.
Luca Versariefeaf272023-01-16 10:19:28 -0800223 // The returned Object will live as long as this ObjectRepository.
Luca Versaria12c9d52023-02-23 08:40:48 -0800224 // TODO(veluca): this is currently public just because of
225 // TransferDefaultConstructor in analyze.cc; in principle such objects
226 // could/should be created in advance.
227 const Object* CreateObject(const ObjectLifetimes& object_lifetimes,
228 PointsToMap& points_to_map);
Luca Versariefeaf272023-01-16 10:19:28 -0800229
Luca Versari99fddff2022-05-25 10:22:32 -0700230 private:
Luca Versaria12c9d52023-02-23 08:40:48 -0800231 ObjectRepository() = default;
232
233 // Creates an object (and related objects) for a given `type`; lifetimes of
234 // created objects are defined by the given
235 // `lifetime_factory`/`root_object_lifetime`, and the
236 // resulting points-to relations are stored in the ObjectRepository's
237 // initial_points_to_map_.
238 const Object* CreateObject(clang::QualType type,
239 Lifetime root_object_lifetime,
240 LifetimeFactory lifetime_factory);
241
242 template <typename... Args>
243 const Object* ConstructObject(Args&&... args);
Luca Versari99fddff2022-05-25 10:22:32 -0700244
Martin Brænned8e32142022-07-01 01:54:41 -0700245 const Object* CloneObject(const Object* object);
Luca Versari99fddff2022-05-25 10:22:32 -0700246
Martin Brænne46f1a572022-07-01 02:07:07 -0700247 std::optional<const Object*> GetFieldObjectInternal(
Martin Brænne1b98ac62022-07-01 06:24:52 -0700248 const Object* struct_object, const clang::FieldDecl* field) const;
Martin Brænne57405822022-07-01 01:36:46 -0700249
Luca Versaria12c9d52023-02-23 08:40:48 -0800250 // Owns all the `const Object*` members of the object repository.
Martin Brænne4a1231d2022-07-01 01:45:44 -0700251 llvm::SpecificBumpPtrAllocator<Object> object_allocator_;
252
Martin Brænne57405822022-07-01 01:36:46 -0700253 // Map from each variable declaration to the object which it declares.
254 MapType object_repository_;
255
256 // Map from each materialized temporary to the object which it declares.
Martin Brænne8f8e4fe2022-07-01 01:53:28 -0700257 llvm::DenseMap<const clang::MaterializeTemporaryExpr*, const Object*>
Martin Brænne57405822022-07-01 01:36:46 -0700258 temporary_objects_;
259
260 // Map from each function parameter to an object representing its initial
261 // value at function entry.
Martin Brænned8e32142022-07-01 01:54:41 -0700262 llvm::DenseMap<const clang::ParmVarDecl*, const Object*>
263 initial_parameter_object_;
Martin Brænne57405822022-07-01 01:36:46 -0700264
Martin Brænne7b0a9d12023-07-10 06:07:50 -0700265 // Map from each initializer (constructors or initializer lists) to the result
266 // object which it initializes.
Martin Brænne57405822022-07-01 01:36:46 -0700267 //
268 // An object in this map may occur in other places too: `object_repository_`
269 // if it is an lvalue, or `return_object_`. Or it may be a temporary in which
270 // case it is only found in this map.
Martin Brænne7b0a9d12023-07-10 06:07:50 -0700271 llvm::DenseMap<const clang::Expr*, const Object*> result_objects_;
Martin Brænne57405822022-07-01 01:36:46 -0700272
Martin Brænne04fb3a42022-07-01 01:52:21 -0700273 std::optional<const Object*> this_object_;
274 const Object* return_object_;
Martin Brænne57405822022-07-01 01:36:46 -0700275
Luca Versari53a2f582023-01-16 10:09:29 -0800276 ObjectSet initial_single_valued_objects_;
Martin Brænne57405822022-07-01 01:36:46 -0700277
278 class VarDeclVisitor;
279
280 PointsToMap initial_points_to_map_;
281 FieldObjects field_object_map_;
282 BaseObjects base_object_map_;
283
Martin Brænne982a1152022-07-01 01:55:53 -0700284 llvm::DenseMap<std::pair<const clang::Expr*, size_t>, const Object*>
Martin Brænne57405822022-07-01 01:36:46 -0700285 call_expr_args_objects_;
286
Martin Brænne982a1152022-07-01 01:55:53 -0700287 llvm::DenseMap<const clang::Expr*, const Object*> call_expr_this_pointers_;
Martin Brænne57405822022-07-01 01:36:46 -0700288
Luca Versariefeaf272023-01-16 10:19:28 -0800289 llvm::DenseMap<const clang::Expr*, const Object*> call_expr_ret_objects_;
290
291 llvm::DenseMap<const clang::Expr*, FunctionLifetimes>
292 call_expr_virtual_lifetimes_;
293
Luca Versaria12c9d52023-02-23 08:40:48 -0800294 const Object* string_literal_object_ = nullptr;
Luca Versari91a56ff2022-08-22 01:58:33 -0700295
Luca Versaria12c9d52023-02-23 08:40:48 -0800296 const clang::FunctionDecl* func_ = nullptr;
Luca Versari91a56ff2022-08-22 01:58:33 -0700297
298 llvm::DenseMap<const Object*, ObjectLifetimes> initial_object_lifetimes_;
Luca Versaricd873a62023-01-18 13:45:08 -0800299
Dmitri Gribenkoa6c5d732023-08-01 00:30:20 -0700300 class ObjectCreator;
Luca Versari99fddff2022-05-25 10:22:32 -0700301};
302
303} // namespace lifetimes
304} // namespace tidy
305} // namespace clang
306
307#endif // DEVTOOLS_RUST_CC_INTEROP_LIFETIME_ANALYSIS_OBJECT_REPOSITORY_H_