blob: c6ff67a7ab299d95f9bec04ae7b55c6b13868510 [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
5#include <memory>
6#include <string>
Marcel Hlopkof1123c82021-08-19 11:38:52 +00007#include <utility>
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +00008#include <vector>
9
Marcel Hlopko7d739792021-08-12 07:52:47 +000010#include "rs_bindings_from_cc/ir.h"
Googler741ed9c2021-10-01 08:00:49 +000011#include "rs_bindings_from_cc/ir_from_cc.h"
Marcel Hlopko7d739792021-08-12 07:52:47 +000012#include "testing/base/public/gmock.h"
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000013#include "testing/base/public/gunit.h"
Marcel Hlopkof1123c82021-08-19 11:38:52 +000014#include "third_party/absl/container/flat_hash_map.h"
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000015#include "third_party/absl/strings/string_view.h"
Marcel Hlopkof1123c82021-08-19 11:38:52 +000016#include "third_party/absl/strings/substitute.h"
17#include "third_party/absl/types/span.h"
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000018
19namespace rs_bindings_from_cc {
20namespace {
21
Googler5bb23512021-09-17 12:13:27 +000022using ::testing::AllOf;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +000023using ::testing::AnyOf;
Michael Forster523dbd42021-10-12 11:05:44 +000024using ::testing::Each;
Googler5bb23512021-09-17 12:13:27 +000025using ::testing::ElementsAre;
Marcel Hlopko7d739792021-08-12 07:52:47 +000026using ::testing::IsEmpty;
Googler5bb23512021-09-17 12:13:27 +000027using ::testing::Not;
Michael Forster523dbd42021-10-12 11:05:44 +000028using ::testing::Pointee;
Googler5bb23512021-09-17 12:13:27 +000029using ::testing::Property;
Marcel Hlopko7d739792021-08-12 07:52:47 +000030using ::testing::SizeIs;
Michael Forster7ef80732021-10-01 18:12:19 +000031using ::testing::VariantWith;
Michael Forster3f323be2021-10-11 07:13:28 +000032using ::testing::status::StatusIs;
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000033
Devin Jeanpierref2ec8712021-10-13 20:47:16 +000034template <typename T>
35UnqualifiedIdentifier GetName(const T& x) {
36 return x.identifier;
37}
38UnqualifiedIdentifier GetName(const Func& x) { return x.name; }
39
Googler5bb23512021-09-17 12:13:27 +000040// Matches an IR node that has the given identifier.
41MATCHER_P(IdentifierIs, identifier, "") {
Devin Jeanpierref2ec8712021-10-13 20:47:16 +000042 UnqualifiedIdentifier name = GetName(arg);
43 const Identifier* actual = std::get_if<Identifier>(&name);
44 if (actual == nullptr) {
45 *result_listener << "actual name not an identifier.";
46 return false;
47 }
48 if (actual->Ident() == identifier) return true;
Googler5bb23512021-09-17 12:13:27 +000049
Devin Jeanpierref2ec8712021-10-13 20:47:16 +000050 *result_listener << "actual identifier: '" << actual->Ident() << "'";
Googler5bb23512021-09-17 12:13:27 +000051 return false;
52}
53
Michael Forster028800b2021-10-05 12:39:59 +000054// Matches an IR node that has the given doc comment.
55MATCHER_P(DocCommentIs, doc_comment, "") {
56 if (arg.doc_comment && *arg.doc_comment == doc_comment) return true;
57
58 *result_listener << "actual doc comment: '"
59 << (arg.doc_comment ? *arg.doc_comment : "<none>") << "'";
60 return false;
61}
62
Googler5bb23512021-09-17 12:13:27 +000063// Matches a Func that has the given mangled name.
64MATCHER_P(MangledNameIs, mangled_name, "") {
65 if (arg.mangled_name == mangled_name) return true;
66
67 *result_listener << "actual mangled name: '" << arg.mangled_name << "'";
68 return false;
69}
70
71// Matches a Func that has a return type matching `matcher`.
72template <typename Matcher>
73auto ReturnType(const Matcher& matcher) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +000074 return testing::Field("return_type", &Func::return_type, matcher);
Googler5bb23512021-09-17 12:13:27 +000075}
76
77// Matches a Func that has parameters matching `matchers`.
78template <typename... Args>
79auto ParamsAre(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +000080 return testing::Field("params", &Func::params, ElementsAre(matchers...));
Googler5bb23512021-09-17 12:13:27 +000081}
82
83// Matches a Func that is inline.
84MATCHER(IsInline, "") { return arg.is_inline; }
85
Googlerf09ef0e2021-09-17 12:13:45 +000086// Matches a FuncParam with a type that matches all given matchers.
87template <typename... Args>
88auto ParamType(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +000089 return testing::Field("type", &FuncParam::type, AllOf(matchers...));
Googlerf09ef0e2021-09-17 12:13:45 +000090}
91
Devin Jeanpierre09c6f452021-09-29 07:34:24 +000092// Matches a RsType or CcType that has the given name.
93MATCHER_P(NameIs, name, "") {
94 if (arg.name == name) return true;
Googlerf09ef0e2021-09-17 12:13:45 +000095
Devin Jeanpierre09c6f452021-09-29 07:34:24 +000096 *result_listener << "actual name: '" << arg.name << "'";
Googlerf09ef0e2021-09-17 12:13:45 +000097 return false;
98}
99
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000100// Matches a MappedType with a CcType that matches all given matchers.
Googlerf09ef0e2021-09-17 12:13:45 +0000101template <typename... Args>
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000102auto CcTypeIs(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000103 return testing::Field("cc_type", &MappedType::cc_type, AllOf(matchers...));
Googlerf09ef0e2021-09-17 12:13:45 +0000104}
105
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000106// Matches a MappedType with a RsType that matches all given matchers.
107template <typename... Args>
108auto RsTypeIs(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000109 return testing::Field("rs_type", &MappedType::rs_type, AllOf(matchers...));
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000110}
111
Devin Jeanpierrecb0277b2021-09-29 07:44:29 +0000112// Matches an RsType that has type parameters matching `matchers`.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000113template <typename... Args>
114auto RsTypeParamsAre(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000115 return testing::Field("type_params", &RsType::type_params,
116 ElementsAre(matchers...));
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000117}
118
Devin Jeanpierrecb0277b2021-09-29 07:44:29 +0000119// Matches a CcType that has type parameters matching `matchers`.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000120template <typename... Args>
121auto CcTypeParamsAre(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000122 return testing::Field("type_params", &CcType::type_params,
123 ElementsAre(matchers...));
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000124}
125
126auto IsCcInt() { return AllOf(NameIs("int"), CcTypeParamsAre()); }
127
128auto IsRsInt() { return AllOf(NameIs("i32"), RsTypeParamsAre()); }
129
130// Matches a CcType that is a pointer to a type matching `matcher`.
131template <typename Matcher>
132auto CcPointsTo(const Matcher& matcher) {
133 return AllOf(NameIs("*"), CcTypeParamsAre(matcher));
134}
135
136// Matches an RsType that is a pointer to a type matching `matcher`.
137template <typename Matcher>
138auto RsPointsTo(const Matcher& matcher) {
139 return AllOf(NameIs("*mut"), RsTypeParamsAre(matcher));
140}
141
142// Matches a MappedType that is void.
Googler5bb23512021-09-17 12:13:27 +0000143MATCHER(IsVoid, "") { return arg.IsVoid(); }
144
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000145// Matches a MappedType that is an integer.
146auto IsInt() { return AllOf(CcTypeIs(IsCcInt()), RsTypeIs(IsRsInt())); }
147
148// Matches a MappedType that is a pointer to integer.
149auto IsIntPtr() {
150 return AllOf(CcTypeIs(CcPointsTo(IsCcInt())),
151 RsTypeIs(RsPointsTo(IsRsInt())));
Googlerf09ef0e2021-09-17 12:13:45 +0000152}
153
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000154// Matches a MappedType for cc and rs types with no type parameters.
155auto IsSimpleType(absl::string_view rs_name, absl::string_view cc_name) {
156 return AllOf(CcTypeIs(NameIs(cc_name), CcTypeParamsAre()),
157 RsTypeIs(NameIs(rs_name), RsTypeParamsAre()));
Googlerf09ef0e2021-09-17 12:13:45 +0000158}
159
Googler5bb23512021-09-17 12:13:27 +0000160// Matches a Record that has fields matching `matchers`.
161template <typename... Args>
162auto FieldsAre(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000163 return testing::Field("fields", &Record::fields, ElementsAre(matchers...));
Googler5bb23512021-09-17 12:13:27 +0000164}
165
Googler6986c072021-09-17 13:54:56 +0000166// Matches a Record that has the given size.
167MATCHER_P(RecordSizeIs, size, "") {
168 if (arg.size == size) return true;
169
170 *result_listener << "actual size: " << arg.size;
171 return false;
172}
173
174// Matches a Record that has the given alignment.
175MATCHER_P(AlignmentIs, alignment, "") {
176 if (arg.alignment == alignment) return true;
177
178 *result_listener << "actual alignment: " << arg.alignment;
179 return false;
180}
181
Devin Jeanpierre07931272021-10-05 11:40:13 +0000182// Matches a Record with a copy_constructor that matches all given matchers.
183template <typename... Args>
184auto CopyConstructor(const Args&... matchers) {
185 return testing::Field("copy_constructor", &Record::copy_constructor,
186 AllOf(matchers...));
187}
188
189// Matches a Record with a move_constructor that matches all given matchers.
190template <typename... Args>
191auto MoveConstructor(const Args&... matchers) {
192 return testing::Field("move_constructor", &Record::move_constructor,
193 AllOf(matchers...));
194}
195
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000196// Matches a Record with a destructor that matches all given matchers.
197template <typename... Args>
198auto Destructor(const Args&... matchers) {
199 return testing::Field("destructor", &Record::destructor, AllOf(matchers...));
200}
201
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000202// Matches a Record which is trivial for calls.
203MATCHER(IsTrivialAbi, "") { return arg.is_trivial_abi; }
204
Devin Jeanpierre07931272021-10-05 11:40:13 +0000205// Matches a SpecialMemberFunc that has the given definition.
206MATCHER_P(DefinitionIs, definition, "") { return arg.definition == definition; }
207
Googler5bb23512021-09-17 12:13:27 +0000208// Matches a Field that has the given access specifier.
209MATCHER_P(AccessIs, access, "") { return arg.access == access; }
210
Googler6986c072021-09-17 13:54:56 +0000211// Matches a Field that has the given offset.
212MATCHER_P(OffsetIs, offset, "") {
213 if (arg.offset == offset) return true;
214
215 *result_listener << "actual offset: " << arg.offset;
216 return false;
217}
218
Googlerf09ef0e2021-09-17 12:13:45 +0000219// Matches a Field with a type that matches all given matchers.
220template <typename... Args>
221auto FieldType(const Args&... matchers) {
Devin Jeanpierre64ca9f62021-09-30 07:10:02 +0000222 return testing::Field("type", &Field::type, AllOf(matchers...));
Googlerf09ef0e2021-09-17 12:13:45 +0000223}
224
Googler52c709b2021-09-16 07:58:29 +0000225TEST(AstVisitorTest, Noop) {
Michael Forster3f323be2021-10-11 07:13:28 +0000226 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"// nothing interesting there."}));
227
Michael Forster7ef80732021-10-01 18:12:19 +0000228 EXPECT_THAT(ir.items, IsEmpty());
Googler5bb23512021-09-17 12:13:27 +0000229 EXPECT_THAT(ir.used_headers,
230 ElementsAre(Property(&HeaderName::IncludePath,
231 "test/testing_header_0.h")));
Marcel Hlopko7d739792021-08-12 07:52:47 +0000232}
233
Michael Forster3f323be2021-10-11 07:13:28 +0000234TEST(AstVisitorTest, ErrorOnInvalidInput) {
235 ASSERT_THAT(IrFromCc({"int foo(); But this is not C++"}),
236 StatusIs(absl::StatusCode::kInvalidArgument));
Marcel Hlopko19f2ebf2021-08-18 09:35:05 +0000237}
238
Googler76b2cad2021-09-16 08:05:11 +0000239TEST(AstVisitorTest, FuncWithVoidReturnType) {
Michael Forster3f323be2021-10-11 07:13:28 +0000240 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo();"}));
Michael Forster7ef80732021-10-01 18:12:19 +0000241 EXPECT_THAT(ir.items, ElementsAre(VariantWith<Func>(
242 AllOf(IdentifierIs("Foo"), MangledNameIs("_Z3Foov"),
243 ReturnType(IsVoid()), ParamsAre()))));
Marcel Hlopko7d739792021-08-12 07:52:47 +0000244}
245
Googler76b2cad2021-09-16 08:05:11 +0000246TEST(AstVisitorTest, TwoFuncs) {
Michael Forster3f323be2021-10-11 07:13:28 +0000247 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo(); void Bar();"}));
Michael Forster7ef80732021-10-01 18:12:19 +0000248 EXPECT_THAT(
249 ir.items,
250 ElementsAre(
251 VariantWith<Func>(AllOf(IdentifierIs("Foo"), MangledNameIs("_Z3Foov"),
252 ReturnType(IsVoid()), ParamsAre())),
253 VariantWith<Func>(AllOf(IdentifierIs("Bar"), MangledNameIs("_Z3Barv"),
254 ReturnType(IsVoid()), ParamsAre()))));
Marcel Hlopko7d739792021-08-12 07:52:47 +0000255}
256
Googler76b2cad2021-09-16 08:05:11 +0000257TEST(AstVisitorTest, TwoFuncsFromTwoHeaders) {
Michael Forster3f323be2021-10-11 07:13:28 +0000258 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo();", "void Bar();"}));
Michael Forster7ef80732021-10-01 18:12:19 +0000259 EXPECT_THAT(ir.items, ElementsAre(VariantWith<Func>(IdentifierIs("Foo")),
260 VariantWith<Func>(IdentifierIs("Bar"))));
Marcel Hlopkof1123c82021-08-19 11:38:52 +0000261}
262
Googler76b2cad2021-09-16 08:05:11 +0000263TEST(AstVisitorTest, NonInlineFunc) {
Michael Forster3f323be2021-10-11 07:13:28 +0000264 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo() {}"}));
Michael Forster7ef80732021-10-01 18:12:19 +0000265 EXPECT_THAT(ir.items, ElementsAre(VariantWith<Func>(
266 AllOf(IdentifierIs("Foo"), Not(IsInline())))));
Marcel Hlopko3164eee2021-08-24 20:09:22 +0000267}
268
Googler76b2cad2021-09-16 08:05:11 +0000269TEST(AstVisitorTest, InlineFunc) {
Michael Forster3f323be2021-10-11 07:13:28 +0000270 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"inline void Foo() {}"}));
Michael Forster7ef80732021-10-01 18:12:19 +0000271 EXPECT_THAT(
272 ir.items,
273 ElementsAre(VariantWith<Func>(AllOf(IdentifierIs("Foo"), IsInline()))));
Marcel Hlopko3164eee2021-08-24 20:09:22 +0000274}
275
Googler76b2cad2021-09-16 08:05:11 +0000276TEST(AstVisitorTest, FuncJustOnce) {
Michael Forster3f323be2021-10-11 07:13:28 +0000277 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"void Foo(); void Foo();"}));
Michael Forster7ef80732021-10-01 18:12:19 +0000278 EXPECT_THAT(ir.items,
279 ElementsAre(VariantWith<Func>(AllOf(IdentifierIs("Foo")))));
Marcel Hlopko7d739792021-08-12 07:52:47 +0000280}
281
Devin Jeanpierre5c87a722021-09-16 10:35:58 +0000282TEST(AstVisitorTest, TestImportPointerFunc) {
Michael Forster3f323be2021-10-11 07:13:28 +0000283 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({"int* Foo(int* a);"}));
Devin Jeanpierre5c87a722021-09-16 10:35:58 +0000284
Michael Forster7ef80732021-10-01 18:12:19 +0000285 EXPECT_THAT(ir.items,
286 ElementsAre(VariantWith<Func>(AllOf(
287 ReturnType(IsIntPtr()), ParamsAre(ParamType(IsIntPtr()))))));
Devin Jeanpierre5c87a722021-09-16 10:35:58 +0000288}
289
Googler76b2cad2021-09-16 08:05:11 +0000290TEST(AstVisitorTest, Struct) {
Michael Forster3f323be2021-10-11 07:13:28 +0000291 ASSERT_OK_AND_ASSIGN(
292 IR ir,
293 IrFromCc({"struct SomeStruct { int first_field; int second_field; };"}));
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000294
Devin Jeanpierredf4dc8b2021-10-21 12:53:19 +0000295 std::vector<Record*> records = ir.get_items_if<Record>();
296 EXPECT_THAT(records,
297 ElementsAre(Pointee(AllOf(
Googler6986c072021-09-17 13:54:56 +0000298 IdentifierIs("SomeStruct"), RecordSizeIs(8), AlignmentIs(4),
299 FieldsAre(AllOf(IdentifierIs("first_field"),
300 FieldType(IsInt()), OffsetIs(0)),
301 AllOf(IdentifierIs("second_field"),
Michael Forster7ef80732021-10-01 18:12:19 +0000302 FieldType(IsInt()), OffsetIs(32)))))));
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000303}
304
Devin Jeanpierre07931272021-10-05 11:40:13 +0000305TEST(AstVisitorTest, TrivialCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000306 absl::string_view file = R"cc(
307 struct Implicit {};
308 struct Defaulted {
309 Defaulted(const Defaulted&) = default;
310 };
311 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000312 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000313
Michael Forster523dbd42021-10-12 11:05:44 +0000314 std::vector<Record*> records = ir.get_items_if<Record>();
315 EXPECT_THAT(records, SizeIs(2));
316 EXPECT_THAT(records, Each(Pointee(CopyConstructor(DefinitionIs(
317 SpecialMemberFunc::Definition::kTrivial)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000318}
319
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000320TEST(AstVisitorTest, NontrivialSelfCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000321 absl::string_view file = R"cc(
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000322 struct NontrivialSelf {
323 NontrivialSelf(const NontrivialSelf&);
324 };
325 struct NontrivialSub : public NontrivialSelf {};
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000326
327 // Despite having a defaulted copy constructor, this is not trivially
328 // copyable, because the *first* declaration is not defaulted.
329 struct NontrivialSelfDefaulted {
330 NontrivialSelfDefaulted(const NontrivialSelfDefaulted&);
331 };
332 inline NontrivialSelfDefaulted::NontrivialSelfDefaulted(
333 const NontrivialSelfDefaulted&) = default;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000334 )cc";
335 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
336
337 std::vector<Record*> records = ir.get_items_if<Record>();
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000338 EXPECT_THAT(records, SizeIs(3));
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000339 EXPECT_THAT(records, Each(Pointee(CopyConstructor(DefinitionIs(
340 SpecialMemberFunc::Definition::kNontrivialSelf)))));
341}
342
343TEST(AstVisitorTest, NontrivialMembersCopyConstructor) {
344 absl::string_view file = R"cc(
345 struct NontrivialSelf {
346 NontrivialSelf(const NontrivialSelf&);
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000347 };
348 struct MemberImplicit {
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000349 NontrivialSelf x;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000350 };
351 struct MemberDefaulted {
352 MemberDefaulted(const MemberDefaulted&) = default;
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000353 NontrivialSelf x;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000354 };
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000355 struct Subclass : public MemberImplicit {};
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000356 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000357 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Michael Forster523dbd42021-10-12 11:05:44 +0000358 std::vector<Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000359 EXPECT_THAT(records, SizeIs(4));
360 EXPECT_THAT(records,
361 Each(Pointee(AnyOf(
362 IdentifierIs(
363 "NontrivialSelf"), // needed to create nontrivial members
364 CopyConstructor(DefinitionIs(
365 SpecialMemberFunc::Definition::kNontrivialMembers))))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000366}
367
368TEST(AstVisitorTest, DeletedCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000369 absl::string_view file = R"cc(
370 struct Deleted {
371 Deleted(const Deleted&) = delete;
372 };
373 struct DeletedByMember {
374 Deleted x;
375 };
376 struct DeletedByCtorDef {
377 DeletedByCtorDef(DeletedByCtorDef&&) {}
378 };
379 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000380 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Michael Forster523dbd42021-10-12 11:05:44 +0000381 std::vector<Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000382 EXPECT_THAT(records, SizeIs(3));
Michael Forster523dbd42021-10-12 11:05:44 +0000383 EXPECT_THAT(records, Each(Pointee(CopyConstructor(DefinitionIs(
384 SpecialMemberFunc::Definition::kDeleted)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000385}
386
387TEST(AstVisitorTest, PublicCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000388 absl::string_view file = R"cc(
389 class Implicit {};
390 struct Defaulted {
391 Defaulted(const Defaulted&) = default;
392 };
393 class Section {
394 public:
395 Section(const Section&) = default;
396 };
397 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000398 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000399
Michael Forster523dbd42021-10-12 11:05:44 +0000400 std::vector<Record*> records = ir.get_items_if<Record>();
401 EXPECT_THAT(records, SizeIs(3));
402 EXPECT_THAT(records, Each(Pointee(CopyConstructor(AccessIs(kPublic)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000403}
404
405TEST(AstVisitorTest, PrivateCopyConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000406 absl::string_view file = R"cc(
407 class Defaulted {
408 Defaulted(const Defaulted&) = default;
409 };
410 struct Section {
411 private:
412 Section(const Section&) = default;
413 };
414 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000415 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000416
Michael Forster523dbd42021-10-12 11:05:44 +0000417 std::vector<Record*> records = ir.get_items_if<Record>();
418 EXPECT_THAT(records, SizeIs(2));
419 EXPECT_THAT(records, Each(Pointee(CopyConstructor(AccessIs(kPrivate)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000420}
421
422TEST(AstVisitorTest, TrivialMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000423 absl::string_view file = R"cc(
424 struct Implicit {};
425 struct Defaulted {
426 Defaulted(Defaulted&&) = default;
427 };
428 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000429 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000430
Michael Forster523dbd42021-10-12 11:05:44 +0000431 std::vector<Record*> records = ir.get_items_if<Record>();
432 EXPECT_THAT(records, SizeIs(2));
433 EXPECT_THAT(records, Each(Pointee(MoveConstructor(DefinitionIs(
434 SpecialMemberFunc::Definition::kTrivial)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000435}
436
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000437TEST(AstVisitorTest, NontrivialSelfMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000438 absl::string_view file = R"cc(
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000439 struct NontrivialSelf {
440 NontrivialSelf(NontrivialSelf&&);
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000441 };
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000442 struct NontrivialSub : public NontrivialSelf {};
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000443
444 // Despite having a defaulted move constructor, this is not trivially
445 // movable, because the *first* declaration is not defaulted.
446 struct NontrivialSelfDefaulted {
447 NontrivialSelfDefaulted(NontrivialSelfDefaulted&&);
448 };
449 inline NontrivialSelfDefaulted::NontrivialSelfDefaulted(
450 NontrivialSelfDefaulted&&) = default;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000451 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000452 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Michael Forster523dbd42021-10-12 11:05:44 +0000453 std::vector<Record*> records = ir.get_items_if<Record>();
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000454 EXPECT_THAT(records, SizeIs(3));
Michael Forster523dbd42021-10-12 11:05:44 +0000455 EXPECT_THAT(records, Each(Pointee(MoveConstructor(DefinitionIs(
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000456 SpecialMemberFunc::Definition::kNontrivialSelf)))));
457}
458
459TEST(AstVisitorTest, NontrivialMembersMoveConstructor) {
460 absl::string_view file = R"cc(
461 struct NontrivialSelf {
462 NontrivialSelf(NontrivialSelf&&);
463 };
464 struct MemberImplicit {
465 NontrivialSelf x;
466 };
467 struct MemberDefaulted {
468 MemberDefaulted(MemberDefaulted&&) = default;
469 NontrivialSelf x;
470 };
471 struct Subclass : public MemberImplicit {};
472 )cc";
473 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
474 std::vector<Record*> records = ir.get_items_if<Record>();
475 EXPECT_THAT(records, SizeIs(4));
476 EXPECT_THAT(records,
477 Each(Pointee(AnyOf(
478 IdentifierIs(
479 "NontrivialSelf"), // needed to create nontrivial members
480 MoveConstructor(DefinitionIs(
481 SpecialMemberFunc::Definition::kNontrivialMembers))))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000482}
483
484TEST(AstVisitorTest, DeletedMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000485 absl::string_view file = R"cc(
486 struct Deleted {
487 Deleted(Deleted&&) = delete;
488 };
489 struct DeletedByMember {
490 Deleted x;
491 };
492 struct SuppressedByCtorDef {
493 SuppressedByCtorDef(const SuppressedByCtorDef&) {}
494 };
495 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000496 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Michael Forster523dbd42021-10-12 11:05:44 +0000497 std::vector<Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000498 EXPECT_THAT(records, SizeIs(3));
Michael Forster523dbd42021-10-12 11:05:44 +0000499 EXPECT_THAT(records, Each(Pointee(MoveConstructor(DefinitionIs(
500 SpecialMemberFunc::Definition::kDeleted)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000501}
502
503TEST(AstVisitorTest, PublicMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000504 absl::string_view file = R"cc(
505 class Implicit {};
506 struct Defaulted {
507 Defaulted(Defaulted&&) = default;
508 };
509 class Section {
510 public:
511 Section(Section&&) = default;
512 };
513 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000514 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000515
Michael Forster523dbd42021-10-12 11:05:44 +0000516 std::vector<Record*> records = ir.get_items_if<Record>();
517 EXPECT_THAT(records, SizeIs(3));
518 EXPECT_THAT(records, Each(Pointee(MoveConstructor(AccessIs(kPublic)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000519}
520
521TEST(AstVisitorTest, PrivateMoveConstructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000522 absl::string_view file = R"cc(
523 class Defaulted {
524 Defaulted(Defaulted&&) = default;
525 };
526 struct Section {
527 private:
528 Section(Section&&) = default;
529 };
530 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000531 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000532
Michael Forster523dbd42021-10-12 11:05:44 +0000533 std::vector<Record*> records = ir.get_items_if<Record>();
534 EXPECT_THAT(records, SizeIs(2));
535 EXPECT_THAT(records, Each(Pointee(MoveConstructor(AccessIs(kPrivate)))));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000536}
537
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000538TEST(AstVisitorTest, TrivialDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000539 absl::string_view file = R"cc(
540 struct Implicit {};
541 struct Defaulted {
542 ~Defaulted() = default;
543 };
544 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000545 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000546
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000547 std::vector<Record*> records = ir.get_items_if<Record>();
548 EXPECT_THAT(records, SizeIs(2));
549 EXPECT_THAT(records, Each(Pointee(Destructor(DefinitionIs(
550 SpecialMemberFunc::Definition::kTrivial)))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000551}
552
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000553TEST(AstVisitorTest, NontrivialSelfDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000554 absl::string_view file = R"cc(
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000555 struct NontrivialSelf {
556 ~NontrivialSelf();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000557 };
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000558 struct NontrivialSub : public NontrivialSelf {};
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000559
560 // Despite having a defaulted destructor, this is not trivially
561 // destructible, because the *first* declaration is not defaulted.
562 struct NontrivialSelfDefaulted {
563 ~NontrivialSelfDefaulted();
564 };
565 inline NontrivialSelfDefaulted::~NontrivialSelfDefaulted() = default;
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000566 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000567 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000568 std::vector<Record*> records = ir.get_items_if<Record>();
Devin Jeanpierreb41041d2021-10-27 18:48:22 +0000569 EXPECT_THAT(records, SizeIs(3));
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000570 EXPECT_THAT(records, Each(Pointee(Destructor(DefinitionIs(
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000571 SpecialMemberFunc::Definition::kNontrivialSelf)))));
572}
573
574TEST(AstVisitorTest, NontrivialMembersDestructor) {
575 absl::string_view file = R"cc(
576 struct NontrivialSelf {
577 ~NontrivialSelf();
578 };
579 struct MemberImplicit {
580 NontrivialSelf x;
581 };
582 struct MemberDefaulted {
583 MemberDefaulted(MemberDefaulted&&) = default;
584 NontrivialSelf x;
585 };
586 struct Subclass : public MemberImplicit {};
587 )cc";
588 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
589 std::vector<Record*> records = ir.get_items_if<Record>();
590 EXPECT_THAT(records, SizeIs(4));
591 EXPECT_THAT(records,
592 Each(Pointee(AnyOf(
593 IdentifierIs(
594 "NontrivialSelf"), // needed to create nontrivial members
595 Destructor(DefinitionIs(
596 SpecialMemberFunc::Definition::kNontrivialMembers))))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000597}
598
599TEST(AstVisitorTest, DeletedDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000600 absl::string_view file = R"cc(
601 struct Deleted {
602 ~Deleted() = delete;
603 };
604 struct DeletedByMember {
605 Deleted x;
606 };
607 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000608 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000609
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000610 std::vector<Record*> records = ir.get_items_if<Record>();
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000611 EXPECT_THAT(records, SizeIs(2));
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000612 EXPECT_THAT(records, Each(Pointee(Destructor(DefinitionIs(
613 SpecialMemberFunc::Definition::kDeleted)))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000614}
615
616TEST(AstVisitorTest, PublicDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000617 absl::string_view file = R"cc(
618 class Implicit {};
619 struct Defaulted {
620 ~Defaulted() = default;
621 };
622 class Section {
623 public:
624 ~Section() = default;
625 };
626 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000627 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000628
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000629 std::vector<Record*> records = ir.get_items_if<Record>();
630 EXPECT_THAT(records, SizeIs(3));
631 EXPECT_THAT(records, Each(Pointee(Destructor(AccessIs(kPublic)))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000632}
633
634TEST(AstVisitorTest, PrivateDestructor) {
Devin Jeanpierrebf0d5602021-10-13 20:47:39 +0000635 absl::string_view file = R"cc(
636 class Defaulted {
637 ~Defaulted() = default;
638 };
639 struct Section {
640 private:
641 ~Section() = default;
642 };
643 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000644 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000645
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000646 std::vector<Record*> records = ir.get_items_if<Record>();
647 EXPECT_THAT(records, SizeIs(2));
648 EXPECT_THAT(records, Each(Pointee(Destructor(AccessIs(kPrivate)))));
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000649}
650
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000651TEST(AstVisitorTest, TrivialAbi) {
652 absl::string_view file = R"cc(
653 struct Empty {};
654 struct Defaulted {
655 Defaulted(const Defaulted&) = default;
656 };
657 struct [[clang::trivial_abi]] Nontrivial {
658 Nontrivial(const Nontrivial&) {}
659 };
660 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000661 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000662
Michael Forster523dbd42021-10-12 11:05:44 +0000663 std::vector<Record*> records = ir.get_items_if<Record>();
664 EXPECT_THAT(records, SizeIs(3));
665 EXPECT_THAT(records, Each(Pointee(IsTrivialAbi())));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000666}
667
668TEST(AstVisitorTest, NotTrivialAbi) {
669 absl::string_view file = R"cc(
670 struct Nontrivial {
671 Nontrivial(const Nontrivial&) {}
672 };
673 )cc";
Michael Forster3f323be2021-10-11 07:13:28 +0000674 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000675
Michael Forster523dbd42021-10-12 11:05:44 +0000676 std::vector<Record*> records = ir.get_items_if<Record>();
677 EXPECT_THAT(records, SizeIs(1));
678 EXPECT_THAT(records, Each(Pointee(Not(IsTrivialAbi()))));
Devin Jeanpierrea4896de2021-10-05 13:57:23 +0000679}
680
Googler2e85f342021-09-17 07:04:07 +0000681TEST(AstVisitorTest, MemberVariableAccessSpecifiers) {
Michael Forster3f323be2021-10-11 07:13:28 +0000682 ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({R"(
Googler2e85f342021-09-17 07:04:07 +0000683 struct SomeStruct {
684 int default_access_int;
685 public:
686 int public_int;
687 protected:
688 int protected_int;
689 private:
690 int private_int;
691 };
692
693 class SomeClass {
694 int default_access_int;
695 };
Michael Forster3f323be2021-10-11 07:13:28 +0000696 )"}));
Googler2e85f342021-09-17 07:04:07 +0000697
Devin Jeanpierredf4dc8b2021-10-21 12:53:19 +0000698 std::vector<Record*> records = ir.get_items_if<Record>();
Googler5bb23512021-09-17 12:13:27 +0000699 EXPECT_THAT(
Devin Jeanpierredf4dc8b2021-10-21 12:53:19 +0000700 records,
Googler5bb23512021-09-17 12:13:27 +0000701 ElementsAre(
Devin Jeanpierredf4dc8b2021-10-21 12:53:19 +0000702 Pointee(AllOf(
Googler5bb23512021-09-17 12:13:27 +0000703 IdentifierIs("SomeStruct"),
704 FieldsAre(
705 AllOf(IdentifierIs("default_access_int"), AccessIs(kPublic)),
706 AllOf(IdentifierIs("public_int"), AccessIs(kPublic)),
707 AllOf(IdentifierIs("protected_int"), AccessIs(kProtected)),
Michael Forster7ef80732021-10-01 18:12:19 +0000708 AllOf(IdentifierIs("private_int"), AccessIs(kPrivate))))),
Devin Jeanpierredf4dc8b2021-10-21 12:53:19 +0000709 Pointee(AllOf(IdentifierIs("SomeClass"),
710 FieldsAre(AllOf(IdentifierIs("default_access_int"),
711 AccessIs(kPrivate)))))));
Googler2e85f342021-09-17 07:04:07 +0000712}
713
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +0000714} // namespace
715} // namespace rs_bindings_from_cc