blob: 95cb33244f001ec95abc313c4cb40519ed7dbe53 [file] [log] [blame]
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +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
Googler870b38e2021-12-01 15:54:08 +00005#include <optional>
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +00006#include <string>
Marcel Hlopko20f4ce42021-11-02 08:20:00 +00007#include <type_traits>
8#include <variant>
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +00009#include <vector>
10
Luca Versaric21d92f2022-05-25 00:56:30 -070011#include "gmock/gmock.h"
12#include "gtest/gtest.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070013#include "absl/status/status.h"
14#include "absl/status/statusor.h"
15#include "absl/strings/string_view.h"
16#include "absl/types/span.h"
Luca Versaric21d92f2022-05-25 00:56:30 -070017#include "common/status_test_matchers.h"
18#include "common/test_utils.h"
Marcel Hlopko3b254b32022-03-09 14:10:49 +000019#include "rs_bindings_from_cc/bazel_types.h"
20#include "rs_bindings_from_cc/ir.h"
21#include "rs_bindings_from_cc/ir_from_cc.h"
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000022
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -070023namespace crubit {
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000024namespace {
25
Googler5bb23512021-09-17 12:13:27 +000026using ::testing::AllOf;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +000027using ::testing::AnyOf;
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -070028using ::testing::Contains;
Michael Forster523dbd42021-10-12 11:05:44 +000029using ::testing::Each;
Googler5bb23512021-09-17 12:13:27 +000030using ::testing::ElementsAre;
Marcel Hlopko7d739792021-08-12 07:52:47 +000031using ::testing::IsEmpty;
Googler5bb23512021-09-17 12:13:27 +000032using ::testing::Not;
Michael Forster523dbd42021-10-12 11:05:44 +000033using ::testing::Pointee;
Marcel Hlopko7d739792021-08-12 07:52:47 +000034using ::testing::SizeIs;
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -070035using ::testing::UnorderedElementsAre;
Michael Forster7ef80732021-10-01 18:12:19 +000036using ::testing::VariantWith;
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000037
Rosica Dejanovskad638cf52022-03-23 15:45:01 +000038std::optional<ItemId> DeclIdForRecord(const IR& ir, absl::string_view rs_name) {
Googler870b38e2021-12-01 15:54:08 +000039 for (const Record* record : ir.get_items_if<Record>()) {
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +000040 if (record->rs_name == rs_name) {
Marcel Hlopko264b9ad2021-12-02 21:06:44 +000041 return record->id;
Googler870b38e2021-12-01 15:54:08 +000042 }
43 }
44 return std::nullopt;
45}
46
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -070047std::optional<IR::Item> FindItemById(const IR& ir, ItemId id) {
48 for (auto item : ir.items) {
49 if (auto* record = std::get_if<Record>(&item); record && record->id == id) {
50 return item;
51 } else if (auto* func = std::get_if<Func>(&item); func && func->id == id) {
52 return item;
53 } else if (auto* comment = std::get_if<Comment>(&item);
54 comment && comment->id == id) {
55 return item;
56 } else if (auto* unsupported = std::get_if<UnsupportedItem>(&item);
57 unsupported && unsupported->id == id) {
58 return item;
Rosica Dejanovska09aa6362022-08-24 05:41:09 -070059 } else if (auto* ns = std::get_if<Namespace>(&item); ns && ns->id == id) {
60 return item;
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -070061 }
62 }
63 return std::nullopt;
64}
65
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +000066template <typename T>
67UnqualifiedIdentifier GetName(const T& x) {
68 return x.identifier;
69}
70UnqualifiedIdentifier GetName(const Func& x) { return x.name; }
Rosica Dejanovska09aa6362022-08-24 05:41:09 -070071UnqualifiedIdentifier GetName(const Namespace& x) { return x.name; }
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +000072
Googler5bb23512021-09-17 12:13:27 +000073// Matches an IR node that has the given identifier.
74MATCHER_P(IdentifierIs, identifier, "") {
Devin Jeanpierref2ec8712021-10-13 20:47:16 +000075 UnqualifiedIdentifier name = GetName(arg);
76 const Identifier* actual = std::get_if<Identifier>(&name);
77 if (actual == nullptr) {
78 *result_listener << "actual name not an identifier.";
79 return false;
80 }
81 if (actual->Ident() == identifier) return true;
Googler5bb23512021-09-17 12:13:27 +000082
Devin Jeanpierref2ec8712021-10-13 20:47:16 +000083 *result_listener << "actual identifier: '" << actual->Ident() << "'";
Googler5bb23512021-09-17 12:13:27 +000084 return false;
85}
86
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +000087// Matches an Record node that has the given `rs_name`.
88MATCHER_P(RsNameIs, rs_name, "") { return arg.rs_name == rs_name; }
89
Michael Forster028800b2021-10-05 12:39:59 +000090// Matches an IR node that has the given doc comment.
91MATCHER_P(DocCommentIs, doc_comment, "") {
92 if (arg.doc_comment && *arg.doc_comment == doc_comment) return true;
93
94 *result_listener << "actual doc comment: '"
95 << (arg.doc_comment ? *arg.doc_comment : "<none>") << "'";
96 return false;
97}
98
Googler5bb23512021-09-17 12:13:27 +000099// Matches a Func that has the given mangled name.
100MATCHER_P(MangledNameIs, mangled_name, "") {
101 if (arg.mangled_name == mangled_name) return true;
102
103 *result_listener << "actual mangled name: '" << arg.mangled_name << "'";
104 return false;
105}
106
107// Matches a Func that has a return type matching `matcher`.
108template <typename Matcher>
109auto ReturnType(const Matcher& matcher) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000110 return testing::Field("return_type", &Func::return_type, matcher);
Googler5bb23512021-09-17 12:13:27 +0000111}
112
113// Matches a Func that has parameters matching `matchers`.
114template <typename... Args>
115auto ParamsAre(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000116 return testing::Field("params", &Func::params, ElementsAre(matchers...));
Googler5bb23512021-09-17 12:13:27 +0000117}
118
119// Matches a Func that is inline.
120MATCHER(IsInline, "") { return arg.is_inline; }
121
Googlerf09ef0e2021-09-17 12:13:45 +0000122// Matches a FuncParam with a type that matches all given matchers.
123template <typename... Args>
124auto ParamType(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000125 return testing::Field("type", &FuncParam::type, AllOf(matchers...));
Googlerf09ef0e2021-09-17 12:13:45 +0000126}
127
Googler870b38e2021-12-01 15:54:08 +0000128// Matches an RsType or CcType that has the given name.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000129MATCHER_P(NameIs, name, "") {
130 if (arg.name == name) return true;
Googlerf09ef0e2021-09-17 12:13:45 +0000131
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000132 *result_listener << "actual name: '" << arg.name << "'";
Googlerf09ef0e2021-09-17 12:13:45 +0000133 return false;
134}
135
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700136// Matches text for comments.
137MATCHER_P(TextIs, text, "") {
138 if (arg.text == text) return true;
139
140 *result_listener << "actual text: '" << arg.text << "'";
141 return false;
142}
143
Googler870b38e2021-12-01 15:54:08 +0000144// Matches an RsType or CcType that has the given decl_id.
145MATCHER_P(DeclIdIs, decl_id, "") {
Dmitri Gribenko57ddcf92022-07-20 10:24:33 -0700146 if (arg.decl_id.has_value() && *arg.decl_id == decl_id) return true;
Googler870b38e2021-12-01 15:54:08 +0000147
148 *result_listener << "actual decl_id: ";
Dmitri Gribenko57ddcf92022-07-20 10:24:33 -0700149 if (arg.decl_id.has_value()) {
Googler870b38e2021-12-01 15:54:08 +0000150 *result_listener << *arg.decl_id;
151 } else {
152 *result_listener << "std::nullopt";
153 }
154 return false;
155}
156
157// Matches an RsType or CcType that is const .
158MATCHER(IsConst, "") { return arg.is_const; }
159
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000160// Matches a MappedType with a CcType that matches all given matchers.
Googlerf09ef0e2021-09-17 12:13:45 +0000161template <typename... Args>
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000162auto CcTypeIs(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000163 return testing::Field("cc_type", &MappedType::cc_type, AllOf(matchers...));
Googlerf09ef0e2021-09-17 12:13:45 +0000164}
165
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000166// Matches a MappedType with a RsType that matches all given matchers.
167template <typename... Args>
168auto RsTypeIs(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000169 return testing::Field("rs_type", &MappedType::rs_type, AllOf(matchers...));
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000170}
171
Googlerff7fc232021-12-02 09:43:00 +0000172// Matches an RsType that has type arguments matching `matchers`.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000173template <typename... Args>
174auto RsTypeParamsAre(const Args&... matchers) {
Googlerff7fc232021-12-02 09:43:00 +0000175 return testing::Field("type_args", &RsType::type_args,
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000176 ElementsAre(matchers...));
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000177}
178
Googlerff7fc232021-12-02 09:43:00 +0000179// Matches a CcType that has type arguments matching `matchers`.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000180template <typename... Args>
181auto CcTypeParamsAre(const Args&... matchers) {
Googlerff7fc232021-12-02 09:43:00 +0000182 return testing::Field("type_args", &CcType::type_args,
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000183 ElementsAre(matchers...));
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000184}
185
186auto IsCcInt() { return AllOf(NameIs("int"), CcTypeParamsAre()); }
187
Lukasz Anforowicz460e4272023-05-18 16:11:46 -0700188auto IsRsInt() {
189 return AllOf(NameIs("::core::ffi::c_int"), RsTypeParamsAre());
190}
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000191
192// Matches a CcType that is a pointer to a type matching `matcher`.
193template <typename Matcher>
194auto CcPointsTo(const Matcher& matcher) {
195 return AllOf(NameIs("*"), CcTypeParamsAre(matcher));
196}
197
Googler61dce3b2021-12-02 09:16:32 +0000198template <typename Matcher>
199auto CcReferenceTo(const Matcher& matcher) {
200 return AllOf(NameIs("&"), CcTypeParamsAre(matcher));
201}
202
Googler870b38e2021-12-01 15:54:08 +0000203// Matches an RsType that is a mutable pointer to a type matching `matcher`.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000204template <typename Matcher>
205auto RsPointsTo(const Matcher& matcher) {
206 return AllOf(NameIs("*mut"), RsTypeParamsAre(matcher));
207}
208
Googler870b38e2021-12-01 15:54:08 +0000209// Matches an RsType that is a const pointer to a type matching `matcher`.
210template <typename Matcher>
211auto RsConstPointsTo(const Matcher& matcher) {
212 return AllOf(NameIs("*const"), RsTypeParamsAre(matcher));
213}
214
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000215// Matches a MappedType that is void.
Googler5bb23512021-09-17 12:13:27 +0000216MATCHER(IsVoid, "") { return arg.IsVoid(); }
217
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000218// Matches a MappedType that is a pointer to integer.
219auto IsIntPtr() {
220 return AllOf(CcTypeIs(CcPointsTo(IsCcInt())),
221 RsTypeIs(RsPointsTo(IsRsInt())));
Googlerf09ef0e2021-09-17 12:13:45 +0000222}
223
Googler61dce3b2021-12-02 09:16:32 +0000224// Matches a MappedType that is an lvalue reference to integer.
225auto IsIntRef() {
226 return AllOf(CcTypeIs(CcReferenceTo(IsCcInt())),
227 RsTypeIs(RsPointsTo(IsRsInt())));
228}
229
Googler5bb23512021-09-17 12:13:27 +0000230// Matches a Record that has fields matching `matchers`.
231template <typename... Args>
232auto FieldsAre(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000233 return testing::Field("fields", &Record::fields, ElementsAre(matchers...));
Googler5bb23512021-09-17 12:13:27 +0000234}
235
Googler6986c072021-09-17 13:54:56 +0000236// Matches a Record that has the given size.
237MATCHER_P(RecordSizeIs, size, "") {
238 if (arg.size == size) return true;
239
240 *result_listener << "actual size: " << arg.size;
241 return false;
242}
243
244// Matches a Record that has the given alignment.
245MATCHER_P(AlignmentIs, alignment, "") {
246 if (arg.alignment == alignment) return true;
247
248 *result_listener << "actual alignment: " << arg.alignment;
249 return false;
250}
251
Devin Jeanpierre07931272021-10-05 11:40:13 +0000252// Matches a Record with a copy_constructor that matches all given matchers.
253template <typename... Args>
254auto CopyConstructor(const Args&... matchers) {
255 return testing::Field("copy_constructor", &Record::copy_constructor,
256 AllOf(matchers...));
257}
258
259// Matches a Record with a move_constructor that matches all given matchers.
260template <typename... Args>
261auto MoveConstructor(const Args&... matchers) {
262 return testing::Field("move_constructor", &Record::move_constructor,
263 AllOf(matchers...));
264}
265
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000266// Matches a Record with a destructor that matches all given matchers.
267template <typename... Args>
268auto Destructor(const Args&... matchers) {
269 return testing::Field("destructor", &Record::destructor, AllOf(matchers...));
270}
271
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000272// Matches a Record which is trivial for calls.
273MATCHER(IsTrivialAbi, "") { return arg.is_trivial_abi; }
274
Googler6986c072021-09-17 13:54:56 +0000275// Matches a Field that has the given offset.
276MATCHER_P(OffsetIs, offset, "") {
277 if (arg.offset == offset) return true;
278
279 *result_listener << "actual offset: " << arg.offset;
280 return false;
281}
282
Googlerf09ef0e2021-09-17 12:13:45 +0000283// Matches a Field with a type that matches all given matchers.
284template <typename... Args>
285auto FieldType(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000286 return testing::Field("type", &Field::type, AllOf(matchers...));
Googlerf09ef0e2021-09-17 12:13:45 +0000287}
288
Googlerdcca7f72022-01-10 12:30:43 +0000289// Return the items from `ir` without predefined builtin types.
290decltype(IR::items) ItemsWithoutBuiltins(const IR& ir) {
291 decltype(IR::items) items;
292
293 for (const auto& item : ir.items) {
294 if (const auto* type_alias = std::get_if<TypeAlias>(&item)) {
295 if (type_alias->identifier.Ident() == "__builtin_ms_va_list") {
296 continue;
297 }
298 }
299 items.push_back(item);
300 }
301
302 return items;
303}
304
Michael Forster360351c2022-01-27 17:38:34 +0000305TEST(ImporterTest, Noop) {
Michael Forster7b628b12022-01-27 17:48:57 +0000306 // Nothing interesting there, but also not empty, so that the header gets
307 // generated.
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700308 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({" "}));
Michael Forster3f323be2021-10-11 07:13:28 +0000309
Googlerdcca7f72022-01-10 12:30:43 +0000310 EXPECT_THAT(ItemsWithoutBuiltins(ir), IsEmpty());
Marcel Hlopko7d739792021-08-12 07:52:47 +0000311}
312
Michael Forster360351c2022-01-27 17:38:34 +0000313TEST(ImporterTest, ErrorOnInvalidInput) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700314 ASSERT_THAT(IrFromCc({"int foo(); But this is not C++"}),
Michael Forster3f323be2021-10-11 07:13:28 +0000315 StatusIs(absl::StatusCode::kInvalidArgument));
Marcel Hlopko19f2ebf2021-08-18 09:35:05 +0000316}
317
Michael Forster360351c2022-01-27 17:38:34 +0000318TEST(ImporterTest, FuncWithVoidReturnType) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700319 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo();"}));
Googlerdcca7f72022-01-10 12:30:43 +0000320 EXPECT_THAT(ItemsWithoutBuiltins(ir),
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700321 UnorderedElementsAre(VariantWith<Func>(
Googlerdcca7f72022-01-10 12:30:43 +0000322 AllOf(IdentifierIs("Foo"), MangledNameIs("_Z3Foov"),
323 ReturnType(IsVoid()), ParamsAre()))));
Marcel Hlopko7d739792021-08-12 07:52:47 +0000324}
325
Michael Forster360351c2022-01-27 17:38:34 +0000326TEST(ImporterTest, TwoFuncs) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700327 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo(); void Bar();"}));
Michael Forster7ef80732021-10-01 18:12:19 +0000328 EXPECT_THAT(
Googlerdcca7f72022-01-10 12:30:43 +0000329 ItemsWithoutBuiltins(ir),
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700330 UnorderedElementsAre(
Michael Forster7ef80732021-10-01 18:12:19 +0000331 VariantWith<Func>(AllOf(IdentifierIs("Foo"), MangledNameIs("_Z3Foov"),
332 ReturnType(IsVoid()), ParamsAre())),
333 VariantWith<Func>(AllOf(IdentifierIs("Bar"), MangledNameIs("_Z3Barv"),
334 ReturnType(IsVoid()), ParamsAre()))));
Marcel Hlopko7d739792021-08-12 07:52:47 +0000335}
336
Michael Forster360351c2022-01-27 17:38:34 +0000337TEST(ImporterTest, TwoFuncsFromTwoHeaders) {
Marcel Hlopko7aa38a72021-11-11 07:39:51 +0000338 ASSERT_OK_AND_ASSIGN(
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700339 IR ir,
340 IrFromCc({.current_target = BazelLabel{"//two_funcs:one_target"},
341 .public_headers = {HeaderName("test/testing_header_0.h"),
342 HeaderName("test/testing_header_1.h")},
343 .virtual_headers_contents_for_testing =
344 {{HeaderName("test/testing_header_0.h"), "void Foo();"},
345 {HeaderName("test/testing_header_1.h"), "void Bar();"}},
346 .headers_to_targets = {
347 {HeaderName("test/testing_header_0.h"),
348 BazelLabel{"//two_funcs:one_target"}},
349 {HeaderName("test/testing_header_1.h"),
350 BazelLabel{"//two_funcs:one_target"}},
351 }}));
Googlerdcca7f72022-01-10 12:30:43 +0000352 EXPECT_THAT(ItemsWithoutBuiltins(ir),
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700353 UnorderedElementsAre(VariantWith<Func>(IdentifierIs("Foo")),
354 VariantWith<Func>(IdentifierIs("Bar"))));
Marcel Hlopkof1123c82021-08-19 11:38:52 +0000355}
356
Michael Forster360351c2022-01-27 17:38:34 +0000357TEST(ImporterTest, NonInlineFunc) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700358 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo() {}"}));
Googlerdcca7f72022-01-10 12:30:43 +0000359 EXPECT_THAT(ItemsWithoutBuiltins(ir),
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700360 UnorderedElementsAre(VariantWith<Func>(
Googlerdcca7f72022-01-10 12:30:43 +0000361 AllOf(IdentifierIs("Foo"), Not(IsInline())))));
Marcel Hlopko3164eee2021-08-24 20:09:22 +0000362}
363
Michael Forster360351c2022-01-27 17:38:34 +0000364TEST(ImporterTest, InlineFunc) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700365 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"inline void Foo() {}"}));
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700366 EXPECT_THAT(ItemsWithoutBuiltins(ir),
367 UnorderedElementsAre(
368 VariantWith<Func>(AllOf(IdentifierIs("Foo"), IsInline()))));
Marcel Hlopko3164eee2021-08-24 20:09:22 +0000369}
370
Michael Forster360351c2022-01-27 17:38:34 +0000371TEST(ImporterTest, FuncJustOnce) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700372 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo(); void Foo();"}));
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700373 EXPECT_THAT(
374 ItemsWithoutBuiltins(ir),
375 UnorderedElementsAre(VariantWith<Func>(AllOf(IdentifierIs("Foo")))));
Marcel Hlopko7d739792021-08-12 07:52:47 +0000376}
377
Michael Forster360351c2022-01-27 17:38:34 +0000378TEST(ImporterTest, TestImportPointerFunc) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700379 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"int* Foo(int* a);"}));
Devin Jeanpierre5c87a722021-09-16 10:35:58 +0000380
Googlerdcca7f72022-01-10 12:30:43 +0000381 EXPECT_THAT(ItemsWithoutBuiltins(ir),
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700382 UnorderedElementsAre(VariantWith<Func>(AllOf(
Michael Forster7ef80732021-10-01 18:12:19 +0000383 ReturnType(IsIntPtr()), ParamsAre(ParamType(IsIntPtr()))))));
Devin Jeanpierre5c87a722021-09-16 10:35:58 +0000384}
385
Michael Forster360351c2022-01-27 17:38:34 +0000386TEST(ImporterTest, TestImportConstStructPointerFunc) {
Googler870b38e2021-12-01 15:54:08 +0000387 ASSERT_OK_AND_ASSIGN(IR ir,
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700388 IrFromCc({"struct S{}; const S* Foo(const S* s);"}));
Googler870b38e2021-12-01 15:54:08 +0000389
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000390 std::optional<ItemId> decl_id = DeclIdForRecord(ir, "S");
Googler870b38e2021-12-01 15:54:08 +0000391 ASSERT_TRUE(decl_id.has_value());
392
393 auto is_ptr_to_const_s =
394 AllOf(CcTypeIs(CcPointsTo(AllOf(DeclIdIs(*decl_id), IsConst()))),
395 RsTypeIs(RsConstPointsTo(DeclIdIs(*decl_id))));
396
397 EXPECT_THAT(ir.items, Contains(VariantWith<Func>(AllOf(
398 IdentifierIs("Foo"), ReturnType(is_ptr_to_const_s),
399 ParamsAre(ParamType(is_ptr_to_const_s))))));
400}
401
Michael Forster360351c2022-01-27 17:38:34 +0000402TEST(ImporterTest, TestImportReferenceFunc) {
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700403 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"int& Foo(int& a);"}));
Googler61dce3b2021-12-02 09:16:32 +0000404
Googlerdcca7f72022-01-10 12:30:43 +0000405 EXPECT_THAT(ItemsWithoutBuiltins(ir),
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700406 UnorderedElementsAre(VariantWith<Func>(AllOf(
Googler61dce3b2021-12-02 09:16:32 +0000407 ReturnType(IsIntRef()), ParamsAre(ParamType(IsIntRef()))))));
408}
409
Michael Forster360351c2022-01-27 17:38:34 +0000410TEST(ImporterTest, TrivialCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000411 absl::string_view file = R"cc(
412 struct Implicit {};
413 struct Defaulted {
414 Defaulted(const Defaulted&) = default;
415 };
416 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700417 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000418
Googler1661eee2021-12-01 12:36:19 +0000419 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000420 EXPECT_THAT(records, SizeIs(2));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700421 EXPECT_THAT(records,
422 Each(Pointee(CopyConstructor(SpecialMemberFunc::kTrivial))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000423}
424
Michael Forster360351c2022-01-27 17:38:34 +0000425TEST(ImporterTest, NontrivialUserDefinedCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000426 absl::string_view file = R"cc(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000427 struct NontrivialUserDefined {
428 NontrivialUserDefined(const NontrivialUserDefined&);
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000429 };
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000430 struct NontrivialSub : public NontrivialUserDefined {};
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000431
432 // Despite having a defaulted copy constructor, this is not trivially
433 // copyable, because the *first* declaration is not defaulted.
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000434 struct NontrivialUserDefinedDefaulted {
435 NontrivialUserDefinedDefaulted(const NontrivialUserDefinedDefaulted&);
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000436 };
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000437 inline NontrivialUserDefinedDefaulted::NontrivialUserDefinedDefaulted(
438 const NontrivialUserDefinedDefaulted&) = default;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000439 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700440 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000441
Googler1661eee2021-12-01 12:36:19 +0000442 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000443 EXPECT_THAT(records, SizeIs(3));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700444 EXPECT_THAT(records, Each(Pointee(CopyConstructor(
445 SpecialMemberFunc::kNontrivialUserDefined))));
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000446}
447
Michael Forster360351c2022-01-27 17:38:34 +0000448TEST(ImporterTest, NontrivialMembersCopyConstructor) {
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000449 absl::string_view file = R"cc(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000450 struct NontrivialUserDefined {
451 NontrivialUserDefined(const NontrivialUserDefined&);
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000452 };
453 struct MemberImplicit {
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000454 NontrivialUserDefined x;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000455 };
456 struct MemberDefaulted {
457 MemberDefaulted(const MemberDefaulted&) = default;
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000458 NontrivialUserDefined x;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000459 };
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000460 struct Subclass : public MemberImplicit {};
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000461 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700462 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Googler1661eee2021-12-01 12:36:19 +0000463 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000464 EXPECT_THAT(records, SizeIs(4));
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000465 EXPECT_THAT(
466 records,
467 Each(Pointee(AnyOf(
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +0000468 RsNameIs(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000469 "NontrivialUserDefined"), // needed to create nontrivial members
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700470 CopyConstructor(SpecialMemberFunc::kNontrivialMembers)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000471}
472
Michael Forster360351c2022-01-27 17:38:34 +0000473TEST(ImporterTest, DeletedCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000474 absl::string_view file = R"cc(
475 struct Deleted {
476 Deleted(const Deleted&) = delete;
477 };
478 struct DeletedByMember {
479 Deleted x;
480 };
481 struct DeletedByCtorDef {
482 DeletedByCtorDef(DeletedByCtorDef&&) {}
483 };
484 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700485 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Googler1661eee2021-12-01 12:36:19 +0000486 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000487 EXPECT_THAT(records, SizeIs(3));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700488 EXPECT_THAT(records,
489 Each(Pointee(CopyConstructor(SpecialMemberFunc::kUnavailable))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000490}
491
Michael Forster360351c2022-01-27 17:38:34 +0000492TEST(ImporterTest, PublicCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000493 absl::string_view file = R"cc(
494 class Implicit {};
495 struct Defaulted {
496 Defaulted(const Defaulted&) = default;
497 };
498 class Section {
499 public:
500 Section(const Section&) = default;
501 };
502 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700503 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000504
Googler1661eee2021-12-01 12:36:19 +0000505 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000506 EXPECT_THAT(records, SizeIs(3));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700507 EXPECT_THAT(records,
508 Each(Pointee(CopyConstructor(SpecialMemberFunc::kTrivial))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000509}
510
Michael Forster360351c2022-01-27 17:38:34 +0000511TEST(ImporterTest, PrivateCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000512 absl::string_view file = R"cc(
513 class Defaulted {
514 Defaulted(const Defaulted&) = default;
515 };
516 struct Section {
517 private:
518 Section(const Section&) = default;
519 };
520 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700521 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000522
Googler1661eee2021-12-01 12:36:19 +0000523 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000524 EXPECT_THAT(records, SizeIs(2));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700525 EXPECT_THAT(records,
526 Each(Pointee(CopyConstructor(SpecialMemberFunc::kUnavailable))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000527}
528
Michael Forster360351c2022-01-27 17:38:34 +0000529TEST(ImporterTest, TrivialMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000530 absl::string_view file = R"cc(
531 struct Implicit {};
532 struct Defaulted {
533 Defaulted(Defaulted&&) = default;
534 };
535 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700536 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000537
Googler1661eee2021-12-01 12:36:19 +0000538 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000539 EXPECT_THAT(records, SizeIs(2));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700540 EXPECT_THAT(records,
541 Each(Pointee(MoveConstructor(SpecialMemberFunc::kTrivial))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000542}
543
Michael Forster360351c2022-01-27 17:38:34 +0000544TEST(ImporterTest, NontrivialUserDefinedMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000545 absl::string_view file = R"cc(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000546 struct NontrivialUserDefined {
547 NontrivialUserDefined(NontrivialUserDefined&&);
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000548 };
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000549 struct NontrivialSub : public NontrivialUserDefined {};
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000550
551 // Despite having a defaulted move constructor, this is not trivially
552 // movable, because the *first* declaration is not defaulted.
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000553 struct NontrivialUserDefinedDefaulted {
554 NontrivialUserDefinedDefaulted(NontrivialUserDefinedDefaulted&&);
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000555 };
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000556 inline NontrivialUserDefinedDefaulted::NontrivialUserDefinedDefaulted(
557 NontrivialUserDefinedDefaulted&&) = default;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000558 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700559 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Googler1661eee2021-12-01 12:36:19 +0000560 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000561 EXPECT_THAT(records, SizeIs(3));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700562 EXPECT_THAT(records, Each(Pointee(MoveConstructor(
563 SpecialMemberFunc::kNontrivialUserDefined))));
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000564}
565
Michael Forster360351c2022-01-27 17:38:34 +0000566TEST(ImporterTest, NontrivialMembersMoveConstructor) {
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000567 absl::string_view file = R"cc(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000568 struct NontrivialUserDefined {
569 NontrivialUserDefined(NontrivialUserDefined&&);
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000570 };
571 struct MemberImplicit {
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000572 NontrivialUserDefined x;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000573 };
574 struct MemberDefaulted {
575 MemberDefaulted(MemberDefaulted&&) = default;
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000576 NontrivialUserDefined x;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000577 };
578 struct Subclass : public MemberImplicit {};
579 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700580 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Googler1661eee2021-12-01 12:36:19 +0000581 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000582 EXPECT_THAT(records, SizeIs(4));
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000583 EXPECT_THAT(
584 records,
585 Each(Pointee(AnyOf(
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +0000586 RsNameIs(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000587 "NontrivialUserDefined"), // needed to create nontrivial members
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700588 MoveConstructor(SpecialMemberFunc::kNontrivialMembers)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000589}
590
Michael Forster360351c2022-01-27 17:38:34 +0000591TEST(ImporterTest, DeletedMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000592 absl::string_view file = R"cc(
593 struct Deleted {
594 Deleted(Deleted&&) = delete;
595 };
596 struct DeletedByMember {
597 Deleted x;
598 };
599 struct SuppressedByCtorDef {
600 SuppressedByCtorDef(const SuppressedByCtorDef&) {}
601 };
602 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700603 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Googler1661eee2021-12-01 12:36:19 +0000604 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000605 EXPECT_THAT(records, SizeIs(3));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700606 EXPECT_THAT(records,
607 Each(Pointee(MoveConstructor(SpecialMemberFunc::kUnavailable))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000608}
609
Michael Forster360351c2022-01-27 17:38:34 +0000610TEST(ImporterTest, PublicMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000611 absl::string_view file = R"cc(
612 class Implicit {};
613 struct Defaulted {
614 Defaulted(Defaulted&&) = default;
615 };
616 class Section {
617 public:
618 Section(Section&&) = default;
619 };
620 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700621 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000622
Googler1661eee2021-12-01 12:36:19 +0000623 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000624 EXPECT_THAT(records, SizeIs(3));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700625 EXPECT_THAT(records,
626 Each(Pointee(MoveConstructor(SpecialMemberFunc::kTrivial))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000627}
628
Michael Forster360351c2022-01-27 17:38:34 +0000629TEST(ImporterTest, PrivateMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000630 absl::string_view file = R"cc(
631 class Defaulted {
632 Defaulted(Defaulted&&) = default;
633 };
634 struct Section {
635 private:
636 Section(Section&&) = default;
637 };
638 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700639 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000640
Googler1661eee2021-12-01 12:36:19 +0000641 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000642 EXPECT_THAT(records, SizeIs(2));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700643 EXPECT_THAT(records,
644 Each(Pointee(MoveConstructor(SpecialMemberFunc::kUnavailable))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000645}
646
Michael Forster360351c2022-01-27 17:38:34 +0000647TEST(ImporterTest, TrivialDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000648 absl::string_view file = R"cc(
649 struct Implicit {};
650 struct Defaulted {
651 ~Defaulted() = default;
652 };
653 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700654 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000655
Googler1661eee2021-12-01 12:36:19 +0000656 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000657 EXPECT_THAT(records, SizeIs(2));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700658 EXPECT_THAT(records, Each(Pointee(Destructor(SpecialMemberFunc::kTrivial))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000659}
660
Michael Forster360351c2022-01-27 17:38:34 +0000661TEST(ImporterTest, NontrivialUserDefinedDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000662 absl::string_view file = R"cc(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000663 struct NontrivialUserDefined {
664 ~NontrivialUserDefined();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000665 };
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000666 struct NontrivialSub : public NontrivialUserDefined {};
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000667
668 // Despite having a defaulted destructor, this is not trivially
Devin Jeanpierre96839c12021-12-14 00:27:38 +0000669 // destructible, because the destructor is virtual.
670 struct VirtualDestructor {
671 virtual ~VirtualDestructor() = default;
672 };
673
674 // Despite having a defaulted destructor, this is not trivially
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000675 // destructible, because the *first* declaration is not defaulted.
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000676 struct NontrivialUserDefinedDefaulted {
677 ~NontrivialUserDefinedDefaulted();
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000678 };
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000679 inline NontrivialUserDefinedDefaulted::~NontrivialUserDefinedDefaulted() =
680 default;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000681 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700682 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Googler1661eee2021-12-01 12:36:19 +0000683 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierre96839c12021-12-14 00:27:38 +0000684 EXPECT_THAT(records, SizeIs(4));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700685 EXPECT_THAT(
686 records,
687 Each(Pointee(Destructor(SpecialMemberFunc::kNontrivialUserDefined))));
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000688}
689
Michael Forster360351c2022-01-27 17:38:34 +0000690TEST(ImporterTest, NontrivialMembersDestructor) {
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000691 absl::string_view file = R"cc(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000692 struct NontrivialUserDefined {
693 ~NontrivialUserDefined();
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000694 };
695 struct MemberImplicit {
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000696 NontrivialUserDefined x;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000697 };
698 struct MemberDefaulted {
699 MemberDefaulted(MemberDefaulted&&) = default;
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000700 NontrivialUserDefined x;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000701 };
702 struct Subclass : public MemberImplicit {};
703 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700704 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Googler1661eee2021-12-01 12:36:19 +0000705 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000706 EXPECT_THAT(records, SizeIs(4));
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000707 EXPECT_THAT(
708 records,
709 Each(Pointee(AnyOf(
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +0000710 RsNameIs(
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000711 "NontrivialUserDefined"), // needed to create nontrivial members
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700712 Destructor(SpecialMemberFunc::kNontrivialMembers)))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000713}
714
Michael Forster360351c2022-01-27 17:38:34 +0000715TEST(ImporterTest, DeletedDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000716 absl::string_view file = R"cc(
717 struct Deleted {
718 ~Deleted() = delete;
719 };
720 struct DeletedByMember {
721 Deleted x;
722 };
723 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700724 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000725
Googler1661eee2021-12-01 12:36:19 +0000726 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000727 EXPECT_THAT(records, SizeIs(2));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700728 EXPECT_THAT(records,
729 Each(Pointee(Destructor(SpecialMemberFunc::kUnavailable))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000730}
731
Michael Forster360351c2022-01-27 17:38:34 +0000732TEST(ImporterTest, PublicDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000733 absl::string_view file = R"cc(
734 class Implicit {};
735 struct Defaulted {
736 ~Defaulted() = default;
737 };
738 class Section {
739 public:
740 ~Section() = default;
741 };
742 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700743 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000744
Googler1661eee2021-12-01 12:36:19 +0000745 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000746 EXPECT_THAT(records, SizeIs(3));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700747 EXPECT_THAT(records, Each(Pointee(Destructor(SpecialMemberFunc::kTrivial))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000748}
749
Michael Forster360351c2022-01-27 17:38:34 +0000750TEST(ImporterTest, PrivateDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000751 absl::string_view file = R"cc(
752 class Defaulted {
753 ~Defaulted() = default;
754 };
755 struct Section {
756 private:
757 ~Section() = default;
758 };
759 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700760 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000761
Googler1661eee2021-12-01 12:36:19 +0000762 std::vector<const Record*> records = ir.get_items_if<Record>();
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000763 EXPECT_THAT(records, SizeIs(2));
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700764 EXPECT_THAT(records,
765 Each(Pointee(Destructor(SpecialMemberFunc::kUnavailable))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000766}
767
Michael Forster360351c2022-01-27 17:38:34 +0000768TEST(ImporterTest, TrivialAbi) {
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000769 absl::string_view file = R"cc(
770 struct Empty {};
771 struct Defaulted {
772 Defaulted(const Defaulted&) = default;
773 };
774 struct [[clang::trivial_abi]] Nontrivial {
775 Nontrivial(const Nontrivial&) {}
776 };
777 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700778 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000779
Googler1661eee2021-12-01 12:36:19 +0000780 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000781 EXPECT_THAT(records, SizeIs(3));
782 EXPECT_THAT(records, Each(Pointee(IsTrivialAbi())));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000783}
784
Michael Forster360351c2022-01-27 17:38:34 +0000785TEST(ImporterTest, NotTrivialAbi) {
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000786 absl::string_view file = R"cc(
787 struct Nontrivial {
788 Nontrivial(const Nontrivial&) {}
789 };
790 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700791 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000792
Googler1661eee2021-12-01 12:36:19 +0000793 std::vector<const Record*> records = ir.get_items_if<Record>();
Michael Forster523dbd42021-10-12 11:05:44 +0000794 EXPECT_THAT(records, SizeIs(1));
795 EXPECT_THAT(records, Each(Pointee(Not(IsTrivialAbi()))));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000796}
797
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700798TEST(ImporterTest, TopLevelItemIds) {
799 absl::string_view file = R"cc(
800 struct TopLevelStruct {};
801 // Top level comment
802
803 // Function comment
804 void top_level_func();
805 namespace top_level_namespace {
806 struct Nested {};
807 // free nested comment
808
809 // nested_func comment
810 void nested_func();
811 } // namespace top_level_namespace
812 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700813 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700814
815 std::vector<IR::Item> items;
816 for (const auto& id : ir.top_level_item_ids) {
817 auto item = FindItemById(ir, id);
818 ASSERT_TRUE(item.has_value());
819 items.push_back(*item);
820 }
821
822 EXPECT_THAT(ir.top_level_item_ids, SizeIs(5));
823 EXPECT_THAT(
824 items,
825 ElementsAre(
826 VariantWith<Record>(RsNameIs("TopLevelStruct")),
827 VariantWith<Comment>(TextIs("Top level comment")),
828 VariantWith<Func>(IdentifierIs("top_level_func")),
Rosica Dejanovska09aa6362022-08-24 05:41:09 -0700829 VariantWith<Namespace>(IdentifierIs("top_level_namespace")),
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700830 VariantWith<Comment>(TextIs("namespace top_level_namespace"))));
831}
832
833TEST(ImporterTest, RecordItemIds) {
834 absl::string_view file = R"cc(
835 struct TopLevelStruct {
836 // A free comment
837
838 // foo comment
839 int foo;
840
841 int bar();
842 struct Nested {};
843 int baz();
844 };
845 )cc";
Devin Jeanpierreb0af4dc2023-04-27 06:59:25 -0700846 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700847
848 std::vector<const Record*> records = ir.get_items_if<Record>();
849 EXPECT_THAT(records, SizeIs(1));
850
851 std::vector<IR::Item> items;
852 for (const auto& id : records[0]->child_item_ids) {
853 auto item = FindItemById(ir, id);
854 ASSERT_TRUE(item.has_value());
855 items.push_back(*item);
856 }
857
858 EXPECT_THAT(items,
859 AllOf(Contains(VariantWith<Comment>(TextIs("A free comment"))),
860 Contains(VariantWith<Func>(IdentifierIs("bar"))),
861 Contains(VariantWith<UnsupportedItem>(
862 NameIs("TopLevelStruct::Nested"))),
863 Contains(VariantWith<Func>(IdentifierIs("baz")))));
864}
865
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +0000866} // namespace
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -0700867} // namespace crubit