blob: 258735ff73210e449819aa294397ddabe5a4e585 [file] [log] [blame]
Googlerace85a22021-11-26 14:18:31 +00001// 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_annotations/type_lifetimes.h"
6
7#include <algorithm>
Dmitri Gribenkoa087d232023-07-10 08:03:46 -07008#include <cassert>
9#include <cstddef>
10#include <functional>
Googlerc071e242021-12-16 15:23:41 +000011#include <memory>
12#include <optional>
Googlerace85a22021-11-26 14:18:31 +000013#include <string>
Googler705f9452021-12-16 15:30:08 +000014#include <utility>
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070015#include <vector>
Googlerace85a22021-11-26 14:18:31 +000016
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070017#include "absl/strings/str_cat.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070018#include "absl/strings/str_join.h"
Luca Versaricc7e6cb2022-04-05 08:08:23 -070019#include "lifetime_annotations/function_lifetimes.h"
Marcel Hlopko97a68a12022-03-09 11:38:51 +000020#include "lifetime_annotations/lifetime.h"
Martin Brænne198ff492023-04-05 01:41:25 -070021#include "lifetime_annotations/lifetime_error.h"
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070022#include "lifetime_annotations/lifetime_substitutions.h"
Marcel Hlopko97a68a12022-03-09 11:38:51 +000023#include "lifetime_annotations/lifetime_symbol_table.h"
24#include "lifetime_annotations/pointee_type.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070025#include "clang/AST/Attr.h"
26#include "clang/AST/Attrs.inc"
27#include "clang/AST/DeclCXX.h"
28#include "clang/AST/DeclTemplate.h"
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070029#include "clang/AST/Expr.h"
30#include "clang/AST/NestedNameSpecifier.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070031#include "clang/AST/TemplateBase.h"
32#include "clang/AST/Type.h"
Dmitri Gribenkoa087d232023-07-10 08:03:46 -070033#include "clang/AST/TypeLoc.h"
34#include "clang/AST/TypeOrdering.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070035#include "clang/Basic/LLVM.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070036#include "llvm/ADT/ArrayRef.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070037#include "llvm/ADT/Hashing.h"
38#include "llvm/ADT/SmallVector.h"
39#include "llvm/ADT/StringRef.h"
40#include "llvm/Support/Error.h"
41#include "llvm/Support/ErrorHandling.h"
Googlerace85a22021-11-26 14:18:31 +000042
Martin Brænne1a207c52022-04-19 00:05:38 -070043namespace clang {
44namespace tidy {
45namespace lifetimes {
Googlerace85a22021-11-26 14:18:31 +000046
Martin Brænne9fb786f2022-06-23 01:18:19 -070047clang::QualType StripAttributes(clang::QualType type) {
48 while (true) {
49 if (auto macro_qualified_type = type->getAs<clang::MacroQualifiedType>()) {
50 type = macro_qualified_type->getUnderlyingType();
51 } else if (auto attr_type = type->getAs<clang::AttributedType>()) {
52 type = attr_type->getModifiedType();
53 } else {
54 return type;
55 }
56 }
57}
58
59clang::TypeLoc StripAttributes(clang::TypeLoc type_loc,
60 llvm::SmallVector<const clang::Attr*>& attrs) {
61 while (true) {
62 if (auto macro_qualified_type_loc =
63 type_loc.getAs<clang::MacroQualifiedTypeLoc>()) {
64 type_loc = macro_qualified_type_loc.getInnerLoc();
65 } else if (auto attr_type_loc =
66 type_loc.getAs<clang::AttributedTypeLoc>()) {
67 attrs.push_back(attr_type_loc.getAttr());
68 type_loc = attr_type_loc.getModifiedLoc();
69 } else {
70 // The last attribute in a chain of attributes will appear as the
71 // outermost AttributedType, e.g. `int $a $b` will be represented as
72 // follows (in pseudocode):
73 //
74 // AttributedType(annotate_type("lifetime", "b"),
75 // AttributedType(annotate_type("lifetime", "a"),
76 // BuiltinType("int")
77 // )
78 // )
79 //
80 // We reverse the attributes so that we obtain the more intuitive ordering
81 // "a, b".
82 std::reverse(attrs.begin(), attrs.end());
83 return type_loc;
84 }
85 }
86}
87
Martin Brænne8bc2de32022-06-24 07:01:52 -070088llvm::Expected<llvm::SmallVector<const clang::Expr*>> GetAttributeLifetimes(
Martin Brænne9fb786f2022-06-23 01:18:19 -070089 llvm::ArrayRef<const clang::Attr*> attrs) {
90 llvm::SmallVector<const clang::Expr*> result;
91
Martin Brænne8bc2de32022-06-24 07:01:52 -070092 bool saw_annotate_type = false;
93
Martin Brænne9fb786f2022-06-23 01:18:19 -070094 for (const clang::Attr* attr : attrs) {
95 auto annotate_type_attr = clang::dyn_cast<clang::AnnotateTypeAttr>(attr);
96 if (!annotate_type_attr ||
97 annotate_type_attr->getAnnotation() != "lifetime")
98 continue;
99
Martin Brænne8bc2de32022-06-24 07:01:52 -0700100 if (saw_annotate_type) {
Martin Brænne198ff492023-04-05 01:41:25 -0700101 return llvm::make_error<LifetimeError>(
102 LifetimeError::Type::Other,
Martin Brænne8bc2de32022-06-24 07:01:52 -0700103 "Only one `[[annotate_type(\"lifetime\", ...)]]` attribute may be "
104 "placed on a type");
105 }
106 saw_annotate_type = true;
107
Martin Brænne9fb786f2022-06-23 01:18:19 -0700108 for (const clang::Expr* arg : annotate_type_attr->args()) {
109 result.push_back(arg);
110 }
111 }
112
113 return result;
114}
115
Googler247cef72022-03-02 15:13:38 +0000116llvm::SmallVector<std::string> GetLifetimeParameters(clang::QualType type) {
117 // TODO(mboehme):
118 // - Add support for type aliases with lifetime parameters
119 // - Report errors as Clang diagnostics, not through
120 // llvm::report_fatal_error().
121
122 auto record = type->getAs<clang::RecordType>();
123 if (!record) {
124 return {};
125 }
126
127 auto cxx_record = record->getAsCXXRecordDecl();
128 if (!cxx_record) {
129 return {};
130 }
Googler17a2d512022-02-23 12:09:43 +0000131
Luca Versarid101a292022-01-27 17:28:42 +0000132 const clang::AnnotateAttr* lifetime_params_attr = nullptr;
133 for (auto annotate : cxx_record->specific_attrs<clang::AnnotateAttr>()) {
Googler17a2d512022-02-23 12:09:43 +0000134 if (annotate->getAnnotation() == "lifetime_params") {
Luca Versarid101a292022-01-27 17:28:42 +0000135 if (lifetime_params_attr) {
136 llvm::report_fatal_error("repeated lifetime annotation");
137 }
138 lifetime_params_attr = annotate;
139 }
140 }
Luca Versarid101a292022-01-27 17:28:42 +0000141
Luca Versarid101a292022-01-27 17:28:42 +0000142 llvm::SmallVector<std::string> ret;
Martin Brænnecf5d8972022-04-25 23:27:52 -0700143
144 // TODO(mboehme): Require derived class to explicitly declare all lifetime
145 // parameters inherited from the base class.
146 if (cxx_record->hasDefinition()) {
147 for (const clang::CXXBaseSpecifier& base : cxx_record->bases()) {
148 if (lifetime_params_attr) {
149 llvm::report_fatal_error(
150 "derived classes may not add lifetime parameters");
151 }
152 if (!ret.empty()) {
153 llvm::report_fatal_error(
154 "only one base class may have lifetime parameters");
155 }
156 ret = GetLifetimeParameters(base.getType());
157 }
158 }
159
160 if (!lifetime_params_attr) {
161 return ret;
162 }
163
Googler17a2d512022-02-23 12:09:43 +0000164 for (const auto& arg : lifetime_params_attr->args()) {
165 llvm::StringRef lifetime;
166 if (llvm::Error err =
167 EvaluateAsStringLiteral(arg, cxx_record->getASTContext())
168 .moveInto(lifetime)) {
169 llvm::report_fatal_error(llvm::StringRef(toString(std::move(err))));
Luca Versarid101a292022-01-27 17:28:42 +0000170 }
Googler17a2d512022-02-23 12:09:43 +0000171 ret.push_back(lifetime.str());
Luca Versarid101a292022-01-27 17:28:42 +0000172 }
173
174 return ret;
175}
176
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700177ValueLifetimes::ValueLifetimes(const ValueLifetimes& other) { *this = other; }
178
Googlerc071e242021-12-16 15:23:41 +0000179ValueLifetimes& ValueLifetimes::operator=(const ValueLifetimes& other) {
Googler41f3e352021-12-16 15:24:21 +0000180 type_ = other.type_;
Googlerc071e242021-12-16 15:23:41 +0000181 template_argument_lifetimes_ = other.template_argument_lifetimes_;
Luca Versarid101a292022-01-27 17:28:42 +0000182 lifetime_parameters_by_name_ = other.lifetime_parameters_by_name_;
Devin Jeanpierre108e9c02022-06-02 07:10:09 -0700183 auto pointee_lifetimes =
Googlerc071e242021-12-16 15:23:41 +0000184 other.pointee_lifetimes_
185 ? std::make_unique<ObjectLifetimes>(*other.pointee_lifetimes_)
186 : nullptr;
Devin Jeanpierre108e9c02022-06-02 07:10:09 -0700187 auto function_lifetimes =
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700188 other.function_lifetimes_
189 ? std::make_unique<FunctionLifetimes>(*other.function_lifetimes_)
190 : nullptr;
Devin Jeanpierre108e9c02022-06-02 07:10:09 -0700191 // Note: because ValueLifetimes is a recursive type (pointee_lifetimes_
192 // contains a ValueLifetimes), the following line can destroy `other`.
193 // (Thus the temporary local variables before we perform the assignment.)
194 pointee_lifetimes_ = std::move(pointee_lifetimes);
195 function_lifetimes_ = std::move(function_lifetimes);
Googlerc071e242021-12-16 15:23:41 +0000196 return *this;
197}
198
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700199// Defined here because FunctionLifetimes is an incomplete type in the header.
200ValueLifetimes::~ValueLifetimes() = default;
201
Luca Versariaf14c372022-04-04 07:30:24 -0700202namespace {
203
204llvm::Error ForEachTemplateArgument(
Martin Brænne712b7f42022-06-23 00:55:17 -0700205 clang::QualType type, clang::TypeLoc type_loc,
206 const std::function<llvm::Error(int, clang::QualType, clang::TypeLoc)>&
207 callback) {
Luca Versariaf14c372022-04-04 07:30:24 -0700208 llvm::SmallVector<llvm::ArrayRef<clang::TemplateArgument>> template_args =
209 GetTemplateArgs(type);
Martin Brænne712b7f42022-06-23 00:55:17 -0700210 std::optional<llvm::SmallVector<llvm::SmallVector<clang::TypeLoc>>>
211 maybe_template_arg_locs;
212 if (type_loc) {
213 maybe_template_arg_locs = GetTemplateArgs(type_loc);
214 }
215 llvm::SmallVector<llvm::SmallVector<clang::TypeLoc>> template_arg_locs;
216 if (maybe_template_arg_locs) {
217 template_arg_locs = *std::move(maybe_template_arg_locs);
218 } else {
219 // Fill all of `template_arg_locs` with empty `TypeLoc`s so we don't need to
220 // make any case distinctions below.
221 template_arg_locs.resize(template_args.size());
222 for (size_t depth = 0; depth < template_args.size(); depth++) {
223 template_arg_locs[depth].resize(template_args[depth].size());
224 }
225 }
Martin Brænnec2f5e402023-03-31 05:26:27 -0700226 if (template_arg_locs.size() != template_args.size()) {
Jing Lue8358752023-12-12 07:32:41 -0800227 llvm::report_fatal_error(llvm::StringRef(
228 absl::StrCat("In ForEachTemplateArgument(", type.getAsString(),
229 "), template_args_locs has ", template_arg_locs.size(),
230 " entries and template_args has ", template_args.size(),
231 " entries, but they should be equal")));
Martin Brænnec2f5e402023-03-31 05:26:27 -0700232 }
Martin Brænne712b7f42022-06-23 00:55:17 -0700233 for (int depth = 0; depth < template_args.size(); depth++) {
Luca Versariaf14c372022-04-04 07:30:24 -0700234 const auto& args_at_depth = template_args[depth];
Martin Brænne712b7f42022-06-23 00:55:17 -0700235 const auto& arg_locs_at_depth = template_arg_locs[depth];
236 assert(args_at_depth.size() == arg_locs_at_depth.size());
237 for (size_t i = 0; i < args_at_depth.size(); ++i) {
238 const clang::TemplateArgument& arg = args_at_depth[i];
Luca Versariaf14c372022-04-04 07:30:24 -0700239 if (arg.getKind() == clang::TemplateArgument::Type) {
Martin Brænne712b7f42022-06-23 00:55:17 -0700240 if (llvm::Error err =
241 callback(depth, arg.getAsType(), arg_locs_at_depth[i])) {
Luca Versariaf14c372022-04-04 07:30:24 -0700242 return err;
243 }
244 } else if (arg.getKind() == clang::TemplateArgument::Pack) {
245 for (const clang::TemplateArgument& inner_arg : arg.getPackAsArray()) {
246 if (inner_arg.getKind() == clang::TemplateArgument::Type) {
Martin Brænne33f4f502022-06-27 01:15:15 -0700247 // We pass `TypeLoc()` here because if the argument is a parameter
248 // pack, the only thing spelled out in the source code is that
249 // parameter pack -- there is no source location for the individual
250 // arguments contained in the pack.
Martin Brænne712b7f42022-06-23 00:55:17 -0700251 if (llvm::Error err =
252 callback(depth, inner_arg.getAsType(), clang::TypeLoc())) {
Luca Versariaf14c372022-04-04 07:30:24 -0700253 return err;
254 }
255 }
256 }
Martin Brænne16d86dd2022-04-08 00:33:36 -0700257 } else {
Martin Brænne712b7f42022-06-23 00:55:17 -0700258 if (llvm::Error err =
259 callback(depth, clang::QualType(), clang::TypeLoc())) {
Martin Brænne16d86dd2022-04-08 00:33:36 -0700260 return err;
261 }
Luca Versariaf14c372022-04-04 07:30:24 -0700262 }
263 }
264 }
265 return llvm::Error::success();
266}
267
Martin Brænne712b7f42022-06-23 00:55:17 -0700268QualType Undecay(clang::QualType type) {
269 if (auto decayed = type->getAs<clang::DecayedType>()) {
270 return decayed->getOriginalType();
271 }
272 return type;
273}
274
275bool SameType(clang::QualType type1, clang::QualType type2) {
276 // If both types are an AutoType, ignore the actual type and assume they're
277 // the same.
278 // An `AutoType` that came from a TypeLoc will have type `auto` (i.e. as
279 // written), whereas an `AutoType` that didn't come from a `TypeLoc` will be
280 // the actual deduced type. We still want these to compare equal though.
281 if (type1->getAs<clang::AutoType>() && type2->getAs<clang::AutoType>()) {
282 return true;
283 }
284 return Undecay(type1) == Undecay(type2);
285}
286
Luca Versariaf14c372022-04-04 07:30:24 -0700287} // namespace
288
Luca Versari91a56ff2022-08-22 01:58:33 -0700289ValueLifetimes ValueLifetimes::PointerTo(const clang::QualType pointer_type,
290 const ObjectLifetimes& obj) {
291 ValueLifetimes ret;
292 ret.type_ = pointer_type;
293 assert(pointer_type->getPointeeType().getCanonicalType() ==
294 obj.Type().getCanonicalType());
295 ret.pointee_lifetimes_ = std::make_unique<ObjectLifetimes>(obj);
296 return ret;
297}
298
Luca Versari95ce68f2022-03-24 14:44:19 +0000299llvm::Expected<ValueLifetimes> ValueLifetimes::Create(
Martin Brænne712b7f42022-06-23 00:55:17 -0700300 clang::QualType type, clang::TypeLoc type_loc,
301 LifetimeFactory lifetime_factory) {
Googlerc071e242021-12-16 15:23:41 +0000302 assert(!type.isNull());
Martin Brænne712b7f42022-06-23 00:55:17 -0700303 if (type_loc) {
304 assert(SameType(type_loc.getType(), type));
305 }
306
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700307 type = type.IgnoreParens();
Martin Brænne9fb786f2022-06-23 01:18:19 -0700308
309 type = StripAttributes(type);
310 llvm::SmallVector<const clang::Attr*> attrs;
311 if (!type_loc.isNull()) {
312 type_loc = StripAttributes(type_loc, attrs);
313 }
Martin Brænne8bc2de32022-06-24 07:01:52 -0700314 llvm::SmallVector<const clang::Expr*> lifetime_names;
315 if (llvm::Error err = GetAttributeLifetimes(attrs).moveInto(lifetime_names)) {
316 return std::move(err);
317 }
Martin Brænne9fb786f2022-06-23 01:18:19 -0700318
Googler6a06dbc2021-12-16 15:25:02 +0000319 ValueLifetimes ret(type);
Googlerc071e242021-12-16 15:23:41 +0000320
Martin Brænnefd2d10f2023-07-10 04:00:55 -0700321 if (const auto* fn = type->getAs<clang::FunctionProtoType>()) {
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700322 // TODO(veluca): this will not correctly handle the distinction between
323 // parameter and return lifetimes.
324 FunctionLifetimeFactorySingleCallback factory(lifetime_factory);
325 FunctionLifetimes fn_lftm;
Martin Brænne712b7f42022-06-23 00:55:17 -0700326 if (llvm::Error err =
327 FunctionLifetimes::CreateForFunctionType(fn, type_loc, factory)
328 .moveInto(fn_lftm)) {
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700329 return std::move(err);
330 }
331 ret.function_lifetimes_ =
332 std::make_unique<FunctionLifetimes>(std::move(fn_lftm));
333 return ret;
334 }
335
Martin Brænne9fb786f2022-06-23 01:18:19 -0700336 llvm::SmallVector<std::string> lifetime_params = GetLifetimeParameters(type);
337 if (!lifetime_params.empty() && !lifetime_names.empty() &&
338 lifetime_names.size() != lifetime_params.size()) {
Martin Brænne198ff492023-04-05 01:41:25 -0700339 return llvm::make_error<LifetimeError>(
340 LifetimeError::Type::Other,
Martin Brænne9fb786f2022-06-23 01:18:19 -0700341 absl::StrCat("Type has ", lifetime_params.size(),
342 " lifetime parameters but ", lifetime_names.size(),
343 " lifetime arguments were given"));
344 }
345 for (size_t i = 0; i < lifetime_params.size(); ++i) {
Luca Versari95ce68f2022-03-24 14:44:19 +0000346 Lifetime l;
Martin Brænne9fb786f2022-06-23 01:18:19 -0700347 const clang::Expr* lifetime_name = nullptr;
348 if (i < lifetime_names.size()) {
349 lifetime_name = lifetime_names[i];
350 }
351 if (llvm::Error err = lifetime_factory(lifetime_name).moveInto(l)) {
Luca Versari95ce68f2022-03-24 14:44:19 +0000352 return std::move(err);
Luca Versarid101a292022-01-27 17:28:42 +0000353 }
Martin Brænne9fb786f2022-06-23 01:18:19 -0700354 ret.lifetime_parameters_by_name_.Add(lifetime_params[i], l);
Luca Versarid101a292022-01-27 17:28:42 +0000355 }
356
Luca Versari95ce68f2022-03-24 14:44:19 +0000357 // Add implicit lifetime parameters for type template parameters.
Luca Versariaf14c372022-04-04 07:30:24 -0700358 if (llvm::Error err = ForEachTemplateArgument(
Martin Brænne712b7f42022-06-23 00:55:17 -0700359 type, type_loc,
360 [&ret, &lifetime_factory](
361 int depth, clang::QualType arg_type,
362 clang::TypeLoc arg_type_loc) -> llvm::Error {
Martin Brænne16d86dd2022-04-08 00:33:36 -0700363 std::optional<ValueLifetimes> maybe_template_arg_lifetime;
364 if (!arg_type.isNull()) {
365 maybe_template_arg_lifetime.emplace();
366 if (llvm::Error err =
Martin Brænne712b7f42022-06-23 00:55:17 -0700367 ValueLifetimes::Create(arg_type, arg_type_loc,
368 lifetime_factory)
Martin Brænne16d86dd2022-04-08 00:33:36 -0700369 .moveInto(*maybe_template_arg_lifetime)) {
370 return err;
371 }
Luca Versari95ce68f2022-03-24 14:44:19 +0000372 }
Luca Versariaf14c372022-04-04 07:30:24 -0700373 if (ret.template_argument_lifetimes_.size() <= depth) {
374 ret.template_argument_lifetimes_.resize(depth + 1);
375 }
376 ret.template_argument_lifetimes_[depth].push_back(
Martin Brænne16d86dd2022-04-08 00:33:36 -0700377 maybe_template_arg_lifetime);
Luca Versariaf14c372022-04-04 07:30:24 -0700378 return llvm::Error::success();
379 })) {
380 return std::move(err);
Googlerc071e242021-12-16 15:23:41 +0000381 }
382
Luca Versari95ce68f2022-03-24 14:44:19 +0000383 clang::QualType pointee = PointeeType(type);
Martin Brænneafad7ca2023-03-30 06:29:31 -0700384 if (pointee.isNull() || type->isFunctionPointerType() ||
385 type->isFunctionReferenceType()) {
Martin Brænne2c6f94b2023-03-29 05:24:56 -0700386 if (lifetime_params.empty() && !lifetime_names.empty())
Martin Brænne198ff492023-04-05 01:41:25 -0700387 return llvm::make_error<LifetimeError>(
388 LifetimeError::Type::Other,
Martin Brænne2c6f94b2023-03-29 05:24:56 -0700389 absl::StrCat("Type may not be annotated with lifetimes"));
Martin Brænneafad7ca2023-03-30 06:29:31 -0700390 }
391 if (pointee.isNull()) {
Martin Brænne2c6f94b2023-03-29 05:24:56 -0700392 return ret;
393 }
Martin Brænne712b7f42022-06-23 00:55:17 -0700394
395 clang::TypeLoc pointee_type_loc;
396 if (type_loc) {
397 pointee_type_loc = PointeeTypeLoc(type_loc);
398 // Note: We can't assert that `pointee_type_loc` is non-null here. If
399 // `type_loc` is a `TypedefTypeLoc`, then there will be no `TypeLoc` for
400 // the pointee type because the pointee type never got spelled out at the
401 // location of the original `TypeLoc`.
402 }
403
404 ValueLifetimes value_lifetimes;
405 if (llvm::Error err =
406 ValueLifetimes::Create(pointee, pointee_type_loc, lifetime_factory)
407 .moveInto(value_lifetimes)) {
408 return std::move(err);
409 }
410
411 Lifetime object_lifetime;
Martin Brænneafad7ca2023-03-30 06:29:31 -0700412 if (type->isFunctionPointerType() || type->isFunctionReferenceType()) {
413 // Function pointers and function references may not be annotated with a
414 // lifetime. Instead, it is always implied that they have static lifetime.
415 object_lifetime = Lifetime::Static();
416 } else {
417 const clang::Expr* lifetime_name = nullptr;
418 if (!lifetime_names.empty()) {
419 if (lifetime_names.size() != 1) {
Martin Brænne198ff492023-04-05 01:41:25 -0700420 return llvm::make_error<LifetimeError>(
421 LifetimeError::Type::Other,
Martin Brænneafad7ca2023-03-30 06:29:31 -0700422 absl::StrCat("Expected a single lifetime but ",
423 lifetime_names.size(), " were given"));
424 }
425 lifetime_name = lifetime_names.front();
Martin Brænne9fb786f2022-06-23 01:18:19 -0700426 }
Martin Brænneafad7ca2023-03-30 06:29:31 -0700427 if (llvm::Error err =
428 lifetime_factory(lifetime_name).moveInto(object_lifetime)) {
429 return std::move(err);
430 }
Googlerc071e242021-12-16 15:23:41 +0000431 }
Luca Versari95ce68f2022-03-24 14:44:19 +0000432 ret.pointee_lifetimes_ =
Martin Brænne712b7f42022-06-23 00:55:17 -0700433 std::make_unique<ObjectLifetimes>(object_lifetime, value_lifetimes);
Googlerc071e242021-12-16 15:23:41 +0000434 return ret;
435}
436
Googler705f9452021-12-16 15:30:08 +0000437ValueLifetimes ValueLifetimes::ForLifetimeLessType(clang::QualType type) {
Googlerfc1b55c2022-03-04 13:03:46 +0000438 assert(PointeeType(type).isNull() && !type->isRecordType());
Googler705f9452021-12-16 15:30:08 +0000439 return ValueLifetimes(type);
440}
441
442ValueLifetimes ValueLifetimes::ForPointerLikeType(
443 clang::QualType type, const ObjectLifetimes& object_lifetimes) {
Googlerfc1b55c2022-03-04 13:03:46 +0000444 assert(!PointeeType(type).isNull());
Googler705f9452021-12-16 15:30:08 +0000445 ValueLifetimes result(type);
446 result.pointee_lifetimes_ =
447 std::make_unique<ObjectLifetimes>(object_lifetimes);
448 return result;
449}
450
451ValueLifetimes ValueLifetimes::ForRecord(
452 clang::QualType type,
Googlere4d4ec42022-03-28 06:52:23 -0700453 std::vector<std::vector<std::optional<ValueLifetimes>>>
454 template_argument_lifetimes,
Luca Versarid101a292022-01-27 17:28:42 +0000455 LifetimeSymbolTable lifetime_parameters) {
Googler705f9452021-12-16 15:30:08 +0000456 assert(type->isRecordType());
457 assert(GetTemplateArgs(type).size() == template_argument_lifetimes.size());
Googlere4d4ec42022-03-28 06:52:23 -0700458 for (size_t depth = 0; depth < template_argument_lifetimes.size(); ++depth) {
459 assert(GetTemplateArgs(type)[depth].size() ==
460 template_argument_lifetimes[depth].size());
461 }
Googler705f9452021-12-16 15:30:08 +0000462 ValueLifetimes result(type);
463 result.template_argument_lifetimes_ = std::move(template_argument_lifetimes);
Luca Versarid101a292022-01-27 17:28:42 +0000464 result.lifetime_parameters_by_name_ = lifetime_parameters;
Googler705f9452021-12-16 15:30:08 +0000465 return result;
466}
467
Luca Versari95ce68f2022-03-24 14:44:19 +0000468std::string ValueLifetimes::DebugString(
469 const LifetimeFormatter& formatter) const {
Martin Brænneafad7ca2023-03-30 06:29:31 -0700470 if (Type()->isFunctionPointerType() || Type()->isFunctionReferenceType()) {
471 // Function pointers and function references have an implied static
472 // lifetime. This is never annotated, so don't print it either.
473 // Note: If at some point we decide we want to distinguish between regular
474 // pointers (to objects) and function pointers in more places, we could
475 // consider adding a `function_pointee_lifetimes_` in addition to
476 // `pointee_lifetimes_`.
477 assert(pointee_lifetimes_->GetLifetime() == Lifetime::Static());
478 return pointee_lifetimes_->GetValueLifetimes().DebugString(formatter);
479 }
Luca Versari6ee6b342022-04-05 05:40:52 -0700480 if (!PointeeType(Type()).isNull()) {
481 assert(pointee_lifetimes_);
482 return pointee_lifetimes_->DebugString(formatter);
Luca Versari95ce68f2022-03-24 14:44:19 +0000483 }
Martin Brænnefd2d10f2023-07-10 04:00:55 -0700484 if (Type()->getAs<clang::FunctionProtoType>()) {
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700485 assert(function_lifetimes_);
486 std::string fn_lifetimes = function_lifetimes_->DebugString(formatter);
487 if (fn_lifetimes.empty()) return "";
488 return absl::StrCat("(", fn_lifetimes, ")");
489 }
Luca Versari6ee6b342022-04-05 05:40:52 -0700490
491 std::vector<std::vector<std::string>> tmpl_lifetimes;
492 for (auto& tmpl_arg_at_depth : template_argument_lifetimes_) {
493 tmpl_lifetimes.emplace_back();
494 for (const std::optional<ValueLifetimes>& tmpl_arg : tmpl_arg_at_depth) {
495 if (tmpl_arg) {
496 std::string inner = tmpl_arg->DebugString(formatter);
497 if (!inner.empty()) {
498 tmpl_lifetimes.back().push_back(std::move(inner));
499 }
500 }
501 }
502 }
503 std::vector<std::string> lifetime_parameters;
504 for (const auto& lftm_arg : GetLifetimeParameters(type_)) {
505 std::optional<Lifetime> lifetime =
506 lifetime_parameters_by_name_.LookupName(lftm_arg);
507 assert(lifetime.has_value());
508 lifetime_parameters.push_back(formatter(*lifetime));
509 }
510 bool empty_tmpl_lifetimes = true;
511 for (const auto& tmpl_arg_at_depth : tmpl_lifetimes) {
512 for (const auto& tmpl : tmpl_arg_at_depth) {
513 empty_tmpl_lifetimes &= tmpl.empty();
514 }
515 }
516 if (empty_tmpl_lifetimes && lifetime_parameters.empty()) {
517 return "";
518 } else if (empty_tmpl_lifetimes) {
519 if (lifetime_parameters.size() == 1) {
520 return lifetime_parameters[0];
521 }
522 return absl::StrCat("[", absl::StrJoin(lifetime_parameters, ", "), "]");
523 } else if (lifetime_parameters.empty() && tmpl_lifetimes.size() == 1 &&
524 tmpl_lifetimes[0].size() == 1) {
525 return tmpl_lifetimes[0][0];
526 }
527
528 std::vector<std::string> tmpl_lifetimes_per_depth;
529 tmpl_lifetimes_per_depth.reserve(tmpl_lifetimes.size());
530 for (const auto& tmpl_depth : tmpl_lifetimes) {
531 tmpl_lifetimes_per_depth.push_back(
532 absl::StrCat("<", absl::StrJoin(tmpl_depth, ", "), ">"));
533 }
534 std::string lifetime_parameter_string;
535 if (!lifetime_parameters.empty()) {
536 lifetime_parameter_string =
537 absl::StrCat(" [", absl::StrJoin(lifetime_parameters, ", "), "]");
538 }
539
540 return absl::StrCat(absl::StrJoin(tmpl_lifetimes_per_depth, "::"),
541 lifetime_parameter_string);
Luca Versari95ce68f2022-03-24 14:44:19 +0000542}
543
Googler41f3e352021-12-16 15:24:21 +0000544const ObjectLifetimes& ValueLifetimes::GetPointeeLifetimes() const {
Googlerfc1b55c2022-03-04 13:03:46 +0000545 assert(!PointeeType(type_).isNull());
Martin Brænnefd2d10f2023-07-10 04:00:55 -0700546 assert(pointee_lifetimes_);
Googler41f3e352021-12-16 15:24:21 +0000547 return *pointee_lifetimes_;
548}
549
Luca Versari50824882023-01-23 05:51:35 -0800550const FunctionLifetimes& ValueLifetimes::GetFuncLifetimes() const {
551 assert(clang::isa<clang::FunctionProtoType>(type_));
Martin Brænne83bda992023-07-10 12:03:12 -0700552 assert(function_lifetimes_);
Luca Versari50824882023-01-23 05:51:35 -0800553 return *function_lifetimes_;
554}
555
Luca Versari043a36e2022-04-08 00:55:36 -0700556bool ValueLifetimes::HasAny(
557 const std::function<bool(Lifetime)>& predicate) const {
558 for (const auto& tmpl_arg_at_depth : template_argument_lifetimes_) {
559 for (const std::optional<ValueLifetimes>& tmpl_arg : tmpl_arg_at_depth) {
560 if (tmpl_arg && tmpl_arg->HasAny(predicate)) {
561 return true;
562 }
563 }
564 }
565 if (pointee_lifetimes_ && pointee_lifetimes_->HasAny(predicate)) {
566 return true;
567 }
568 for (const auto& lftm_arg : GetLifetimeParameters(type_)) {
569 std::optional<Lifetime> lifetime =
570 lifetime_parameters_by_name_.LookupName(lftm_arg);
571 assert(lifetime.has_value());
572 if (predicate(lifetime.value())) {
573 return true;
574 }
575 }
576 if (function_lifetimes_ && function_lifetimes_->HasAny(predicate)) {
577 return true;
578 }
579 return false;
580}
581
Luca Versaric5231632022-04-11 07:36:35 -0700582void ValueLifetimes::SubstituteLifetimes(const LifetimeSubstitutions& subst) {
583 for (auto& tmpl_arg_at_depth : template_argument_lifetimes_) {
584 for (std::optional<ValueLifetimes>& tmpl_arg : tmpl_arg_at_depth) {
585 if (tmpl_arg) {
586 tmpl_arg->SubstituteLifetimes(subst);
587 }
588 }
589 }
590 if (pointee_lifetimes_) {
591 pointee_lifetimes_->SubstituteLifetimes(subst);
592 }
593 for (const auto& lftm_arg : GetLifetimeParameters(type_)) {
594 std::optional<Lifetime> lifetime =
595 lifetime_parameters_by_name_.LookupName(lftm_arg);
596 assert(lifetime.has_value());
597 lifetime_parameters_by_name_.Rebind(lftm_arg, subst.Substitute(*lifetime));
598 }
599 if (function_lifetimes_) {
600 function_lifetimes_->SubstituteLifetimes(subst);
601 }
602}
603
Luca Versari95ce68f2022-03-24 14:44:19 +0000604void ValueLifetimes::Traverse(std::function<void(Lifetime&, Variance)> visitor,
605 Variance variance) {
Googlere4d4ec42022-03-28 06:52:23 -0700606 for (auto& tmpl_arg_at_depth : template_argument_lifetimes_) {
607 for (std::optional<ValueLifetimes>& tmpl_arg : tmpl_arg_at_depth) {
608 if (tmpl_arg) {
609 tmpl_arg->Traverse(visitor, kInvariant);
610 }
Luca Versari95ce68f2022-03-24 14:44:19 +0000611 }
612 }
613 if (pointee_lifetimes_) {
614 pointee_lifetimes_->Traverse(visitor, variance, Type());
615 }
616 for (const auto& lftm_arg : GetLifetimeParameters(type_)) {
617 std::optional<Lifetime> lifetime =
618 lifetime_parameters_by_name_.LookupName(lftm_arg);
619 assert(lifetime.has_value());
620 Lifetime new_lifetime = *lifetime;
621 visitor(new_lifetime, variance);
622
623 // Note that this check is not an optimization, but a guard against UB:
624 // if one calls the const version of Traverse, with a callback that does not
625 // mutate the lifetime, on a const instance of the Value/ObjectLifetimes,
626 // then calling Rebind would be UB, even if Rebind would do nothing in
627 // practice.
628 if (new_lifetime != lifetime) {
629 lifetime_parameters_by_name_.Rebind(lftm_arg, new_lifetime);
630 }
631 }
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700632 if (function_lifetimes_) {
633 function_lifetimes_->Traverse(visitor);
634 }
Googlerace85a22021-11-26 14:18:31 +0000635}
636
Luca Versari95ce68f2022-03-24 14:44:19 +0000637void ValueLifetimes::Traverse(
638 std::function<void(const Lifetime&, Variance)> visitor,
639 Variance variance) const {
640 const_cast<ValueLifetimes*>(this)->Traverse(
641 [&visitor](Lifetime& l, Variance v) { visitor(l, v); }, variance);
Googlerace85a22021-11-26 14:18:31 +0000642}
643
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700644ValueLifetimes::ValueLifetimes(clang::QualType type) : type_(type) {}
645
Dmitri Gribenkoa087d232023-07-10 08:03:46 -0700646llvm::SmallVector<llvm::ArrayRef<clang::TemplateArgument>> GetTemplateArgs(
647 clang::QualType type) {
Googlere4d4ec42022-03-28 06:52:23 -0700648 llvm::SmallVector<llvm::ArrayRef<clang::TemplateArgument>> result;
649
Martin Brænne5cc52fc2022-04-20 05:42:30 -0700650 // Desugar any typedefs on `type`. We need to do this so that the "depth" of
651 // the template arguments is compatible with
652 // TemplateTypeParmType::getDepth(), which likewise assumes that typedefs are
653 // desugared; see the call to getCanonicalTypeInternal() in
654 // TemplateTypeParmType::getCanTTPTInfo(). Unlike that function, we can't
655 // simply canonicalize the type, as that would also remove type annotations,
656 // and we need those.
657 while (const auto* typedef_type = type->getAs<clang::TypedefType>()) {
658 type = typedef_type->desugar();
659 }
660
Googlere4d4ec42022-03-28 06:52:23 -0700661 if (auto elaborated = type->getAs<clang::ElaboratedType>()) {
662 if (clang::NestedNameSpecifier* qualifier = elaborated->getQualifier()) {
663 if (const clang::Type* qualifier_type = qualifier->getAsType()) {
664 result = GetTemplateArgs(clang::QualType(qualifier_type, 0));
665 }
666 }
Googlerace85a22021-11-26 14:18:31 +0000667 }
Googlere4d4ec42022-03-28 06:52:23 -0700668
669 if (auto specialization = type->getAs<clang::TemplateSpecializationType>()) {
670 result.push_back(specialization->template_arguments());
671 } else if (auto record = type->getAs<clang::RecordType>()) {
Googlerace85a22021-11-26 14:18:31 +0000672 if (auto specialization_decl =
673 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(
674 record->getDecl())) {
Googlere4d4ec42022-03-28 06:52:23 -0700675 result.push_back(specialization_decl->getTemplateArgs().asArray());
Googlerace85a22021-11-26 14:18:31 +0000676 }
677 }
Googlere4d4ec42022-03-28 06:52:23 -0700678
679 return result;
Googlerace85a22021-11-26 14:18:31 +0000680}
681
Martin Brænne46409332022-06-23 00:45:49 -0700682std::optional<llvm::SmallVector<llvm::SmallVector<clang::TypeLoc>>>
Fangrui Songaff93e42024-05-15 13:48:34 -0700683GetTemplateArgs(llvm::ArrayRef<clang::TemplateArgumentLoc> template_arg_locs) {
684 llvm::SmallVector<llvm::SmallVector<clang::TypeLoc>> args;
685 args.push_back({});
686 for (const auto &loc: template_arg_locs) {
687 if (auto* source_info = loc.getTypeSourceInfo()) {
688 args.back().push_back(source_info->getTypeLoc());
689 } else {
690 args.back().push_back(clang::TypeLoc());
691 }
692 }
693 return args;
694}
695
696std::optional<llvm::SmallVector<llvm::SmallVector<clang::TypeLoc>>>
Martin Brænne46409332022-06-23 00:45:49 -0700697GetTemplateArgs(clang::TypeLoc type_loc) {
698 assert(type_loc);
699
700 type_loc = type_loc.getUnqualifiedLoc();
701
702 // We can't get template arguments from a `SubstTemplateTypeParmTypeLoc`
703 // because there is no `TypeLoc` for the type that replaces the template
Martin Brænnee1fa5192023-03-31 05:22:26 -0700704 // parameter.
705 if (type_loc.getAs<clang::SubstTemplateTypeParmTypeLoc>()) {
Martin Brænne46409332022-06-23 00:45:49 -0700706 assert(!type_loc.getNextTypeLoc());
707 return std::nullopt;
708 }
709
Martin Brænnee1fa5192023-03-31 05:22:26 -0700710 // Similarly, there is no `TypeLoc` for the type that a `TypedefType` resolves
711 // to. Note that we intentionally use Type::getAs<TypedefType>() instead of
712 // TypeLoc::getAs<TypedefTypeLoc>() here because the former will strip off any
713 // potential other layers of sugar to get to the `TypedefType`, and we want to
714 // be consistent with `GetTemplateArgs<QualType>`, which obviously uses
715 // `Type::getAs<TypedefType>()`, too.
716 if (type_loc.getType()->getAs<clang::TypedefType>() != nullptr) {
717 return std::nullopt;
718 }
719
Jing Lu1cec4a82023-12-12 09:28:25 -0800720 // Again, there is no `TypeLoc` for the type that a `DecltypeType` or
721 // `AutoType` refers to.
722 if (type_loc.getType()->getAs<clang::DecltypeType>() != nullptr ||
723 type_loc.getType()->getAs<clang::AutoType>() != nullptr) {
Jing Luc6c47e02023-12-12 09:07:02 -0800724 return std::nullopt;
725 }
726
Martin Brænne43be1282022-06-23 00:24:44 -0700727 llvm::SmallVector<llvm::SmallVector<clang::TypeLoc>> args;
728
729 if (auto elaborated_type_loc = type_loc.getAs<clang::ElaboratedTypeLoc>()) {
730 if (clang::NestedNameSpecifierLoc qualifier =
731 elaborated_type_loc.getQualifierLoc()) {
Martin Brænne46409332022-06-23 00:45:49 -0700732 if (qualifier.getTypeLoc()) {
733 if (auto qualifier_args = GetTemplateArgs(qualifier.getTypeLoc())) {
734 args = *qualifier_args;
735 } else {
736 return std::nullopt;
737 }
738 }
Martin Brænne43be1282022-06-23 00:24:44 -0700739 }
Martin Brænne46409332022-06-23 00:45:49 -0700740 if (auto elaborated_args =
741 GetTemplateArgs(elaborated_type_loc.getNamedTypeLoc())) {
742 args.append(*elaborated_args);
743 } else {
744 return std::nullopt;
745 }
Martin Brænne43be1282022-06-23 00:24:44 -0700746 } else if (auto template_specialization_type_loc =
747 type_loc.getAs<clang::TemplateSpecializationTypeLoc>()) {
748 args.push_back({});
749 for (unsigned i = 0; i < template_specialization_type_loc.getNumArgs();
750 ++i) {
Kinuko Yasuda74d5a3c2022-08-29 14:40:04 -0700751 if (auto* source_info = template_specialization_type_loc.getArgLoc(i)
752 .getTypeSourceInfo()) {
753 args.back().push_back(source_info->getTypeLoc());
754 } else {
755 args.back().push_back(clang::TypeLoc());
756 }
Martin Brænne43be1282022-06-23 00:24:44 -0700757 }
Martin Brænne46409332022-06-23 00:45:49 -0700758 } else if (auto record_type_loc = type_loc.getAs<clang::RecordTypeLoc>()) {
759 if (auto specialization_decl =
760 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(
761 record_type_loc.getDecl())) {
Fangrui Songaff93e42024-05-15 13:48:34 -0700762 if (specialization_decl->getTemplateArgsAsWritten()) {
Martin Brænne46409332022-06-23 00:45:49 -0700763 return GetTemplateArgs(
Fangrui Songaff93e42024-05-15 13:48:34 -0700764 specialization_decl->getTemplateArgsAsWritten()->arguments());
Martin Brænne46409332022-06-23 00:45:49 -0700765 }
766 return std::nullopt;
767 }
Martin Brænne43be1282022-06-23 00:24:44 -0700768 } else if (auto dependent_template_specialization_type_loc =
769 type_loc
770 .getAs<clang::DependentTemplateSpecializationTypeLoc>()) {
771 args.push_back({});
Martin Brænnefa6fc842022-06-23 00:25:43 -0700772 for (unsigned i = 0;
773 i < dependent_template_specialization_type_loc.getNumArgs(); ++i) {
774 args.back().push_back(
775 dependent_template_specialization_type_loc.getArgLoc(i)
776 .getTypeSourceInfo()
777 ->getTypeLoc());
778 }
Martin Brænne43be1282022-06-23 00:24:44 -0700779 // TODO(mboehme): Where does this occur exactly? Do we need to be handling
780 // it?
781 // AFAICT, this happens if we're looking at a dependent template name
782 // (https://en.cppreference.com/w/cpp/language/dependent_name), which
783 // probably means that this can only happen in template definitions (as
784 // opposed to template instantiations), and we aren't analyzing those for
785 // now. At the least, I haven't been able to trigger this case from a test.
786 // Triggering a fatal error here so that we notice this case if it does come
Martin Brænnefa6fc842022-06-23 00:25:43 -0700787 // up. We only trigger the fatal error _after_ we've done the processing
788 // above so that we don't get a warning about dead code.
Martin Brænne43be1282022-06-23 00:24:44 -0700789 llvm::report_fatal_error(
790 "Unexpectedly got a DependentSpecializationTypeLoc");
Martin Brænne43be1282022-06-23 00:24:44 -0700791 }
792
793 return args;
794}
795
Luca Versarid101a292022-01-27 17:28:42 +0000796ObjectLifetimes ObjectLifetimes::GetObjectLifetimesForTypeInContext(
797 clang::QualType type, llvm::SmallVector<std::string> type_lifetime_args,
798 llvm::StringRef object_lifetime_parameter) const {
Googler41f3e352021-12-16 15:24:21 +0000799 assert(value_lifetimes_.Type()->isRecordType());
Googlerace85a22021-11-26 14:18:31 +0000800
801 // The object of the `type` (i.e. field or a base class) basically has the
802 // same lifetime as the struct.
Googler705f9452021-12-16 15:30:08 +0000803 Lifetime ret_lifetime = lifetime_;
Luca Versarid101a292022-01-27 17:28:42 +0000804 // ... unless the field has lifetime parameters.
805 if (!object_lifetime_parameter.empty()) {
806 ret_lifetime =
807 value_lifetimes_.GetLifetimeParameter(object_lifetime_parameter);
808 }
Googlerace85a22021-11-26 14:18:31 +0000809
810 // `type` is one of a template argument, a struct, a pointer, or a type
811 // with no lifetimes (other than its own).
812
813 // First case: template argument. We just attach the
814 // template argument's lifetimes to the leaf ObjectLifetimes.
815 if (auto targ = type->getAs<clang::SubstTemplateTypeParmType>()) {
Googler59be2f92022-10-17 06:45:57 -0700816 const clang::TemplateTypeParmDecl* type_parm = targ->getReplacedParameter();
Googlerace85a22021-11-26 14:18:31 +0000817 const std::optional<ValueLifetimes>& arg_lifetimes =
Googlere4d4ec42022-03-28 06:52:23 -0700818 value_lifetimes_.GetTemplateArgumentLifetimes(type_parm->getDepth(),
819 type_parm->getIndex());
Googlerace85a22021-11-26 14:18:31 +0000820 if (!arg_lifetimes) {
821 assert(false);
Googler6a06dbc2021-12-16 15:25:02 +0000822 return llvm::DenseMapInfo<ObjectLifetimes>::getEmptyKey();
Googlerace85a22021-11-26 14:18:31 +0000823 }
Googler705f9452021-12-16 15:30:08 +0000824 return ObjectLifetimes(ret_lifetime, *arg_lifetimes);
Googlerf1009fd2023-05-03 06:29:04 -0700825 } else if (type->isRecordType()) {
Luca Versarid101a292022-01-27 17:28:42 +0000826 // Second case: struct.
827 // Resolve lifetime parameters for the struct, if it has any.
828 LifetimeSymbolTable lifetime_params;
Googler247cef72022-03-02 15:13:38 +0000829 llvm::SmallVector<std::string> params = GetLifetimeParameters(type);
Luca Versarid101a292022-01-27 17:28:42 +0000830 for (size_t i = params.size(); i-- > 0;) {
831 assert(!type_lifetime_args.empty());
832 auto lftm_arg = type_lifetime_args.back();
833 type_lifetime_args.pop_back();
834 lifetime_params.Add(params[i],
835 value_lifetimes_.GetLifetimeParameter(lftm_arg));
836 }
837
Googlerf1009fd2023-05-03 06:29:04 -0700838 // We need to construct potentially reshuffled
Googlerace85a22021-11-26 14:18:31 +0000839 // template arguments, if the struct is a template.
Luca Versarid101a292022-01-27 17:28:42 +0000840
841 // TODO(veluca): mixing lifetimes and template parameters is not supported
842 // yet.
Googlere4d4ec42022-03-28 06:52:23 -0700843 std::vector<std::vector<std::optional<ValueLifetimes>>>
844 template_argument_lifetimes;
845 for (const auto& args_at_depth : GetTemplateArgs(type)) {
846 size_t parameter_pack_expansion_index = 0;
847 template_argument_lifetimes.push_back({});
848 for (const clang::TemplateArgument& arg : args_at_depth) {
849 if (arg.getKind() == clang::TemplateArgument::Type) {
850 if (auto templ_arg =
851 clang::dyn_cast<clang::SubstTemplateTypeParmType>(
852 arg.getAsType())) {
Googler59be2f92022-10-17 06:45:57 -0700853 const clang::TemplateTypeParmDecl* type_parm =
Googlere4d4ec42022-03-28 06:52:23 -0700854 templ_arg->getReplacedParameter();
855 // Template parameter packs get the index of the *pack*, not the
856 // index of the type inside the pack itself. As they must appear
857 // last, we can just increase the counter at every occurrence and
858 // wraparound when we run out of template arguments.
859 size_t index = type_parm->getIndex();
860 if (type_parm->isParameterPack()) {
861 index += parameter_pack_expansion_index++;
862 if (index + 1 >= value_lifetimes_.GetNumTemplateArgumentsAtDepth(
863 type_parm->getDepth())) {
864 parameter_pack_expansion_index = 0;
865 }
Luca Versari29c00862022-01-21 20:53:06 +0000866 }
Googlere4d4ec42022-03-28 06:52:23 -0700867 template_argument_lifetimes.back().push_back(
868 value_lifetimes_.GetTemplateArgumentLifetimes(
869 type_parm->getDepth(), index));
870 } else {
871 // Create a new ValueLifetimes of the type of the template
872 // parameter, with lifetime `lifetime_`.
873 // TODO(veluca): we need to propagate lifetime parameters here.
874 template_argument_lifetimes.back().push_back(
Martin Brænne03d93302022-06-23 00:23:38 -0700875 ValueLifetimes::Create(
876 arg.getAsType(),
877 [this](const clang::Expr*) { return this->lifetime_; })
878 .get());
Luca Versari29c00862022-01-21 20:53:06 +0000879 }
Luca Versari162a4c52021-12-10 08:57:05 +0000880 } else {
Googlere4d4ec42022-03-28 06:52:23 -0700881 template_argument_lifetimes.back().push_back(std::nullopt);
Luca Versari162a4c52021-12-10 08:57:05 +0000882 }
Googlerace85a22021-11-26 14:18:31 +0000883 }
884 }
Luca Versarid101a292022-01-27 17:28:42 +0000885
886 return ObjectLifetimes(
887 ret_lifetime,
888 ValueLifetimes::ForRecord(type, std::move(template_argument_lifetimes),
889 std::move(lifetime_params)));
Googlerfc1b55c2022-03-04 13:03:46 +0000890 } else if (clang::QualType pointee_type = PointeeType(type);
891 !pointee_type.isNull()) {
Martin Brænne0656ebf2022-04-25 23:52:54 -0700892 if (type_lifetime_args.empty()) {
893 llvm::report_fatal_error(
894 llvm::Twine("didn't find type lifetimes for object of type " +
895 type.getAsString()));
Luca Versarid101a292022-01-27 17:28:42 +0000896 }
Martin Brænne0656ebf2022-04-25 23:52:54 -0700897 std::string pointee_object_lifetime_parameter =
898 std::move(type_lifetime_args.back());
899 type_lifetime_args.pop_back();
Googlerace85a22021-11-26 14:18:31 +0000900 // Third case: pointer.
Googler705f9452021-12-16 15:30:08 +0000901 return ObjectLifetimes(
Googlerfc1b55c2022-03-04 13:03:46 +0000902 ret_lifetime, ValueLifetimes::ForPointerLikeType(
903 type, GetObjectLifetimesForTypeInContext(
904 pointee_type, std::move(type_lifetime_args),
Martin Brænne0656ebf2022-04-25 23:52:54 -0700905 pointee_object_lifetime_parameter)));
Googlerace85a22021-11-26 14:18:31 +0000906 }
907
Googler705f9452021-12-16 15:30:08 +0000908 return ObjectLifetimes(ret_lifetime,
909 ValueLifetimes::ForLifetimeLessType(type));
Googlerace85a22021-11-26 14:18:31 +0000910}
911
Luca Versari95ce68f2022-03-24 14:44:19 +0000912std::string ObjectLifetimes::DebugString(
913 const LifetimeFormatter& formatter) const {
Luca Versari6ee6b342022-04-05 05:40:52 -0700914 std::string inner_lifetimes = value_lifetimes_.DebugString(formatter);
915 std::string lifetime = formatter(lifetime_);
916 if (inner_lifetimes.empty()) {
917 return lifetime;
Luca Versari95ce68f2022-03-24 14:44:19 +0000918 }
Luca Versari6ee6b342022-04-05 05:40:52 -0700919 return absl::StrCat(std::move(inner_lifetimes), ", ", std::move(lifetime));
Luca Versari95ce68f2022-03-24 14:44:19 +0000920}
921
Luca Versarid101a292022-01-27 17:28:42 +0000922ObjectLifetimes ObjectLifetimes::GetFieldOrBaseLifetimes(
923 clang::QualType type,
924 llvm::SmallVector<std::string> type_lifetime_args) const {
925 return GetObjectLifetimesForTypeInContext(type, std::move(type_lifetime_args),
926 "");
927}
928
Luca Versari043a36e2022-04-08 00:55:36 -0700929bool ObjectLifetimes::HasAny(
930 const std::function<bool(Lifetime)>& predicate) const {
931 return predicate(lifetime_) || value_lifetimes_.HasAny(predicate);
932}
933
Luca Versaric5231632022-04-11 07:36:35 -0700934void ObjectLifetimes::SubstituteLifetimes(const LifetimeSubstitutions& subst) {
935 lifetime_ = subst.Substitute(lifetime_);
936 value_lifetimes_.SubstituteLifetimes(subst);
937}
938
Luca Versari95ce68f2022-03-24 14:44:19 +0000939void ObjectLifetimes::Traverse(std::function<void(Lifetime&, Variance)> visitor,
940 Variance variance,
941 clang::QualType indirection_type) {
942 assert(indirection_type.isNull() ||
Martin Brænne9fb786f2022-06-23 01:18:19 -0700943 StripAttributes(indirection_type->getPointeeType().IgnoreParens()) ==
944 Type());
Luca Versari95ce68f2022-03-24 14:44:19 +0000945 value_lifetimes_.Traverse(
946 visitor, indirection_type.isNull() || indirection_type.isConstQualified()
947 ? kCovariant
948 : kInvariant);
949 visitor(lifetime_, variance);
950}
951
952void ObjectLifetimes::Traverse(
953 std::function<void(const Lifetime&, Variance)> visitor, Variance variance,
954 clang::QualType indirection_type) const {
955 const_cast<ObjectLifetimes*>(this)->Traverse(
956 [&visitor](Lifetime& l, Variance v) { visitor(l, v); }, variance,
957 indirection_type);
958}
959
Googler17a2d512022-02-23 12:09:43 +0000960llvm::Expected<llvm::StringRef> EvaluateAsStringLiteral(
961 const clang::Expr* expr, const clang::ASTContext& ast_context) {
962 auto error = []() {
Martin Brænne198ff492023-04-05 01:41:25 -0700963 return llvm::make_error<LifetimeError>(
964 LifetimeError::Type::Other,
Googler17a2d512022-02-23 12:09:43 +0000965 "cannot evaluate argument as a string literal");
966 };
967
968 clang::Expr::EvalResult eval_result;
969 if (!expr->EvaluateAsConstantExpr(eval_result, ast_context) ||
970 !eval_result.Val.isLValue()) {
971 return error();
972 }
973
974 const auto* eval_result_expr =
975 eval_result.Val.getLValueBase().dyn_cast<const clang::Expr*>();
976 if (!eval_result_expr) {
977 return error();
978 }
979
980 const auto* strlit = clang::dyn_cast<clang::StringLiteral>(eval_result_expr);
981 if (!strlit) {
982 return error();
983 }
984
985 return strlit->getString();
986}
987
Martin Brænne1a207c52022-04-19 00:05:38 -0700988} // namespace lifetimes
989} // namespace tidy
990} // namespace clang
Googlerace85a22021-11-26 14:18:31 +0000991
992namespace llvm {
993
Martin Brænne1a207c52022-04-19 00:05:38 -0700994bool DenseMapInfo<clang::tidy::lifetimes::ValueLifetimes>::isEqual(
995 const clang::tidy::lifetimes::ValueLifetimes& lhs,
996 const clang::tidy::lifetimes::ValueLifetimes& rhs) {
Googler41f3e352021-12-16 15:24:21 +0000997 if (lhs.type_ != rhs.type_) {
998 return false;
999 }
Googlerace85a22021-11-26 14:18:31 +00001000 if ((lhs.pointee_lifetimes_ == nullptr) !=
1001 (rhs.pointee_lifetimes_ == nullptr)) {
1002 return false;
1003 }
1004 if (lhs.pointee_lifetimes_ &&
Martin Brænne1a207c52022-04-19 00:05:38 -07001005 !DenseMapInfo<clang::tidy::lifetimes::ObjectLifetimes>::isEqual(
Googler2e87fae2021-12-16 15:24:41 +00001006 *lhs.pointee_lifetimes_, *rhs.pointee_lifetimes_)) {
Googlerace85a22021-11-26 14:18:31 +00001007 return false;
1008 }
1009 if (lhs.template_argument_lifetimes_.size() !=
1010 rhs.template_argument_lifetimes_.size()) {
1011 return false;
1012 }
1013 for (size_t i = 0; i < lhs.template_argument_lifetimes_.size(); i++) {
Googlere4d4ec42022-03-28 06:52:23 -07001014 if (lhs.template_argument_lifetimes_[i].size() !=
1015 rhs.template_argument_lifetimes_[i].size()) {
Googlerace85a22021-11-26 14:18:31 +00001016 return false;
1017 }
Googlere4d4ec42022-03-28 06:52:23 -07001018 for (size_t j = 0; j < lhs.template_argument_lifetimes_[i].size(); j++) {
1019 const auto& alhs = lhs.template_argument_lifetimes_[i][j];
1020 const auto& arhs = rhs.template_argument_lifetimes_[i][j];
1021 if (alhs.has_value() != arhs.has_value()) {
1022 return false;
1023 }
1024 if (alhs.has_value() && !isEqual(*alhs, *arhs)) {
1025 return false;
1026 }
Googlerace85a22021-11-26 14:18:31 +00001027 }
1028 }
Luca Versari7f1783d2022-01-31 14:40:39 +00001029 if (lhs.lifetime_parameters_by_name_.GetMapping() !=
1030 rhs.lifetime_parameters_by_name_.GetMapping()) {
1031 return false;
1032 }
Googlerace85a22021-11-26 14:18:31 +00001033 return true;
1034}
1035
Martin Brænne1a207c52022-04-19 00:05:38 -07001036unsigned DenseMapInfo<clang::tidy::lifetimes::ValueLifetimes>::getHashValue(
1037 const clang::tidy::lifetimes::ValueLifetimes& value_lifetimes) {
Googlerace85a22021-11-26 14:18:31 +00001038 llvm::hash_code hash = 0;
Googler2e87fae2021-12-16 15:24:41 +00001039 if (value_lifetimes.pointee_lifetimes_) {
Martin Brænne1a207c52022-04-19 00:05:38 -07001040 hash = DenseMapInfo<clang::tidy::lifetimes::ObjectLifetimes>::getHashValue(
Googler2e87fae2021-12-16 15:24:41 +00001041 *value_lifetimes.pointee_lifetimes_);
Googlerace85a22021-11-26 14:18:31 +00001042 }
Googlere4d4ec42022-03-28 06:52:23 -07001043 for (const auto& lifetimes_at_depth :
Googler2e87fae2021-12-16 15:24:41 +00001044 value_lifetimes.template_argument_lifetimes_) {
Googlere4d4ec42022-03-28 06:52:23 -07001045 for (const auto& tmpl_lifetime : lifetimes_at_depth) {
1046 if (tmpl_lifetime) {
1047 hash = hash_combine(hash, getHashValue(*tmpl_lifetime));
1048 }
Googlerace85a22021-11-26 14:18:31 +00001049 }
1050 }
Luca Versari7f1783d2022-01-31 14:40:39 +00001051 for (const auto& lifetime_arg :
1052 value_lifetimes.lifetime_parameters_by_name_.GetMapping()) {
1053 hash = hash_combine(hash, DenseMapInfo<llvm::StringRef>::getHashValue(
1054 lifetime_arg.first()));
Martin Brænne1a207c52022-04-19 00:05:38 -07001055 hash = hash_combine(
1056 hash, DenseMapInfo<clang::tidy::lifetimes::Lifetime>::getHashValue(
1057 lifetime_arg.second));
Luca Versari7f1783d2022-01-31 14:40:39 +00001058 }
Googler41f3e352021-12-16 15:24:21 +00001059 return hash_combine(
Googler2e87fae2021-12-16 15:24:41 +00001060 hash, DenseMapInfo<clang::QualType>::getHashValue(value_lifetimes.type_));
Googlerace85a22021-11-26 14:18:31 +00001061}
1062
1063} // namespace llvm