blob: a09ee581d0639643103c5f6d2ed44b4050cd2479 [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"
21
22namespace clang {
23namespace tidy {
24namespace lifetimes {
25
26// A record-type expression has 2 modes:
27// 1. If it's being assigned to a reference, then the contents of the expression
28// are a glvalue. This is because references require an object to point to.
29// 2. If it's being assigned to a record object, then the expression itself is
30// not creating an object, but initializing it. So the expression's type is
31// a pure value, and it acts _on_ the initializing object instead of
32// producing an object.
33inline bool IsInitExprInitializingARecordObject(const clang::Expr* expr) {
34 return expr->getType()->isRecordType() && expr->isPRValue();
35}
36
37// A repository for the objects used in the lifetime analysis of a single
38// function.
Martin Brænnefb8153d2022-06-28 04:05:14 -070039// This class establishes a relationship between AST nodes (e.g. variable
40// declarations) and the objects that represent them. It also stores additional
41// information about objects that does not change during the analysis.
42// The `ObjectRepository` only stores state that does not change during the
43// analysis; it is therefore not part of the lattice.
Luca Versari99fddff2022-05-25 10:22:32 -070044class ObjectRepository {
Martin Brænne57405822022-07-01 01:36:46 -070045 private:
46 using MapType = llvm::DenseMap<const clang::ValueDecl*, Object>;
47
Luca Versari99fddff2022-05-25 10:22:32 -070048 public:
49 // An `Object` might represent objects that have either a single value (such
50 // as plain variables) or multiple ones (such as arrays, or structs).
51 // Assignment behaves differently in the two cases.
52 enum class ObjectValueType {
53 kSingleValued,
54 kMultiValued,
55 };
56
57 // Tag struct for InitializedObject: the object being initialized is the
58 // return value of the function.
59 struct ReturnValue {};
60
61 // Maps a given struct-Object to the Object for each of its fields.
62 // TODO(veluca): this approach does not produce correct results when
63 // diamond-problem-style multiple inheritance happens.
64 using FieldObjects =
65 llvm::DenseMap<std::pair<Object, const clang::FieldDecl*>, Object>;
66
67 // Maps a given struct-Object to the Object for each of its bases.
68 using BaseObjects =
69 llvm::DenseMap<std::pair<Object, const clang::Type*>, Object>;
70
Martin Brænned7f20092022-06-28 04:04:33 -070071 // Iterator refers to a pair consisting of a variable declaration and the
72 // object representing that variable.
Luca Versari99fddff2022-05-25 10:22:32 -070073 using const_iterator = MapType::const_iterator;
74 using value_type = MapType::value_type;
75
76 // Initializes the map with objects for all variables that are declared or
77 // referenced in `func`.
78 explicit ObjectRepository(const clang::FunctionDecl* func);
79
80 // Move-only.
81 ObjectRepository(ObjectRepository&&) = default;
82 ObjectRepository& operator=(ObjectRepository&&) = default;
83
84 // Returns a human-readable representation of the mapping.
85 std::string DebugString() const;
86
87 const_iterator begin() const { return object_repository_.begin(); }
88 const_iterator end() const { return object_repository_.end(); }
89
90 // Returns the object associated with a variable or function.
91 Object GetDeclObject(const clang::ValueDecl* decl) const;
92
93 // Returns the object associated with a materialize temporary expression.
94 Object GetTemporaryObject(const clang::MaterializeTemporaryExpr* expr) const;
95
96 // Returns the object representing the value of a function parameter at
97 // function entry.
98 // Note: This `Object` does not represent the parameter variable itself;
99 // use GetDeclObject() to retrieve that. We're using an `Object` here
100 // because we don't have a dedicated "value" class, but you should not
101 // use this object's identity in any way; i.e. no other `Object` in the
102 // points-to map should ever point to the object returned by this
103 // function.
104 Object GetOriginalParameterValue(const clang::ParmVarDecl* var_decl) const;
105
106 // Returns the object associated with an argument to a CallExpr.
107 Object GetCallExprArgumentObject(const clang::CallExpr* expr,
108 size_t arg_index) const;
109
110 // Returns the object associated with the `this` argument to a CallExpr that
111 // represents a method call. Note that this object represents the `this`
112 // pointer, not the object that the method is being called on.
113 Object GetCallExprThisPointer(const clang::CallExpr* expr) const;
114
115 // Returns the object associated with an argument to a CXXConstructExpr.
116 Object GetCXXConstructExprArgumentObject(const clang::CXXConstructExpr* expr,
117 size_t arg_index) const;
118
119 // Returns the object associated with the `this` argument to a
120 // CXXConstructExpr. Note that this object represents the `this` pointer, not
121 // the object that the method is being called on (which is represnted by the
122 // object from GetInitializedObject()).
123 Object GetCXXConstructExprThisPointer(
124 const clang::CXXConstructExpr* expr) const;
125
126 // Returns the object associated with, and initialized by, a constructor call
127 // (CXXConstructExpr) or a initializer list (CXXInitListExpr). Note that this
128 // represents the actual class object being initialized, not the `this`
129 // pointer to it that is passed to methods of the class, and which is
130 // represented by the object from GetCXXConstructExprThisPointer().
131 Object GetInitializedObject(const clang::Expr* initializer_expr) const;
132
133 // Returns what kind of values the given object represents.
134 ObjectValueType GetObjectValueType(Object object) const;
135
136 // Returns the object that represents `*this`, if in a member function.
137 std::optional<Object> GetThisObject() const { return this_object_; }
138
139 // Returns the `Object` associated with the return value of the function.
140 // Unlike the `Object`s for variables, the "return value object" is a fiction
141 // -- there is not, in general, going to be a single object associated with
142 // the return value, and it will not, in general, be possible to take the
143 // address of the return value object. It's still a useful fiction, however,
144 // because it allows us to treat return values the same way as other values.
145 Object GetReturnObject() const { return return_object_; }
146
147 // Returns the object associated with a given field in the struct
148 // represented by `struct_object`.
149 Object GetFieldObject(Object struct_object,
150 const clang::FieldDecl* field) const;
151
152 // Returns the objects associated with a given field in the structs
153 // represented by `struct_objects`.
154 ObjectSet GetFieldObject(const ObjectSet& struct_objects,
155 const clang::FieldDecl* field) const;
156
157 // Returns FieldObjects; useful for producing debugging output.
158 const FieldObjects& GetFieldObjects() const { return field_object_map_; }
159
160 // Returns the object associated with a given base of the struct
161 // represented by `struct_object`.
162 Object GetBaseClassObject(Object struct_object,
163 const clang::Type* base) const;
164 Object GetBaseClassObject(Object struct_object,
165 const clang::QualType base) const {
166 return GetBaseClassObject(struct_object, base.getTypePtr());
167 }
168
169 // Returns the objects associated with a given base of the structs
170 // represented by `struct_object`.
171 ObjectSet GetBaseClassObject(const ObjectSet& struct_objects,
172 const clang::Type* base) const;
173
174 // Returns BaseObjects; useful for producing debugging output.
175 const BaseObjects& GetBaseObjects() const { return base_object_map_; }
176
177 // Returns the PointsToMap implied by variable declarations, i.e. assuming
178 // that no code has been executed yet.
179 const PointsToMap& InitialPointsToMap() const {
180 return initial_points_to_map_;
181 }
182
183 // Creates and returns an object with static lifetime of the given type.
184 // Also creates any transitive objects if required.
185 // When called multiple times with the same `type`, this function always
186 // returns the same object. This is to guarantee that the number of objects
187 // used in the analysis is bounded and that therefore the lattice is finite
188 // and the analysis terminates.
189 Object CreateStaticObject(clang::QualType type);
190
191 private:
192 void CreateObjects(Object root_object, clang::QualType type,
193 LifetimeFactory lifetime_factory, bool transitive);
194
195 Object CloneObject(Object object);
196
197 std::optional<Object> GetFieldObjectInternal(
198 Object struct_object, const clang::FieldDecl* field) const;
Martin Brænne57405822022-07-01 01:36:46 -0700199
200 // Map from each variable declaration to the object which it declares.
201 MapType object_repository_;
202
203 // Map from each materialized temporary to the object which it declares.
204 llvm::DenseMap<const clang::MaterializeTemporaryExpr*, Object>
205 temporary_objects_;
206
207 // Map from each function parameter to an object representing its initial
208 // value at function entry.
209 llvm::DenseMap<const clang::ParmVarDecl*, Object> initial_parameter_object_;
210
211 // Map from each initializer (constructors or initializer lists) to the object
212 // which it initializes.
213 //
214 // An object in this map may occur in other places too: `object_repository_`
215 // if it is an lvalue, or `return_object_`. Or it may be a temporary in which
216 // case it is only found in this map.
217 llvm::DenseMap<const clang::Expr*, Object> initialized_objects_;
218
219 std::optional<Object> this_object_;
220 Object return_object_;
221
222 llvm::DenseMap<Object, ObjectValueType> object_value_types_;
223
224 class VarDeclVisitor;
225
226 PointsToMap initial_points_to_map_;
227 FieldObjects field_object_map_;
228 BaseObjects base_object_map_;
229
230 llvm::DenseMap<std::pair<const clang::Expr*, size_t>, Object>
231 call_expr_args_objects_;
232
233 llvm::DenseMap<const clang::Expr*, Object> call_expr_this_pointers_;
234
235 llvm::DenseMap<clang::QualType, Object> static_objects_;
Luca Versari99fddff2022-05-25 10:22:32 -0700236};
237
238} // namespace lifetimes
239} // namespace tidy
240} // namespace clang
241
242#endif // DEVTOOLS_RUST_CC_INTEROP_LIFETIME_ANALYSIS_OBJECT_REPOSITORY_H_