blob: 97d04a132cc485272b27562057114d15459bb178 [file] [log] [blame]
Googlerb0019ca2021-11-26 14:20:10 +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/lifetime_annotations.h"
6
7#include <string>
8#include <utility>
9
Luca Versaric21d92f2022-05-25 00:56:30 -070010#include "gmock/gmock.h"
11#include "gtest/gtest.h"
12#include "absl/status/status.h"
13#include "common/status_test_matchers.h"
Martin Brænne198ff492023-04-05 01:41:25 -070014#include "lifetime_annotations/lifetime_error.h"
Marcel Hlopko97a68a12022-03-09 11:38:51 +000015#include "lifetime_annotations/test/named_func_lifetimes.h"
16#include "lifetime_annotations/test/run_on_code.h"
Martin Brænne2af40a02022-06-27 01:28:16 -070017#include "lifetime_annotations/type_lifetimes.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070018#include "clang/ASTMatchers/ASTMatchFinder.h"
19#include "clang/ASTMatchers/ASTMatchers.h"
Luca Versari4a68cc22023-01-16 10:06:15 -080020#include "clang/Tooling/Tooling.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070021#include "llvm/Support/FormatVariadic.h"
Googlerb0019ca2021-11-26 14:20:10 +000022
Martin Brænne9fb786f2022-06-23 01:18:19 -070023// This file contains tests both for the "legacy" lifetime annotations
24// (`[[clang::annotate("lifetimes", ...)]]` placed on a function declaration)
25// and the newer annotations (`[[clang::annotate_type("lifetime", ...")]]`
26// placed on a type). This is because we expect we may continue to use the
27// "legacy" style of annotations in sidecar files.
28//
29// Some tests only test one style of annotation where testing the other style
30// does not make sense for the particular test.
31
Martin Brænne1a207c52022-04-19 00:05:38 -070032namespace clang {
33namespace tidy {
34namespace lifetimes {
Googlerb0019ca2021-11-26 14:20:10 +000035namespace {
36
Luca Versaric21d92f2022-05-25 00:56:30 -070037using crubit::IsOkAndHolds;
38using crubit::StatusIs;
Googlerb0019ca2021-11-26 14:20:10 +000039using testing::StartsWith;
Googlerb0019ca2021-11-26 14:20:10 +000040
Lukasz Anforowicz63f10da2022-01-26 16:59:36 +000041bool IsOverloaded(const clang::FunctionDecl* func) {
42 return !func->getDeclContext()->lookup(func->getDeclName()).isSingleResult();
43}
44
Googlerb0019ca2021-11-26 14:20:10 +000045std::string QualifiedName(const clang::FunctionDecl* func) {
46 std::string str;
47 llvm::raw_string_ostream ostream(str);
48 func->printQualifiedName(ostream);
Lukasz Anforowicz63f10da2022-01-26 16:59:36 +000049 if (IsOverloaded(func)) {
Martin Brænne2af40a02022-06-27 01:28:16 -070050 ostream << "[" << StripAttributes(func->getType()).getAsString() << "]";
Lukasz Anforowicz63f10da2022-01-26 16:59:36 +000051 }
Googlerb0019ca2021-11-26 14:20:10 +000052 ostream.flush();
53 return str;
54}
55
Martin Brænne9fb786f2022-06-23 01:18:19 -070056// Prepends definitions for lifetime annotation macros to the code.
57std::string WithLifetimeMacros(absl::string_view code) {
58 std::string result = R"(
Martin Brænne8bc2de32022-06-24 07:01:52 -070059 // TODO(mboehme): We would prefer `$(...)` to be a variadic macro that
60 // stringizes each of its macro arguments individually. This is possible but
61 // requires some contortions: https://stackoverflow.com/a/5958315
Martin Brænne9fb786f2022-06-23 01:18:19 -070062 #define $(l) [[clang::annotate_type("lifetime", #l)]]
Martin Brænne8bc2de32022-06-24 07:01:52 -070063 #define $2(l1, l2) [[clang::annotate_type("lifetime", #l1, #l2)]]
64 #define $3(l1, l2, l3) [[clang::annotate_type("lifetime", #l1, #l2, #l3)]]
Martin Brænne9fb786f2022-06-23 01:18:19 -070065 )";
66 for (char l = 'a'; l <= 'z'; ++l) {
67 absl::StrAppendFormat(&result, "#define $%c $(%c)\n", l, l);
68 }
Martin Brænneddf2e822022-06-27 00:43:56 -070069 absl::StrAppend(&result, "#define $static $(static)\n");
Martin Brænne9fb786f2022-06-23 01:18:19 -070070 absl::StrAppend(&result, code);
71 return result;
72}
73
Martin Brænne198ff492023-04-05 01:41:25 -070074std::string FormatErrorString(llvm::Error err) {
75 std::string result;
76 err = llvm::handleErrors(
77 std::move(err), [&result](const LifetimeError& lifetime_err) {
78 switch (lifetime_err.type()) {
79 case LifetimeError::Type::ElisionNotEnabled:
80 result = "ERROR(ElisionNotEnabled): ";
81 break;
82 case LifetimeError::Type::CannotElideOutputLifetimes:
83 result = "ERROR(CannotElideOutputLifetimes): ";
84 break;
85 case LifetimeError::Type::Other:
86 result = "ERROR(Other): ";
87 break;
88 }
89 absl::StrAppend(&result, lifetime_err.message());
90 });
91 if (err) {
92 result = absl::StrCat("ERROR: ", llvm::toString(std::move(err)));
93 }
94 return result;
95}
96
Googlerb0019ca2021-11-26 14:20:10 +000097class LifetimeAnnotationsTest : public testing::Test {
98 protected:
99 absl::StatusOr<NamedFuncLifetimes> GetNamedLifetimeAnnotations(
100 absl::string_view code,
101 const clang::tooling::FileContentMappings& file_contents =
Luca Versari4a68cc22023-01-16 10:06:15 -0800102 clang::tooling::FileContentMappings(),
103 bool skip_templates = true) {
Googlerb0019ca2021-11-26 14:20:10 +0000104 absl::StatusOr<NamedFuncLifetimes> result;
Googler656e5b22022-03-01 09:40:47 +0000105 bool success = runOnCodeWithLifetimeHandlers(
Googler1cd66872021-12-10 11:40:03 +0000106 llvm::StringRef(code.data(), code.size()),
Luca Versari4a68cc22023-01-16 10:06:15 -0800107 [&result, skip_templates](
108 clang::ASTContext& ast_context,
109 const LifetimeAnnotationContext& lifetime_context) {
Googlerb0019ca2021-11-26 14:20:10 +0000110 using clang::ast_matchers::findAll;
111 using clang::ast_matchers::functionDecl;
112 using clang::ast_matchers::match;
113
114 NamedFuncLifetimes named_func_lifetimes;
115 for (const auto& node :
116 match(findAll(functionDecl().bind("func")), ast_context)) {
117 if (const auto* func =
118 node.getNodeAs<clang::FunctionDecl>("func")) {
Luca Versari4a68cc22023-01-16 10:06:15 -0800119 // Skip various categories of function, unless explicitly
120 // requested:
Martin Brænnebd003e92022-06-27 23:22:27 -0700121 // - Template instantiation don't contain any annotations that
122 // aren't present in the template itself, but they may contain
123 // reference-like types (which will obviously be unannotated),
124 // which will generate nuisance "lifetime elision not enabled"
125 // errors.
126 // - Implicitly defaulted functions obviously cannot contain
127 // lifetime annotations. They will need to be handled through
128 // `AnalyzeDefaultedFunction()` in analyze.cc.
Luca Versari4a68cc22023-01-16 10:06:15 -0800129 if ((func->isTemplateInstantiation() && skip_templates) ||
Martin Brænnebd003e92022-06-27 23:22:27 -0700130 (func->isDefaulted() && !func->isExplicitlyDefaulted())) {
131 continue;
132 }
133
Googlerbea5dd12021-11-30 11:47:04 +0000134 LifetimeSymbolTable symbol_table;
Googlerb0019ca2021-11-26 14:20:10 +0000135 llvm::Expected<FunctionLifetimes> func_lifetimes =
Googlerbea5dd12021-11-30 11:47:04 +0000136 GetLifetimeAnnotations(func, lifetime_context, &symbol_table);
Googlerb0019ca2021-11-26 14:20:10 +0000137
Martin Brænne2af40a02022-06-27 01:28:16 -0700138 std::string new_entry;
139 if (func_lifetimes) {
140 new_entry = NameLifetimes(*func_lifetimes, symbol_table);
141 } else {
Martin Brænne198ff492023-04-05 01:41:25 -0700142 new_entry = FormatErrorString(func_lifetimes.takeError());
Googlerb0019ca2021-11-26 14:20:10 +0000143 }
Martin Brænne2af40a02022-06-27 01:28:16 -0700144
Lukasz Anforowicz63f10da2022-01-26 16:59:36 +0000145 std::string func_name = QualifiedName(func);
Lukasz Anforowicz63f10da2022-01-26 16:59:36 +0000146 std::optional<llvm::StringRef> old_entry =
147 named_func_lifetimes.Get(func_name);
148 if (old_entry.has_value()) {
149 if (new_entry != old_entry.value()) {
150 result = absl::UnknownError(
151 llvm::formatv(
152 "Unexpectedly different lifetimes for function '{0}'."
153 "Old: '{1}'. New: '{2}'.",
154 func_name, old_entry.value(), new_entry)
155 .str());
156 return;
157 }
158 } else {
159 named_func_lifetimes.Add(std::move(func_name),
160 std::move(new_entry));
161 }
Googlerb0019ca2021-11-26 14:20:10 +0000162 }
163 }
164
165 result = std::move(named_func_lifetimes);
166 },
167 {}, file_contents);
168
Googler656e5b22022-03-01 09:40:47 +0000169 if (!success) {
170 return absl::UnknownError(
171 "Error extracting lifetimes. (Compilation error?)");
172 }
173
Googlerb0019ca2021-11-26 14:20:10 +0000174 return result;
175 }
176};
177
178TEST_F(LifetimeAnnotationsTest, NoLifetimes) {
179 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
180 int f(int);
181 )"),
182 IsOkAndHolds(LifetimesAre({{"f", "()"}})));
183}
184
Googler656e5b22022-03-01 09:40:47 +0000185TEST_F(LifetimeAnnotationsTest, Failure_CompileError) {
186 EXPECT_THAT(
187 GetNamedLifetimeAnnotations(R"(
188 undefined f(undefined);
189 )"),
190 StatusIs(absl::StatusCode::kUnknown,
191 StartsWith("Error extracting lifetimes. (Compilation error?)")));
192}
193
Googlerb0019ca2021-11-26 14:20:10 +0000194TEST_F(LifetimeAnnotationsTest, Failure_NoAnnotationsNoLifetimeElision) {
195 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
196 int** f(int*);
197 )"),
Martin Brænne198ff492023-04-05 01:41:25 -0700198 IsOkAndHolds(LifetimesAre({{"f",
199 "ERROR(ElisionNotEnabled): Lifetime "
200 "elision not enabled for 'f'"}})));
Googlerb0019ca2021-11-26 14:20:10 +0000201}
202
Googler6804a012022-01-05 07:04:36 +0000203TEST_F(LifetimeAnnotationsTest, Failure_NoOutputAnnotationNoLifetimeElision) {
204 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
205 int* f();
206 )"),
Martin Brænne2af40a02022-06-27 01:28:16 -0700207 // We specifically want to see this error message rather than
208 // "Cannot elide output lifetimes".
Martin Brænne198ff492023-04-05 01:41:25 -0700209 IsOkAndHolds(LifetimesAre({{"f",
210 "ERROR(ElisionNotEnabled): Lifetime "
211 "elision not enabled for 'f'"}})));
Googler6804a012022-01-05 07:04:36 +0000212}
213
Googlerb0019ca2021-11-26 14:20:10 +0000214TEST_F(LifetimeAnnotationsTest, Failure_NoAnnotationsElisionPragmaInWrongFile) {
215 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
Googler33f768d2021-11-29 10:33:49 +0000216 #pragma clang lifetime_elision
Googlerb0019ca2021-11-26 14:20:10 +0000217 #include "header.h"
218 )",
219 {std::make_pair("header.h", R"(
220 int** f(int*);
221 )")}),
Martin Brænne198ff492023-04-05 01:41:25 -0700222 IsOkAndHolds(LifetimesAre({{"f",
223 "ERROR(ElisionNotEnabled): Lifetime "
224 "elision not enabled for 'f'"}})));
Googlerb0019ca2021-11-26 14:20:10 +0000225}
226
227TEST_F(LifetimeAnnotationsTest, LifetimeElision_OneInputLifetime) {
228 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
Googler33f768d2021-11-29 10:33:49 +0000229 #pragma clang lifetime_elision
Googlerb0019ca2021-11-26 14:20:10 +0000230 int** f(int*);
231 )"),
232 IsOkAndHolds(LifetimesAre({{"f", "a -> (a, a)"}})));
233}
234
235TEST_F(LifetimeAnnotationsTest, LifetimeElision_NoOutputLifetimes) {
236 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
Googler33f768d2021-11-29 10:33:49 +0000237 #pragma clang lifetime_elision
Googlerb0019ca2021-11-26 14:20:10 +0000238 void f(int**, int *);
239 )"),
240 IsOkAndHolds(LifetimesAre({{"f", "(a, b), c"}})));
241}
242
243TEST_F(LifetimeAnnotationsTest, LifetimeElision_Templates) {
244 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
Googler33f768d2021-11-29 10:33:49 +0000245 #pragma clang lifetime_elision
Googlerb0019ca2021-11-26 14:20:10 +0000246 template <class T> class vector {};
247 int* f(vector<int *>);
248 vector<int*> g(int *);
249 )"),
250 IsOkAndHolds(LifetimesAre({{"f", "a -> a"}, {"g", "a -> a"}})));
251}
252
Kinuko Yasuda74d5a3c2022-08-29 14:40:04 -0700253TEST_F(LifetimeAnnotationsTest, LifetimeElision_TemplatesWithConstant) {
254 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
255 #pragma clang lifetime_elision
256 template <class T, bool B> class vector {};
257 int* f(vector<int *, true>);
258 vector<int*, false> g(int *);
259 )"),
260 IsOkAndHolds(LifetimesAre({{"f", "a -> a"}, {"g", "a -> a"}})));
261}
262
Googlere4d4ec42022-03-28 06:52:23 -0700263TEST_F(LifetimeAnnotationsTest, LifetimeElision_NestedTemplates) {
Luca Versari6ee6b342022-04-05 05:40:52 -0700264 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
Googlerbdc55802022-03-24 11:21:37 +0000265 #pragma clang lifetime_elision
266 template <class T>
267 struct Outer {
268 template <class U>
269 struct Inner {
270 };
271 };
272 void f(Outer<int *>::Inner<int *> &);
273 Outer<int *>::Inner<int *> g(int *);
274 )"),
Luca Versari6ee6b342022-04-05 05:40:52 -0700275 IsOkAndHolds(LifetimesAre(
276 {{"f", "(<a>::<b>, c)"}, {"g", "a -> <a>::<a>"}})));
Googlerbdc55802022-03-24 11:21:37 +0000277}
278
Googlerfbb37d22022-03-02 15:13:53 +0000279TEST_F(LifetimeAnnotationsTest, LifetimeElision_LifetimeParameterizedType) {
280 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
281 #pragma clang lifetime_elision
282 struct [[clang::annotate("lifetime_params", "s")]] string_view{};
283 string_view f(string_view);
284 )"),
285 IsOkAndHolds(LifetimesAre({{"f", "a -> a"}})));
286}
287
Googlerb0019ca2021-11-26 14:20:10 +0000288TEST_F(LifetimeAnnotationsTest, LifetimeElision_Method) {
289 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
Googler33f768d2021-11-29 10:33:49 +0000290 #pragma clang lifetime_elision
Googlerb0019ca2021-11-26 14:20:10 +0000291 struct S {
292 int** method(int *, int *);
293 };
294 )"),
Googler6804a012022-01-05 07:04:36 +0000295 IsOkAndHolds(LifetimesAre({{"S::method", "a: b, c -> (a, a)"}})));
Googlerb0019ca2021-11-26 14:20:10 +0000296}
297
Devin Jeanpierre108e9c02022-06-02 07:10:09 -0700298TEST_F(LifetimeAnnotationsTest, LifetimeElision_Destructor) {
299 EXPECT_THAT(GetNamedLifetimeAnnotations(R"cc(
300 // Note: this works even without #pragma clang lifetime_elision
301 struct S {
302 ~S();
303 };
304 )cc"),
305 IsOkAndHolds(LifetimesAre({{"S::~S", "a:"}})));
306}
307
Lukasz Anforowicz63f10da2022-01-26 16:59:36 +0000308TEST_F(LifetimeAnnotationsTest, LifetimeElision_ExplicitlyDefaultedCtor) {
309 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
310 #pragma clang lifetime_elision
311 struct S {
312 S() = default;
313 };)"),
314 IsOkAndHolds(LifetimesAre({{"S::S", "a:"}})));
315}
316
Googler8a8e82e2022-02-28 14:53:56 +0000317TEST_F(LifetimeAnnotationsTest, LifetimeElision_ArrayParamLifetimes) {
318 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
319 #pragma clang lifetime_elision
320 void f(int pair[2]);
321 )"),
322 IsOkAndHolds(LifetimesAre({{"f", "a"}})));
323}
324
325TEST_F(LifetimeAnnotationsTest, LifetimeElision_ArrayParamAsTypedefLifetimes) {
326 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
327 #pragma clang lifetime_elision
Googler656e5b22022-03-01 09:40:47 +0000328 typedef int Arr[2];
Googler8a8e82e2022-02-28 14:53:56 +0000329 void f(Arr);
330 )"),
331 IsOkAndHolds(LifetimesAre({{"f", "a"}})));
332}
333
Googler8a8e82e2022-02-28 14:53:56 +0000334TEST_F(LifetimeAnnotationsTest,
Martin Brænneafad7ca2023-03-30 06:29:31 -0700335 LifetimeElision_LifetimesInsideFunctionPointerParameter) {
Googler8a8e82e2022-02-28 14:53:56 +0000336 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
337 #pragma clang lifetime_elision
Martin Brænneafad7ca2023-03-30 06:29:31 -0700338 void f(void (*)(int *, int *));
Googler8a8e82e2022-02-28 14:53:56 +0000339 )"),
Martin Brænneafad7ca2023-03-30 06:29:31 -0700340 IsOkAndHolds(LifetimesAre({{"f", "(a, b)"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000341}
342
Martin Brænneafad7ca2023-03-30 06:29:31 -0700343TEST_F(
344 LifetimeAnnotationsTest,
345 LifetimeElision_FunctionPointerParameterDoesNotCountTowardsInputLifetimes) {
Googler8a8e82e2022-02-28 14:53:56 +0000346 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
347 #pragma clang lifetime_elision
Martin Brænneafad7ca2023-03-30 06:29:31 -0700348 int* f(int *, void (*)());
Googler8a8e82e2022-02-28 14:53:56 +0000349 )"),
Martin Brænneafad7ca2023-03-30 06:29:31 -0700350 IsOkAndHolds(LifetimesAre({{"f", "a, () -> a"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000351}
352
Martin Brænneafad7ca2023-03-30 06:29:31 -0700353TEST_F(
354 LifetimeAnnotationsTest,
355 LifetimeElision_FunctionReferenceParameterDoesNotCountTowardsInputLifetimes) {
Googler8a8e82e2022-02-28 14:53:56 +0000356 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
357 #pragma clang lifetime_elision
Martin Brænneafad7ca2023-03-30 06:29:31 -0700358 int* f(int *, void (&)());
Googler8a8e82e2022-02-28 14:53:56 +0000359 )"),
Martin Brænneafad7ca2023-03-30 06:29:31 -0700360 IsOkAndHolds(LifetimesAre({{"f", "a, () -> a"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000361}
362
Googler2e1f0c12022-03-01 09:26:30 +0000363TEST_F(LifetimeAnnotationsTest,
364 LifetimeElision_PointerToMemberDoesNotGetLifetime) {
365 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
366 #pragma clang lifetime_elision
367 struct S {};
368 void f(int S::*ptr_to_member);
369 )"),
370 IsOkAndHolds(LifetimesAre({{"f", "()"}})));
371}
372
Googler8a8e82e2022-02-28 14:53:56 +0000373TEST_F(LifetimeAnnotationsTest, LifetimeElision_FailureTooFewInputLifetimes) {
374 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
375 #pragma clang lifetime_elision
376 int* f();
377 )"),
Martin Brænne2af40a02022-06-27 01:28:16 -0700378 IsOkAndHolds(LifetimesAre(
379 {{"f",
Martin Brænne198ff492023-04-05 01:41:25 -0700380 "ERROR(CannotElideOutputLifetimes): Cannot elide output "
381 "lifetimes for 'f' because it is a non-member function "
382 "that does not have exactly one input lifetime"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000383}
384
385TEST_F(LifetimeAnnotationsTest, LifetimeElision_FailureTooManyInputLifetimes) {
386 EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
387 #pragma clang lifetime_elision
388 int* f(int**);
389 )"),
Martin Brænne2af40a02022-06-27 01:28:16 -0700390 IsOkAndHolds(LifetimesAre(
391 {{"f",
Martin Brænne198ff492023-04-05 01:41:25 -0700392 "ERROR(CannotElideOutputLifetimes): Cannot elide output "
393 "lifetimes for 'f' because it is a non-member function "
394 "that does not have exactly one input lifetime"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000395}
396
397TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_NoLifetimes) {
398 EXPECT_THAT(GetNamedLifetimeAnnotations(R"_(
399 [[clang::annotate("lifetimes", "()")]]
400 void f(int);
401 )_"),
402 IsOkAndHolds(LifetimesAre({{"f", "()"}})));
403}
404
Martin Brænneafad7ca2023-03-30 06:29:31 -0700405TEST_F(LifetimeAnnotationsTest,
406 LifetimeAnnotation_FunctionPointerHasNoLifetimes) {
407 EXPECT_THAT(GetNamedLifetimeAnnotations(R"_(
408 void f(void (*)());
409 )_"),
410 IsOkAndHolds(LifetimesAre({{"f", "()"}})));
411}
412
413TEST_F(LifetimeAnnotationsTest,
Martin Brænne3279a7f2023-04-04 03:52:16 -0700414 LifetimeAnnotation_FunctionPointerReturnTypeHasNoLifetimes) {
415 EXPECT_THAT(GetNamedLifetimeAnnotations(R"_(
416 int (* f())(float, double);
417 )_"),
418 IsOkAndHolds(LifetimesAre({{"f", "-> ((), ())"}})));
419}
420
421TEST_F(LifetimeAnnotationsTest,
Martin Brænneafad7ca2023-03-30 06:29:31 -0700422 LifetimeAnnotation_FunctionReferenceHasNoLifetimes) {
423 EXPECT_THAT(GetNamedLifetimeAnnotations(R"_(
424 void f(void (&)());
425 )_"),
426 IsOkAndHolds(LifetimesAre({{"f", "()"}})));
427}
428
Martin Brænne9fb786f2022-06-23 01:18:19 -0700429TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_BadAttributeArgument) {
430 EXPECT_THAT(
431 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
432 void f(int* [[clang::annotate_type("lifetime", 1)]]);
433 )")),
Martin Brænne2af40a02022-06-27 01:28:16 -0700434 IsOkAndHolds(LifetimesAre(
Martin Brænne198ff492023-04-05 01:41:25 -0700435 {{"f",
436 "ERROR(Other): cannot evaluate argument as a string literal"}})));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700437}
438
Googler8a8e82e2022-02-28 14:53:56 +0000439TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Simple) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700440 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000441 [[clang::annotate("lifetimes", "a -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700442 int* f1(int*);
443 int* $a f2(int* $a);
444 )")),
445 IsOkAndHolds(LifetimesAre({{"f1", "a -> a"}, {"f2", "a -> a"}})));
446}
447
448TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_SimpleRef) {
449 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
450 [[clang::annotate("lifetimes", "a -> a")]]
451 int& f1(int&);
452 int& $a f2(int& $a);
453 )")),
454 IsOkAndHolds(LifetimesAre({{"f1", "a -> a"}, {"f2", "a -> a"}})));
455}
456
457TEST_F(LifetimeAnnotationsTest,
Martin Brænne2c6f94b2023-03-29 05:24:56 -0700458 LifetimeAnnotation_Invalid_LifetimeOnNonReferenceLikeType) {
Martin Brænne198ff492023-04-05 01:41:25 -0700459 EXPECT_THAT(
460 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænne2c6f94b2023-03-29 05:24:56 -0700461 void f(int $a);
462 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700463 IsOkAndHolds(LifetimesAre(
464 {{"f", "ERROR(Other): Type may not be annotated with lifetimes"}})));
Martin Brænne2c6f94b2023-03-29 05:24:56 -0700465}
466
467TEST_F(LifetimeAnnotationsTest,
Martin Brænneafad7ca2023-03-30 06:29:31 -0700468 LifetimeAnnotation_Invalid_LifetimeOnFunctionPointer) {
Martin Brænne198ff492023-04-05 01:41:25 -0700469 EXPECT_THAT(
470 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænneafad7ca2023-03-30 06:29:31 -0700471 void f(void (* $a)());
472 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700473 IsOkAndHolds(LifetimesAre(
474 {{"f", "ERROR(Other): Type may not be annotated with lifetimes"}})));
Martin Brænneafad7ca2023-03-30 06:29:31 -0700475}
476
477TEST_F(LifetimeAnnotationsTest,
Martin Brænne3279a7f2023-04-04 03:52:16 -0700478 LifetimeAnnotation_Invalid_LifetimeOnFunctionPointerReturnType) {
Martin Brænne198ff492023-04-05 01:41:25 -0700479 EXPECT_THAT(
480 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænne3279a7f2023-04-04 03:52:16 -0700481 int (* $a f())(float, double);
482 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700483 IsOkAndHolds(LifetimesAre(
484 {{"f", "ERROR(Other): Type may not be annotated with lifetimes"}})));
Martin Brænne3279a7f2023-04-04 03:52:16 -0700485}
486
487TEST_F(LifetimeAnnotationsTest,
Martin Brænneafad7ca2023-03-30 06:29:31 -0700488 LifetimeAnnotation_Invalid_LifetimeOnFunctionReference) {
Martin Brænne198ff492023-04-05 01:41:25 -0700489 EXPECT_THAT(
490 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænneafad7ca2023-03-30 06:29:31 -0700491 void f(void (& $a)());
492 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700493 IsOkAndHolds(LifetimesAre(
494 {{"f", "ERROR(Other): Type may not be annotated with lifetimes"}})));
Martin Brænneafad7ca2023-03-30 06:29:31 -0700495}
496
497TEST_F(LifetimeAnnotationsTest,
Martin Brænne9fb786f2022-06-23 01:18:19 -0700498 LifetimeAnnotation_Invalid_MultipleLifetimesOnPointer) {
499 EXPECT_THAT(
500 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænne8bc2de32022-06-24 07:01:52 -0700501 void f(int* $2(a, b));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700502 )")),
Martin Brænne2af40a02022-06-27 01:28:16 -0700503 IsOkAndHolds(LifetimesAre(
Martin Brænne198ff492023-04-05 01:41:25 -0700504 {{"f",
505 "ERROR(Other): Expected a single lifetime but 2 were given"}})));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700506}
507
508TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Static) {
509 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
510 [[clang::annotate("lifetimes", "static -> static")]]
511 int* f1(int*);
512 int* $static f2(int* $static);
513 )")),
514 IsOkAndHolds(LifetimesAre(
515 {{"f1", "static -> static"}, {"f2", "static -> static"}})));
516}
517
518TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_PartialElision) {
519 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
520 #pragma clang lifetime_elision
521 int* $a f(int* $a, int*, int* $a);
522 )")),
523 IsOkAndHolds(LifetimesAre({{"f", "a, b, a -> a"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000524}
525
526TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_MultiplePtr) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700527 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000528 [[clang::annotate("lifetimes", "(a, b) -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700529 int* f1(int**);
530 int* $a f2(int* $a * $b);
531 )")),
532 IsOkAndHolds(LifetimesAre(
533 {{"f1", "(a, b) -> a"}, {"f2", "(a, b) -> a"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000534}
535
536TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_MultipleArguments) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700537 EXPECT_THAT(
538 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000539 [[clang::annotate("lifetimes", "a, b -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700540 int* f1(int*, int*);
541 int* $a f2(int* $a, int* $b);
542 )")),
543 IsOkAndHolds(LifetimesAre({{"f1", "a, b -> a"}, {"f2", "a, b -> a"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000544}
545
546TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_NoReturn) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700547 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000548 [[clang::annotate("lifetimes", "a, b")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700549 void f1(int*, int*);
550 void f2(int* $a, int* $b);
551 )")),
552 IsOkAndHolds(LifetimesAre({{"f1", "a, b"}, {"f2", "a, b"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000553}
554
Martin Brænne9fb786f2022-06-23 01:18:19 -0700555TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_ParamWithoutLifetime) {
556 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000557 [[clang::annotate("lifetimes", "a, (), a -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700558 int* f1(int*, int, int*);
559 int* $a f2(int* $a, int, int* $a);
560 )")),
561 IsOkAndHolds(LifetimesAre(
562 {{"f1", "a, (), a -> a"}, {"f2", "a, (), a -> a"}})));
563}
564
565TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_LifetimeParameterizedType) {
566 // Use a custom delimiter so that the `")` in the `clang::annotate` attribute
567 // below doesn't prematurely terminate the string.
568 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"code(
569 struct [[clang::annotate("lifetime_params", "a", "b")]] S_param {};
570
571 [[clang::annotate("lifetimes", "([a, b]) -> ([a, b])")]]
572 S_param f1(S_param s);
573
Martin Brænne8bc2de32022-06-24 07:01:52 -0700574 S_param $2(a, b) f2(S_param $2(a, b) s);
Martin Brænne9fb786f2022-06-23 01:18:19 -0700575 )code")),
576 IsOkAndHolds(LifetimesAre({{"f1", "([a, b]) -> ([a, b])"},
577 {"f2", "([a, b]) -> ([a, b])"}})));
578}
579
Martin Brænne8bc2de32022-06-24 07:01:52 -0700580TEST_F(
581 LifetimeAnnotationsTest,
582 LifetimeAnnotation_LifetimeParameterizedType_Invalid_WrongNumberOfLifetimes) {
Martin Brænne198ff492023-04-05 01:41:25 -0700583 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænne9fb786f2022-06-23 01:18:19 -0700584 struct [[clang::annotate("lifetime_params", "a", "b")]] S_param {};
585
Martin Brænne8bc2de32022-06-24 07:01:52 -0700586 void f(S_param $3(a, b, c) s);
Martin Brænne9fb786f2022-06-23 01:18:19 -0700587 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700588 IsOkAndHolds(LifetimesAre(
589 {{"f",
590 "ERROR(Other): Type has 2 lifetime parameters but 3 "
591 "lifetime arguments were given"}})));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700592}
593
Martin Brænne8bc2de32022-06-24 07:01:52 -0700594TEST_F(
595 LifetimeAnnotationsTest,
596 LifetimeAnnotation_LifetimeParameterizedType_Invalid_MultipleAnnotateAttributes) {
Martin Brænne198ff492023-04-05 01:41:25 -0700597 EXPECT_THAT(
598 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænne8bc2de32022-06-24 07:01:52 -0700599 struct [[clang::annotate("lifetime_params", "a", "b")]] S_param {};
600
601 void f(S_param $a $b s);
602 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700603 IsOkAndHolds(LifetimesAre(
604 {{"f",
605 "ERROR(Other): Only one `[[annotate_type(\"lifetime\", ...)]]` "
606 "attribute may be placed on a type"}})));
Martin Brænne8bc2de32022-06-24 07:01:52 -0700607}
608
Martin Brænne9fb786f2022-06-23 01:18:19 -0700609TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Template) {
610 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
611 template <class T> class vector {};
612
613 [[clang::annotate("lifetimes", "(a, b) -> a")]]
614 int* f1(const vector<int *> &);
615 int* $a f2(const vector<int * $a> & $b);
616 )")),
617 IsOkAndHolds(LifetimesAre(
618 {{"f1", "(a, b) -> a"}, {"f2", "(a, b) -> a"}})));
619}
620
Luca Versari4a68cc22023-01-16 10:06:15 -0800621TEST_F(LifetimeAnnotationsTest, LifetimeAnnotationTemplateUniversalReference) {
622 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
623 #pragma clang lifetime_elision
624 template <typename T>
625 struct S {
626 static void f(T&&) {}
627 };
628
629 void g() { int a; S<int&>::f(a); }
630 )"),
631 clang::tooling::FileContentMappings(),
632 /*skip_templates=*/false),
633 IsOkAndHolds(LifetimesContain({{"S<int &>::f", "a"}})));
634}
635
Martin Brænne9fb786f2022-06-23 01:18:19 -0700636TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_VariadicTemplate) {
637 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"code(
638 template <class... T> class variadic{};
639
640 [[clang::annotate("lifetimes", "(<a, b>, c)")]]
641 void f1(const variadic<int *, int *> &);
642 void f2(const variadic<int * $a, int * $b> & $c);
643 )code")),
644 IsOkAndHolds(LifetimesAre(
645 {{"f1", "(<a, b>, c)"}, {"f2", "(<a, b>, c)"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000646}
647
Martin Brænne33f4f502022-06-27 01:15:15 -0700648TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_VariadicTemplateWithCtor) {
Martin Brænne33f4f502022-06-27 01:15:15 -0700649 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"code(
650 template <typename... Args> struct S { S() $a {} };
651 template <typename T, typename... Args>
652 struct S<T, Args...> {
653 S(T t, Args... args) $a {}
654 };
655
Martin Brænnebd003e92022-06-27 23:22:27 -0700656 void target(int* $a a, int* $b b) {
Martin Brænne33f4f502022-06-27 01:15:15 -0700657 S<int*, int*> s = {a, b};
658 }
659 )code")),
Martin Brænnebd003e92022-06-27 23:22:27 -0700660 IsOkAndHolds(LifetimesAre({{"S::S<Args...>", "a:"},
661 {"S<type-parameter-0-0, "
662 "type-parameter-0-1...>::"
663 "S<type-parameter-0-0, "
664 "type-parameter-0-1...>",
665 "a: (), ()"},
666 {"target", "a, b"}})));
Martin Brænne33f4f502022-06-27 01:15:15 -0700667}
668
Martin Brænne01628862023-03-31 05:19:47 -0700669TEST_F(LifetimeAnnotationsTest,
Martin Brænnee1fa5192023-03-31 05:22:26 -0700670 LifetimeAnnotation_AliasTemplateForClassTemplate) {
Martin Brænne01628862023-03-31 05:19:47 -0700671 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
672 template<class T> struct trait {
673 using type = T;
674 };
675 template<class T> using alias_template = typename trait<T>::type;
676 void target(alias_template<int>* $a p) {
677 }
678 )")),
679 IsOkAndHolds(LifetimesAre({{"target", "a"}})));
680}
681
Googler8a8e82e2022-02-28 14:53:56 +0000682TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Method) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700683 EXPECT_THAT(
684 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000685 struct S {
686 [[clang::annotate("lifetimes", "a: -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700687 int* f1();
688 int* $a f2() $a;
Googler8a8e82e2022-02-28 14:53:56 +0000689 };
Martin Brænne9fb786f2022-06-23 01:18:19 -0700690 )")),
691 IsOkAndHolds(LifetimesAre({{"S::f1", "a: -> a"}, {"S::f2", "a: -> a"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000692}
693
694TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_MethodWithParam) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700695 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000696 struct S {
697 [[clang::annotate("lifetimes", "a: b -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700698 int* f1(int*);
699 int* $a f2(int* $b) $a;
Googler8a8e82e2022-02-28 14:53:56 +0000700 };
Martin Brænne9fb786f2022-06-23 01:18:19 -0700701 )")),
702 IsOkAndHolds(LifetimesAre(
703 {{"S::f1", "a: b -> a"}, {"S::f2", "a: b -> a"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000704}
705
Luca Versari95ce68f2022-03-24 14:44:19 +0000706TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_MethodWithLifetimeParams) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700707 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Luca Versari95ce68f2022-03-24 14:44:19 +0000708 struct [[clang::annotate("lifetime_params", "x", "y")]] S {
Luca Versari6ee6b342022-04-05 05:40:52 -0700709 [[clang::annotate("lifetimes", "([x, y], a): -> x")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700710 int* f1();
711 // It's implied that the lifetime parameters of `this` are $x and $y
712 // because this is a member function on struct with those lifetime
713 // parameters.
714 // TODO(mboehme): This doesn't work yet. We need some special handling
715 // to know that in this context, the type `S` doesn't need lifetimes
716 // put on it.
717 // TODO(mboehme): How do we resolve this difference relative to the
718 // "legacy" lifetime annotations? Does this mean that they should also
719 // not include the lifetimes x and y?
720 // int* $x f2() $a;
Luca Versari95ce68f2022-03-24 14:44:19 +0000721 };
Martin Brænne9fb786f2022-06-23 01:18:19 -0700722 )")),
723 IsOkAndHolds(LifetimesAre({{"S::f1", "([x, y], a): -> x"}})));
Luca Versari95ce68f2022-03-24 14:44:19 +0000724}
725
Googler8a8e82e2022-02-28 14:53:56 +0000726TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Invalid_MissingThis) {
Martin Brænne2af40a02022-06-27 01:28:16 -0700727 EXPECT_THAT(
728 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000729 struct S {
730 [[clang::annotate("lifetimes", "-> a")]]
731 int* f();
732 };
Martin Brænne9fb786f2022-06-23 01:18:19 -0700733 )")),
Martin Brænne2af40a02022-06-27 01:28:16 -0700734 IsOkAndHolds(LifetimesAre(
735 {{"S::f",
Martin Brænne198ff492023-04-05 01:41:25 -0700736 "ERROR(Other): Invalid lifetime annotation: too few lifetimes"}})));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700737 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
738 struct S {
739 int* $a f();
740 };
741 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700742 IsOkAndHolds(LifetimesAre({{"S::f",
743 "ERROR(ElisionNotEnabled): Lifetime "
744 "elision not enabled for 'f'"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000745}
746
747TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Invalid_ThisOnFreeFunction) {
Martin Brænne198ff492023-04-05 01:41:25 -0700748 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000749 [[clang::annotate("lifetimes", "a: a -> a")]]
750 int* f(int*);
Martin Brænne9fb786f2022-06-23 01:18:19 -0700751 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700752 IsOkAndHolds(LifetimesAre({{"f",
753 "ERROR(Other): Invalid lifetime "
754 "annotation: too many lifetimes"}})));
755 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Martin Brænne9fb786f2022-06-23 01:18:19 -0700756 int* $a f(int* $a) $a;
757 )")),
Martin Brænne198ff492023-04-05 01:41:25 -0700758 IsOkAndHolds(LifetimesAre(
759 {{"f",
760 "ERROR(Other): Encountered a `this` lifetime on a "
761 "function with no `this` parameter"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000762}
763
764TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Invalid_WrongNumber) {
Martin Brænne2af40a02022-06-27 01:28:16 -0700765 EXPECT_THAT(
766 GetNamedLifetimeAnnotations(R"(
Googler8a8e82e2022-02-28 14:53:56 +0000767 [[clang::annotate("lifetimes", "a -> a")]]
768 int* f(int**);
769 )"),
Martin Brænne2af40a02022-06-27 01:28:16 -0700770 IsOkAndHolds(LifetimesAre(
Martin Brænne198ff492023-04-05 01:41:25 -0700771 {{"f",
772 "ERROR(Other): Invalid lifetime annotation: too few lifetimes"}})));
Googler8a8e82e2022-02-28 14:53:56 +0000773}
774
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700775TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_Callback) {
Martin Brænneafad7ca2023-03-30 06:29:31 -0700776 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
777 [[clang::annotate("lifetimes", "b, (a -> a) -> b")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700778 int* f1(int*, int* (*)(int*));
Martin Brænneafad7ca2023-03-30 06:29:31 -0700779 int* $b f2(int* $b, int* $a (*)(int* $a));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700780 )")),
Martin Brænneafad7ca2023-03-30 06:29:31 -0700781 IsOkAndHolds(LifetimesAre(
782 {{"f1", "b, (a -> a) -> b"}, {"f2", "b, (a -> a) -> b"}})));
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700783}
784
785TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_CallbackMultipleParams) {
Martin Brænneafad7ca2023-03-30 06:29:31 -0700786 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
787 [[clang::annotate("lifetimes", "c, ((a, b -> a)) -> c")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700788 int* f1(int*, int* (*)(int*, int*));
Martin Brænneafad7ca2023-03-30 06:29:31 -0700789 int* $c f2(int* $c, int* $a (*)(int* $a, int* $b));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700790 )")),
Martin Brænneafad7ca2023-03-30 06:29:31 -0700791 IsOkAndHolds(LifetimesAre({{"f1", "c, (a, b -> a) -> c"},
792 {"f2", "c, (a, b -> a) -> c"}})));
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700793}
794
795TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_CallbackTmplFunc) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700796 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700797 template <typename Func>
798 struct function;
Martin Brænneafad7ca2023-03-30 06:29:31 -0700799 [[clang::annotate("lifetimes", "a, (b -> b) -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700800 int* f1(int*, function<int*(int*)>);
801 int* $a f2(int* $a, function<int* $b(int* $b)>);
802 )")),
Martin Brænne91704652023-03-30 06:13:54 -0700803 IsOkAndHolds(LifetimesAre(
804 {{"f1", "a, (b -> b) -> a"}, {"f2", "a, (b -> b) -> a"}})));
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700805}
806
807TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_MultipleCallbacks) {
Martin Brænneafad7ca2023-03-30 06:29:31 -0700808 EXPECT_THAT(
809 GetNamedLifetimeAnnotations(WithLifetimeMacros(R"(
810 [[clang::annotate("lifetimes", "a, (b -> b), (c -> c) -> a")]]
Martin Brænne9fb786f2022-06-23 01:18:19 -0700811 int* f1(int*, int* (*)(int*), int* (*)(int*));
Martin Brænneafad7ca2023-03-30 06:29:31 -0700812 int* $a f2(int* $a, int* $b (*)(int* $b), int* $c (*)(int* $c));
Martin Brænne9fb786f2022-06-23 01:18:19 -0700813 )")),
Martin Brænneafad7ca2023-03-30 06:29:31 -0700814 IsOkAndHolds(LifetimesAre({{"f1", "a, (b -> b), (c -> c) -> a"},
815 {"f2", "a, (b -> b), (c -> c) -> a"}})));
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700816}
817
818TEST_F(LifetimeAnnotationsTest, LifetimeAnnotation_ReturnFunctionPtr) {
Martin Brænne9fb786f2022-06-23 01:18:19 -0700819 EXPECT_THAT(GetNamedLifetimeAnnotations(WithLifetimeMacros(R"_(
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700820 typedef int* (*FP)(int*);
Martin Brænneafad7ca2023-03-30 06:29:31 -0700821 [[clang::annotate("lifetimes", "a -> (b -> b)")]]
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700822 FP f(int*);
Martin Brænne9fb786f2022-06-23 01:18:19 -0700823 // TODO(mboehme): Need to support lifetime parameters on type aliases to
824 // be able to express this in the new syntax.
825 )_")),
Martin Brænneafad7ca2023-03-30 06:29:31 -0700826 IsOkAndHolds(LifetimesAre({{"f", "a -> (b -> b)"}})));
Luca Versaricc7e6cb2022-04-05 08:08:23 -0700827}
828
Googlerb0019ca2021-11-26 14:20:10 +0000829} // namespace
Martin Brænne1a207c52022-04-19 00:05:38 -0700830} // namespace lifetimes
831} // namespace tidy
832} // namespace clang