blob: 7648208da135ad3ac179307e6e435e1c2b28505d [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#include "lifetime_analysis/points_to_map.h"
6
7#include <string>
8#include <utility>
9#include <vector>
10
11#include "absl/strings/str_format.h"
12#include "absl/strings/str_join.h"
13#include "clang/AST/Expr.h"
14
15namespace clang {
16namespace tidy {
17namespace lifetimes {
18
19bool PointsToMap::operator==(const PointsToMap& other) const {
20 return pointer_points_tos_ == other.pointer_points_tos_ &&
21 expr_objects_ == other.expr_objects_;
22}
23
24std::string PointsToMap::DebugString() const {
25 std::vector<std::string> parts;
26 for (const auto& [pointer, points_to] : pointer_points_tos_) {
Martin Brænnea5098e12022-07-01 06:22:28 -070027 parts.push_back(absl::StrFormat("%s -> %s", pointer->DebugString(),
Luca Versari99fddff2022-05-25 10:22:32 -070028 points_to.DebugString()));
29 }
30 for (const auto& [expr, objects] : expr_objects_) {
31 parts.push_back(absl::StrFormat("%s (%p) -> %s", expr->getStmtClassName(),
32 expr, objects.DebugString()));
33 }
34 return absl::StrJoin(parts, "\n");
35}
36
37PointsToMap PointsToMap::Union(const PointsToMap& other) const {
38 PointsToMap result;
39
40 result.pointer_points_tos_ = pointer_points_tos_;
41 for (const auto& [pointer, points_to] : other.pointer_points_tos_) {
42 result.pointer_points_tos_[pointer].Add(points_to);
43 }
44 // TODO(mboehme): Do we even need to perform a union on expression object
45 // sets?
46 result.expr_objects_ = expr_objects_;
47 for (const auto& [expr, objects] : other.expr_objects_) {
48 result.expr_objects_[expr].Add(objects);
49 }
50
51 return result;
52}
53
Martin Brænnea5098e12022-07-01 06:22:28 -070054ObjectSet PointsToMap::GetPointerPointsToSet(const Object* pointer) const {
Luca Versari99fddff2022-05-25 10:22:32 -070055 auto iter = pointer_points_tos_.find(pointer);
56 if (iter == pointer_points_tos_.end()) {
57 return ObjectSet();
58 }
59 return iter->second;
60}
61
Martin Brænnea5098e12022-07-01 06:22:28 -070062void PointsToMap::SetPointerPointsToSet(const Object* pointer,
63 ObjectSet points_to) {
Luca Versari99fddff2022-05-25 10:22:32 -070064 pointer_points_tos_[pointer] = std::move(points_to);
65}
66
67void PointsToMap::SetPointerPointsToSet(const ObjectSet& pointers,
68 const ObjectSet& points_to) {
Martin Brænne4d8cdfd2022-07-01 06:16:36 -070069 for (const Object* pointer : pointers) {
Luca Versari99fddff2022-05-25 10:22:32 -070070 SetPointerPointsToSet(pointer, points_to);
71 }
72}
73
Martin Brænnea5098e12022-07-01 06:22:28 -070074void PointsToMap::ExtendPointerPointsToSet(const Object* pointer,
Luca Versari99fddff2022-05-25 10:22:32 -070075 const ObjectSet& points_to) {
76 ObjectSet& set = pointer_points_tos_[pointer];
77 set.Add(points_to);
78}
79
80ObjectSet PointsToMap::GetPointerPointsToSet(const ObjectSet& pointers) const {
81 ObjectSet result;
Martin Brænne4d8cdfd2022-07-01 06:16:36 -070082 for (const Object* pointer : pointers) {
Martin Brænnea5098e12022-07-01 06:22:28 -070083 auto iter = pointer_points_tos_.find(pointer);
Luca Versari99fddff2022-05-25 10:22:32 -070084 if (iter != pointer_points_tos_.end()) {
85 result.Add(iter->second);
86 }
87 }
88 return result;
89}
90
91ObjectSet PointsToMap::GetExprObjectSet(const clang::Expr* expr) const {
92 // We can't handle `ParenExpr`s like other `Expr`s because the CFG doesn't
93 // contain `CFGStmt`s for them. Instead, if we encounter a `ParenExpr` here,
94 // we simply return the object set for its subexpression.
95 if (auto paren = clang::dyn_cast<clang::ParenExpr>(expr)) {
96 expr = paren->getSubExpr();
97 }
98
99 assert(expr->isGLValue() || expr->getType()->isPointerType() ||
100 expr->getType()->isArrayType() || expr->getType()->isFunctionType() ||
101 expr->getType()->isBuiltinType());
102
103 auto iter = expr_objects_.find(expr);
104 if (iter == expr_objects_.end()) {
105 llvm::errs() << "Didn't find object set for expression:\n";
106 expr->dump();
107 llvm::report_fatal_error("Didn't find object set for expression");
108 }
109 return iter->second;
110}
111
112void PointsToMap::SetExprObjectSet(const clang::Expr* expr, ObjectSet objects) {
113 assert(expr->isGLValue() || expr->getType()->isPointerType() ||
114 expr->getType()->isArrayType() || expr->getType()->isBuiltinType());
115 expr_objects_[expr] = std::move(objects);
116}
117
Martin Brænnea5098e12022-07-01 06:22:28 -0700118std::vector<const Object*> PointsToMap::GetAllPointersWithLifetime(
Luca Versari99fddff2022-05-25 10:22:32 -0700119 Lifetime lifetime) const {
Martin Brænnea5098e12022-07-01 06:22:28 -0700120 std::vector<const Object*> result;
Luca Versari99fddff2022-05-25 10:22:32 -0700121 for (const auto& [pointer, _] : pointer_points_tos_) {
Martin Brænnea5098e12022-07-01 06:22:28 -0700122 if (pointer->GetLifetime() == lifetime) {
Luca Versari99fddff2022-05-25 10:22:32 -0700123 result.push_back(pointer);
124 }
125 }
126 return result;
127}
128
129} // namespace lifetimes
130} // namespace tidy
131} // namespace clang