blob: 4419e379219a20fd0fa67c1825de1d8d13ad0bd4 [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
8#include <functional>
9#include <optional>
10#include <string>
11#include <variant>
12
13#include "lifetime_analysis/object.h"
14#include "lifetime_analysis/object_set.h"
15#include "lifetime_analysis/points_to_map.h"
16#include "lifetime_annotations/type_lifetimes.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/Expr.h"
19#include "clang/AST/ExprCXX.h"
20#include "llvm/ADT/DenseMap.h"
Martin Brænne4a1231d2022-07-01 01:45:44 -070021#include "llvm/Support/Allocator.h"
Luca Versari99fddff2022-05-25 10:22:32 -070022
23namespace clang {
24namespace tidy {
25namespace lifetimes {
26
27// A record-type expression has 2 modes:
28// 1. If it's being assigned to a reference, then the contents of the expression
29// are a glvalue. This is because references require an object to point to.
30// 2. If it's being assigned to a record object, then the expression itself is
31// not creating an object, but initializing it. So the expression's type is
32// a pure value, and it acts _on_ the initializing object instead of
33// producing an object.
34inline bool IsInitExprInitializingARecordObject(const clang::Expr* expr) {
35 return expr->getType()->isRecordType() && expr->isPRValue();
36}
37
38// A repository for the objects used in the lifetime analysis of a single
39// function.
Martin Brænnefb8153d2022-06-28 04:05:14 -070040// This class establishes a relationship between AST nodes (e.g. variable
41// declarations) and the objects that represent them. It also stores additional
42// information about objects that does not change during the analysis.
43// The `ObjectRepository` only stores state that does not change during the
44// analysis; it is therefore not part of the lattice.
Luca Versari99fddff2022-05-25 10:22:32 -070045class ObjectRepository {
Martin Brænne57405822022-07-01 01:36:46 -070046 private:
Martin Brænnee9a4a472022-07-01 02:26:55 -070047 using MapType = llvm::DenseMap<const clang::ValueDecl*, const Object*>;
Martin Brænne57405822022-07-01 01:36:46 -070048
Luca Versari99fddff2022-05-25 10:22:32 -070049 public:
50 // An `Object` might represent objects that have either a single value (such
51 // as plain variables) or multiple ones (such as arrays, or structs).
52 // Assignment behaves differently in the two cases.
53 enum class ObjectValueType {
54 kSingleValued,
55 kMultiValued,
56 };
57
58 // Tag struct for InitializedObject: the object being initialized is the
59 // return value of the function.
60 struct ReturnValue {};
61
62 // Maps a given struct-Object to the Object for each of its fields.
63 // TODO(veluca): this approach does not produce correct results when
64 // diamond-problem-style multiple inheritance happens.
65 using FieldObjects =
Martin Brænne1b98ac62022-07-01 06:24:52 -070066 llvm::DenseMap<std::pair<const Object*, const clang::FieldDecl*>,
67 const Object*>;
Luca Versari99fddff2022-05-25 10:22:32 -070068
69 // Maps a given struct-Object to the Object for each of its bases.
70 using BaseObjects =
Martin Brænne1b98ac62022-07-01 06:24:52 -070071 llvm::DenseMap<std::pair<const Object*, const clang::Type*>,
72 const Object*>;
Luca Versari99fddff2022-05-25 10:22:32 -070073
Martin Brænned7f20092022-06-28 04:04:33 -070074 // Iterator refers to a pair consisting of a variable declaration and the
75 // object representing that variable.
Luca Versari99fddff2022-05-25 10:22:32 -070076 using const_iterator = MapType::const_iterator;
77 using value_type = MapType::value_type;
78
79 // Initializes the map with objects for all variables that are declared or
80 // referenced in `func`.
81 explicit ObjectRepository(const clang::FunctionDecl* func);
82
83 // Move-only.
84 ObjectRepository(ObjectRepository&&) = default;
85 ObjectRepository& operator=(ObjectRepository&&) = default;
86
87 // Returns a human-readable representation of the mapping.
88 std::string DebugString() const;
89
90 const_iterator begin() const { return object_repository_.begin(); }
91 const_iterator end() const { return object_repository_.end(); }
92
Martin Brænne4a1231d2022-07-01 01:45:44 -070093 // Creates an object with the given lifetime and type.
94 // The returned object will live as long as this `ObjectRepository`.
95 const Object* CreateObject(Lifetime lifetime, clang::QualType type);
96
97 // Creates an object representing a declared function.
98 // The returned object will live as long as this `ObjectRepository`.
99 const Object* CreateObjectFromFunctionDecl(const clang::FunctionDecl& func);
100
Luca Versari99fddff2022-05-25 10:22:32 -0700101 // Returns the object associated with a variable or function.
Martin Brænne46b5f072022-07-01 02:29:16 -0700102 const Object* GetDeclObject(const clang::ValueDecl* decl) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700103
104 // Returns the object associated with a materialize temporary expression.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700105 const Object* GetTemporaryObject(
106 const clang::MaterializeTemporaryExpr* expr) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700107
108 // Returns the object representing the value of a function parameter at
109 // function entry.
110 // Note: This `Object` does not represent the parameter variable itself;
111 // use GetDeclObject() to retrieve that. We're using an `Object` here
112 // because we don't have a dedicated "value" class, but you should not
113 // use this object's identity in any way; i.e. no other `Object` in the
114 // points-to map should ever point to the object returned by this
115 // function.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700116 const Object* GetOriginalParameterValue(
117 const clang::ParmVarDecl* var_decl) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700118
119 // Returns the object associated with an argument to a CallExpr.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700120 const Object* GetCallExprArgumentObject(const clang::CallExpr* expr,
121 size_t arg_index) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700122
123 // Returns the object associated with the `this` argument to a CallExpr that
124 // represents a method call. Note that this object represents the `this`
125 // pointer, not the object that the method is being called on.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700126 const Object* GetCallExprThisPointer(const clang::CallExpr* expr) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700127
128 // Returns the object associated with an argument to a CXXConstructExpr.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700129 const Object* GetCXXConstructExprArgumentObject(
130 const clang::CXXConstructExpr* expr, size_t arg_index) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700131
132 // Returns the object associated with the `this` argument to a
133 // CXXConstructExpr. Note that this object represents the `this` pointer, not
134 // the object that the method is being called on (which is represnted by the
135 // object from GetInitializedObject()).
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700136 const Object* GetCXXConstructExprThisPointer(
Luca Versari99fddff2022-05-25 10:22:32 -0700137 const clang::CXXConstructExpr* expr) const;
138
139 // Returns the object associated with, and initialized by, a constructor call
140 // (CXXConstructExpr) or a initializer list (CXXInitListExpr). Note that this
141 // represents the actual class object being initialized, not the `this`
142 // pointer to it that is passed to methods of the class, and which is
143 // represented by the object from GetCXXConstructExprThisPointer().
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700144 const Object* GetInitializedObject(const clang::Expr* initializer_expr) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700145
146 // Returns what kind of values the given object represents.
Martin Brænne1b98ac62022-07-01 06:24:52 -0700147 ObjectValueType GetObjectValueType(const Object* object) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700148
149 // Returns the object that represents `*this`, if in a member function.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700150 std::optional<const Object*> GetThisObject() const { return this_object_; }
Luca Versari99fddff2022-05-25 10:22:32 -0700151
152 // Returns the `Object` associated with the return value of the function.
153 // Unlike the `Object`s for variables, the "return value object" is a fiction
154 // -- there is not, in general, going to be a single object associated with
155 // the return value, and it will not, in general, be possible to take the
156 // address of the return value object. It's still a useful fiction, however,
157 // because it allows us to treat return values the same way as other values.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700158 const Object* GetReturnObject() const { return return_object_; }
Luca Versari99fddff2022-05-25 10:22:32 -0700159
160 // Returns the object associated with a given field in the struct
161 // represented by `struct_object`.
Martin Brænneaf594682022-07-01 06:12:16 -0700162 const Object* GetFieldObject(const Object* struct_object,
Martin Brænne1b98ac62022-07-01 06:24:52 -0700163 const clang::FieldDecl* field) const;
Luca Versari99fddff2022-05-25 10:22:32 -0700164
165 // Returns the objects associated with a given field in the structs
166 // represented by `struct_objects`.
167 ObjectSet GetFieldObject(const ObjectSet& struct_objects,
168 const clang::FieldDecl* field) const;
169
170 // Returns FieldObjects; useful for producing debugging output.
171 const FieldObjects& GetFieldObjects() const { return field_object_map_; }
172
173 // Returns the object associated with a given base of the struct
174 // represented by `struct_object`.
Martin Brænne1b98ac62022-07-01 06:24:52 -0700175 const Object* GetBaseClassObject(const Object* struct_object,
Martin Brænnee08ac882022-07-01 02:24:49 -0700176 const clang::Type* base) const;
Martin Brænneaf594682022-07-01 06:12:16 -0700177 const Object* GetBaseClassObject(const Object* struct_object,
Martin Brænnee08ac882022-07-01 02:24:49 -0700178 const clang::QualType base) const {
Luca Versari99fddff2022-05-25 10:22:32 -0700179 return GetBaseClassObject(struct_object, base.getTypePtr());
180 }
181
182 // Returns the objects associated with a given base of the structs
183 // represented by `struct_object`.
184 ObjectSet GetBaseClassObject(const ObjectSet& struct_objects,
185 const clang::Type* base) const;
186
187 // Returns BaseObjects; useful for producing debugging output.
188 const BaseObjects& GetBaseObjects() const { return base_object_map_; }
189
190 // Returns the PointsToMap implied by variable declarations, i.e. assuming
191 // that no code has been executed yet.
192 const PointsToMap& InitialPointsToMap() const {
193 return initial_points_to_map_;
194 }
195
196 // Creates and returns an object with static lifetime of the given type.
197 // Also creates any transitive objects if required.
198 // When called multiple times with the same `type`, this function always
199 // returns the same object. This is to guarantee that the number of objects
200 // used in the analysis is bounded and that therefore the lattice is finite
201 // and the analysis terminates.
Martin Brænned7c0d0b2022-07-01 05:43:00 -0700202 const Object* CreateStaticObject(clang::QualType type);
Luca Versari99fddff2022-05-25 10:22:32 -0700203
204 private:
Martin Brænne493d4d42022-07-01 05:44:23 -0700205 void CreateObjects(const Object* root_object, clang::QualType type,
Luca Versari99fddff2022-05-25 10:22:32 -0700206 LifetimeFactory lifetime_factory, bool transitive);
207
Martin Brænned8e32142022-07-01 01:54:41 -0700208 const Object* CloneObject(const Object* object);
Luca Versari99fddff2022-05-25 10:22:32 -0700209
Martin Brænne46f1a572022-07-01 02:07:07 -0700210 std::optional<const Object*> GetFieldObjectInternal(
Martin Brænne1b98ac62022-07-01 06:24:52 -0700211 const Object* struct_object, const clang::FieldDecl* field) const;
Martin Brænne57405822022-07-01 01:36:46 -0700212
Martin Brænne4a1231d2022-07-01 01:45:44 -0700213 llvm::SpecificBumpPtrAllocator<Object> object_allocator_;
214
Martin Brænne57405822022-07-01 01:36:46 -0700215 // Map from each variable declaration to the object which it declares.
216 MapType object_repository_;
217
218 // Map from each materialized temporary to the object which it declares.
Martin Brænne8f8e4fe2022-07-01 01:53:28 -0700219 llvm::DenseMap<const clang::MaterializeTemporaryExpr*, const Object*>
Martin Brænne57405822022-07-01 01:36:46 -0700220 temporary_objects_;
221
222 // Map from each function parameter to an object representing its initial
223 // value at function entry.
Martin Brænned8e32142022-07-01 01:54:41 -0700224 llvm::DenseMap<const clang::ParmVarDecl*, const Object*>
225 initial_parameter_object_;
Martin Brænne57405822022-07-01 01:36:46 -0700226
227 // Map from each initializer (constructors or initializer lists) to the object
228 // which it initializes.
229 //
230 // An object in this map may occur in other places too: `object_repository_`
231 // if it is an lvalue, or `return_object_`. Or it may be a temporary in which
232 // case it is only found in this map.
Martin Brænneecd58c32022-07-01 02:25:47 -0700233 llvm::DenseMap<const clang::Expr*, const Object*> initialized_objects_;
Martin Brænne57405822022-07-01 01:36:46 -0700234
Martin Brænne04fb3a42022-07-01 01:52:21 -0700235 std::optional<const Object*> this_object_;
236 const Object* return_object_;
Martin Brænne57405822022-07-01 01:36:46 -0700237
Martin Brænne1b98ac62022-07-01 06:24:52 -0700238 llvm::DenseMap<const Object*, ObjectValueType> object_value_types_;
Martin Brænne57405822022-07-01 01:36:46 -0700239
240 class VarDeclVisitor;
241
242 PointsToMap initial_points_to_map_;
243 FieldObjects field_object_map_;
244 BaseObjects base_object_map_;
245
Martin Brænne982a1152022-07-01 01:55:53 -0700246 llvm::DenseMap<std::pair<const clang::Expr*, size_t>, const Object*>
Martin Brænne57405822022-07-01 01:36:46 -0700247 call_expr_args_objects_;
248
Martin Brænne982a1152022-07-01 01:55:53 -0700249 llvm::DenseMap<const clang::Expr*, const Object*> call_expr_this_pointers_;
Martin Brænne57405822022-07-01 01:36:46 -0700250
Martin Brænne3b587cf2022-07-01 01:57:01 -0700251 llvm::DenseMap<clang::QualType, const Object*> static_objects_;
Luca Versari99fddff2022-05-25 10:22:32 -0700252};
253
254} // namespace lifetimes
255} // namespace tidy
256} // namespace clang
257
258#endif // DEVTOOLS_RUST_CC_INTEROP_LIFETIME_ANALYSIS_OBJECT_REPOSITORY_H_