blob: d79ff7255564733cf5abed8ace85a3761f5bfbb4 [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:
47 using MapType = llvm::DenseMap<const clang::ValueDecl*, Object>;
48
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 =
66 llvm::DenseMap<std::pair<Object, const clang::FieldDecl*>, Object>;
67
68 // Maps a given struct-Object to the Object for each of its bases.
69 using BaseObjects =
70 llvm::DenseMap<std::pair<Object, const clang::Type*>, Object>;
71
Martin Brænned7f20092022-06-28 04:04:33 -070072 // Iterator refers to a pair consisting of a variable declaration and the
73 // object representing that variable.
Luca Versari99fddff2022-05-25 10:22:32 -070074 using const_iterator = MapType::const_iterator;
75 using value_type = MapType::value_type;
76
77 // Initializes the map with objects for all variables that are declared or
78 // referenced in `func`.
79 explicit ObjectRepository(const clang::FunctionDecl* func);
80
81 // Move-only.
82 ObjectRepository(ObjectRepository&&) = default;
83 ObjectRepository& operator=(ObjectRepository&&) = default;
84
85 // Returns a human-readable representation of the mapping.
86 std::string DebugString() const;
87
88 const_iterator begin() const { return object_repository_.begin(); }
89 const_iterator end() const { return object_repository_.end(); }
90
Martin Brænne4a1231d2022-07-01 01:45:44 -070091 // Creates an object with the given lifetime and type.
92 // The returned object will live as long as this `ObjectRepository`.
93 const Object* CreateObject(Lifetime lifetime, clang::QualType type);
94
95 // Creates an object representing a declared function.
96 // The returned object will live as long as this `ObjectRepository`.
97 const Object* CreateObjectFromFunctionDecl(const clang::FunctionDecl& func);
98
Luca Versari99fddff2022-05-25 10:22:32 -070099 // Returns the object associated with a variable or function.
100 Object GetDeclObject(const clang::ValueDecl* decl) const;
101
102 // Returns the object associated with a materialize temporary expression.
103 Object GetTemporaryObject(const clang::MaterializeTemporaryExpr* expr) const;
104
105 // Returns the object representing the value of a function parameter at
106 // function entry.
107 // Note: This `Object` does not represent the parameter variable itself;
108 // use GetDeclObject() to retrieve that. We're using an `Object` here
109 // because we don't have a dedicated "value" class, but you should not
110 // use this object's identity in any way; i.e. no other `Object` in the
111 // points-to map should ever point to the object returned by this
112 // function.
113 Object GetOriginalParameterValue(const clang::ParmVarDecl* var_decl) const;
114
115 // Returns the object associated with an argument to a CallExpr.
116 Object GetCallExprArgumentObject(const clang::CallExpr* expr,
117 size_t arg_index) const;
118
119 // Returns the object associated with the `this` argument to a CallExpr that
120 // represents a method call. Note that this object represents the `this`
121 // pointer, not the object that the method is being called on.
122 Object GetCallExprThisPointer(const clang::CallExpr* expr) const;
123
124 // Returns the object associated with an argument to a CXXConstructExpr.
125 Object GetCXXConstructExprArgumentObject(const clang::CXXConstructExpr* expr,
126 size_t arg_index) const;
127
128 // Returns the object associated with the `this` argument to a
129 // CXXConstructExpr. Note that this object represents the `this` pointer, not
130 // the object that the method is being called on (which is represnted by the
131 // object from GetInitializedObject()).
132 Object GetCXXConstructExprThisPointer(
133 const clang::CXXConstructExpr* expr) const;
134
135 // Returns the object associated with, and initialized by, a constructor call
136 // (CXXConstructExpr) or a initializer list (CXXInitListExpr). Note that this
137 // represents the actual class object being initialized, not the `this`
138 // pointer to it that is passed to methods of the class, and which is
139 // represented by the object from GetCXXConstructExprThisPointer().
140 Object GetInitializedObject(const clang::Expr* initializer_expr) const;
141
142 // Returns what kind of values the given object represents.
143 ObjectValueType GetObjectValueType(Object object) const;
144
145 // Returns the object that represents `*this`, if in a member function.
Martin Brænne04fb3a42022-07-01 01:52:21 -0700146 std::optional<Object> GetThisObject() const {
147 if (this_object_) {
148 return **this_object_;
149 } else {
150 return std::nullopt;
151 }
152 }
Luca Versari99fddff2022-05-25 10:22:32 -0700153
154 // Returns the `Object` associated with the return value of the function.
155 // Unlike the `Object`s for variables, the "return value object" is a fiction
156 // -- there is not, in general, going to be a single object associated with
157 // the return value, and it will not, in general, be possible to take the
158 // address of the return value object. It's still a useful fiction, however,
159 // because it allows us to treat return values the same way as other values.
Martin Brænne04fb3a42022-07-01 01:52:21 -0700160 Object GetReturnObject() const { return *return_object_; }
Luca Versari99fddff2022-05-25 10:22:32 -0700161
162 // Returns the object associated with a given field in the struct
163 // represented by `struct_object`.
164 Object GetFieldObject(Object struct_object,
165 const clang::FieldDecl* field) const;
166
167 // Returns the objects associated with a given field in the structs
168 // represented by `struct_objects`.
169 ObjectSet GetFieldObject(const ObjectSet& struct_objects,
170 const clang::FieldDecl* field) const;
171
172 // Returns FieldObjects; useful for producing debugging output.
173 const FieldObjects& GetFieldObjects() const { return field_object_map_; }
174
175 // Returns the object associated with a given base of the struct
176 // represented by `struct_object`.
177 Object GetBaseClassObject(Object struct_object,
178 const clang::Type* base) const;
179 Object GetBaseClassObject(Object struct_object,
180 const clang::QualType base) const {
181 return GetBaseClassObject(struct_object, base.getTypePtr());
182 }
183
184 // Returns the objects associated with a given base of the structs
185 // represented by `struct_object`.
186 ObjectSet GetBaseClassObject(const ObjectSet& struct_objects,
187 const clang::Type* base) const;
188
189 // Returns BaseObjects; useful for producing debugging output.
190 const BaseObjects& GetBaseObjects() const { return base_object_map_; }
191
192 // Returns the PointsToMap implied by variable declarations, i.e. assuming
193 // that no code has been executed yet.
194 const PointsToMap& InitialPointsToMap() const {
195 return initial_points_to_map_;
196 }
197
198 // Creates and returns an object with static lifetime of the given type.
199 // Also creates any transitive objects if required.
200 // When called multiple times with the same `type`, this function always
201 // returns the same object. This is to guarantee that the number of objects
202 // used in the analysis is bounded and that therefore the lattice is finite
203 // and the analysis terminates.
204 Object CreateStaticObject(clang::QualType type);
205
206 private:
207 void CreateObjects(Object root_object, clang::QualType type,
208 LifetimeFactory lifetime_factory, bool transitive);
209
210 Object CloneObject(Object object);
211
212 std::optional<Object> GetFieldObjectInternal(
213 Object struct_object, const clang::FieldDecl* field) const;
Martin Brænne57405822022-07-01 01:36:46 -0700214
Martin Brænne4a1231d2022-07-01 01:45:44 -0700215 llvm::SpecificBumpPtrAllocator<Object> object_allocator_;
216
Martin Brænne57405822022-07-01 01:36:46 -0700217 // Map from each variable declaration to the object which it declares.
218 MapType object_repository_;
219
220 // Map from each materialized temporary to the object which it declares.
Martin Brænne8f8e4fe2022-07-01 01:53:28 -0700221 llvm::DenseMap<const clang::MaterializeTemporaryExpr*, const Object*>
Martin Brænne57405822022-07-01 01:36:46 -0700222 temporary_objects_;
223
224 // Map from each function parameter to an object representing its initial
225 // value at function entry.
226 llvm::DenseMap<const clang::ParmVarDecl*, Object> initial_parameter_object_;
227
228 // Map from each initializer (constructors or initializer lists) to the object
229 // which it initializes.
230 //
231 // An object in this map may occur in other places too: `object_repository_`
232 // if it is an lvalue, or `return_object_`. Or it may be a temporary in which
233 // case it is only found in this map.
234 llvm::DenseMap<const clang::Expr*, Object> initialized_objects_;
235
Martin Brænne04fb3a42022-07-01 01:52:21 -0700236 std::optional<const Object*> this_object_;
237 const Object* return_object_;
Martin Brænne57405822022-07-01 01:36:46 -0700238
239 llvm::DenseMap<Object, ObjectValueType> object_value_types_;
240
241 class VarDeclVisitor;
242
243 PointsToMap initial_points_to_map_;
244 FieldObjects field_object_map_;
245 BaseObjects base_object_map_;
246
247 llvm::DenseMap<std::pair<const clang::Expr*, size_t>, Object>
248 call_expr_args_objects_;
249
250 llvm::DenseMap<const clang::Expr*, Object> call_expr_this_pointers_;
251
252 llvm::DenseMap<clang::QualType, Object> static_objects_;
Luca Versari99fddff2022-05-25 10:22:32 -0700253};
254
255} // namespace lifetimes
256} // namespace tidy
257} // namespace clang
258
259#endif // DEVTOOLS_RUST_CC_INTEROP_LIFETIME_ANALYSIS_OBJECT_REPOSITORY_H_