blob: 16c792b8460017de392fb37957946b41a1a0c564 [file] [log] [blame]
Brian Silverman4e662aa2022-05-11 23:10:19 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use crate::{
10 builder_modifiers::{
11 make_clang_arg_adder, make_cpp17_adder, EnableAutodiscover, SetSuppressSystemHeaders,
12 },
13 code_checkers::{
14 make_error_finder, make_rust_code_finder, make_string_finder, CppMatcher,
15 NoSystemHeadersChecker,
16 },
17};
18use autocxx_integration_tests::{
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070019 directives_from_lists, do_run_test, do_run_test_manual, run_generate_all_test, run_test,
20 run_test_ex, run_test_expect_fail, run_test_expect_fail_ex, TestError,
Brian Silverman4e662aa2022-05-11 23:10:19 -070021};
22use indoc::indoc;
23use itertools::Itertools;
24use proc_macro2::{Span, TokenStream};
25use quote::quote;
26use syn::{parse_quote, Token};
27use test_log::test;
28
29#[test]
30fn test_return_void() {
31 let cxx = indoc! {"
32 void do_nothing() {
33 }
34 "};
35 let hdr = indoc! {"
36 void do_nothing();
37 "};
38 let rs = quote! {
39 ffi::do_nothing();
40 };
41 run_test(cxx, hdr, rs, &["do_nothing"], &[]);
42}
43
44#[test]
45fn test_two_funcs() {
46 let cxx = indoc! {"
47 void do_nothing1() {
48 }
49 void do_nothing2() {
50 }
51 "};
52 let hdr = indoc! {"
53 void do_nothing1();
54 void do_nothing2();
55 "};
56 let rs = quote! {
57 ffi::do_nothing1();
58 ffi::do_nothing2();
59 };
60 run_test(cxx, hdr, rs, &["do_nothing1", "do_nothing2"], &[]);
61}
62
63#[test]
64fn test_two_funcs_with_definition() {
65 // Test to ensure C++ header isn't included twice
66 let cxx = indoc! {"
67 void do_nothing1() {
68 }
69 void do_nothing2() {
70 }
71 "};
72 let hdr = indoc! {"
73 struct Bob {
74 int a;
75 };
76 void do_nothing1();
77 void do_nothing2();
78 "};
79 let rs = quote! {
80 ffi::do_nothing1();
81 ffi::do_nothing2();
82 };
83 run_test(cxx, hdr, rs, &["do_nothing1", "do_nothing2"], &[]);
84}
85
86#[test]
87fn test_return_i32() {
88 let cxx = indoc! {"
89 uint32_t give_int() {
90 return 5;
91 }
92 "};
93 let hdr = indoc! {"
94 #include <cstdint>
95 uint32_t give_int();
96 "};
97 let rs = quote! {
98 assert_eq!(ffi::give_int(), 5);
99 };
100 run_test(cxx, hdr, rs, &["give_int"], &[]);
101}
102
103#[test]
104fn test_take_i32() {
105 let cxx = indoc! {"
106 uint32_t take_int(uint32_t a) {
107 return a + 3;
108 }
109 "};
110 let hdr = indoc! {"
111 #include <cstdint>
112 uint32_t take_int(uint32_t a);
113 "};
114 let rs = quote! {
115 assert_eq!(ffi::take_int(3), 6);
116 };
117 run_test(cxx, hdr, rs, &["take_int"], &[]);
118}
119
120#[test]
121fn test_nested_module() {
122 let cxx = indoc! {"
123 void do_nothing() {
124 }
125 "};
126 let hdr = indoc! {"
127 void do_nothing();
128 "};
129 let hexathorpe = Token![#](Span::call_site());
130 let unexpanded_rust = quote! {
131 mod a {
132 use autocxx::prelude::*;
133
134 include_cpp!(
135 #hexathorpe include "input.h"
136 generate!("do_nothing")
137 safety!(unsafe)
138 );
139
140 pub use ffi::*;
141 }
142
143 fn main() {
144 a::do_nothing();
145 }
146 };
147
148 do_run_test_manual(cxx, hdr, unexpanded_rust, None, None).unwrap();
149}
150
151#[test]
152#[ignore] // https://github.com/google/autocxx/issues/681
153#[cfg(target_pointer_width = "64")]
154fn test_return_big_ints() {
155 let cxx = indoc! {"
156 "};
157 let hdr = indoc! {"
158 #include <cstdint>
159 inline uint32_t give_u32() {
160 return 5;
161 }
162 inline uint64_t give_u64() {
163 return 5;
164 }
165 inline int32_t give_i32() {
166 return 5;
167 }
168 inline int64_t give_i64() {
169 return 5;
170 }
171 inline __int128 give_i128() {
172 return 5;
173 }
174 "};
175 let rs = quote! {
176 assert_eq!(ffi::give_u32(), 5);
177 assert_eq!(ffi::give_u64(), 5);
178 assert_eq!(ffi::give_i32(), 5);
179 assert_eq!(ffi::give_i64(), 5);
180 assert_eq!(ffi::give_i128(), 5);
181 };
182 run_test(
183 cxx,
184 hdr,
185 rs,
186 &["give_u32", "give_u64", "give_i32", "give_i64", "give_i128"],
187 &[],
188 );
189}
190
191#[test]
192#[ignore] // because cxx doesn't support unique_ptrs to primitives.
193fn test_give_up_int() {
194 let cxx = indoc! {"
195 std::unique_ptr<uint32_t> give_up() {
196 return std::make_unique<uint32_t>(12);
197 }
198 "};
199 let hdr = indoc! {"
200 #include <cstdint>
201 #include <memory>
202 std::unique_ptr<uint32_t> give_up();
203 "};
204 let rs = quote! {
205 assert_eq!(ffi::give_up().as_ref().unwrap(), 12);
206 };
207 run_test(cxx, hdr, rs, &["give_up"], &[]);
208}
209
210#[test]
211#[ignore] // because we don't yet implement UniquePtr etc. for autocxx::c_int and friends
212fn test_give_up_ctype() {
213 let cxx = indoc! {"
214 std::unique_ptr<int> give_up() {
215 return std::make_unique<int>(12);
216 }
217 "};
218 let hdr = indoc! {"
219 #include <memory>
220 std::unique_ptr<int> give_up();
221 "};
222 let rs = quote! {
223 assert_eq!(ffi::give_up().as_ref().unwrap(), autocxx::c_int(12));
224 };
225 run_test(cxx, hdr, rs, &["give_up"], &[]);
226}
227
228#[test]
229fn test_give_string_up() {
230 let cxx = indoc! {"
231 std::unique_ptr<std::string> give_str_up() {
232 return std::make_unique<std::string>(\"Bob\");
233 }
234 "};
235 let hdr = indoc! {"
236 #include <memory>
237 #include <string>
238 std::unique_ptr<std::string> give_str_up();
239 "};
240 let rs = quote! {
241 assert_eq!(ffi::give_str_up().as_ref().unwrap().to_str().unwrap(), "Bob");
242 };
243 run_test(cxx, hdr, rs, &["give_str_up"], &[]);
244}
245
246#[test]
247fn test_give_string_plain() {
248 let cxx = indoc! {"
249 std::string give_str() {
250 return std::string(\"Bob\");
251 }
252 "};
253 let hdr = indoc! {"
254 #include <string>
255 std::string give_str();
256 "};
257 let rs = quote! {
258 assert_eq!(ffi::give_str().as_ref().unwrap(), "Bob");
259 };
260 run_test(cxx, hdr, rs, &["give_str"], &[]);
261}
262
263#[test]
264fn test_cycle_string_up() {
265 let cxx = indoc! {"
266 std::unique_ptr<std::string> give_str_up() {
267 return std::make_unique<std::string>(\"Bob\");
268 }
269 uint32_t take_str_up(std::unique_ptr<std::string> a) {
270 return a->length();
271 }
272 "};
273 let hdr = indoc! {"
274 #include <memory>
275 #include <string>
276 #include <cstdint>
277 std::unique_ptr<std::string> give_str_up();
278 uint32_t take_str_up(std::unique_ptr<std::string> a);
279 "};
280 let rs = quote! {
281 let s = ffi::give_str_up();
282 assert_eq!(ffi::take_str_up(s), 3);
283 };
284 run_test(cxx, hdr, rs, &["give_str_up", "take_str_up"], &[]);
285}
286
287#[test]
288fn test_cycle_string() {
289 let cxx = indoc! {"
290 std::string give_str() {
291 return std::string(\"Bob\");
292 }
293 uint32_t take_str(std::string a) {
294 return a.length();
295 }
296 "};
297 let hdr = indoc! {"
298 #include <string>
299 #include <cstdint>
300 std::string give_str();
301 uint32_t take_str(std::string a);
302 "};
303 let rs = quote! {
304 let s = ffi::give_str();
305 assert_eq!(ffi::take_str(s), 3);
306 };
307 let generate = &["give_str", "take_str"];
308 run_test(cxx, hdr, rs, generate, &[]);
309}
310
311#[test]
312fn test_cycle_string_by_ref() {
313 let cxx = indoc! {"
314 std::unique_ptr<std::string> give_str() {
315 return std::make_unique<std::string>(\"Bob\");
316 }
317 uint32_t take_str(const std::string& a) {
318 return a.length();
319 }
320 "};
321 let hdr = indoc! {"
322 #include <string>
323 #include <memory>
324 #include <cstdint>
325 std::unique_ptr<std::string> give_str();
326 uint32_t take_str(const std::string& a);
327 "};
328 let rs = quote! {
329 let s = ffi::give_str();
330 assert_eq!(ffi::take_str(s.as_ref().unwrap()), 3);
331 };
332 let generate = &["give_str", "take_str"];
333 run_test(cxx, hdr, rs, generate, &[]);
334}
335
336#[test]
337fn test_cycle_string_by_mut_ref() {
338 let cxx = indoc! {"
339 std::unique_ptr<std::string> give_str() {
340 return std::make_unique<std::string>(\"Bob\");
341 }
342 uint32_t take_str(std::string& a) {
343 return a.length();
344 }
345 "};
346 let hdr = indoc! {"
347 #include <string>
348 #include <memory>
349 #include <cstdint>
350 std::unique_ptr<std::string> give_str();
351 uint32_t take_str(std::string& a);
352 "};
353 let rs = quote! {
354 let mut s = ffi::give_str();
355 assert_eq!(ffi::take_str(s.as_mut().unwrap()), 3);
356 };
357 let generate = &["give_str", "take_str"];
358 run_test(cxx, hdr, rs, generate, &[]);
359}
360
361#[test]
362fn test_give_pod_by_value() {
363 let cxx = indoc! {"
364 Bob give_bob() {
365 Bob a;
366 a.a = 3;
367 a.b = 4;
368 return a;
369 }
370 "};
371 let hdr = indoc! {"
372 #include <cstdint>
373 struct Bob {
374 uint32_t a;
375 uint32_t b;
376 };
377 Bob give_bob();
378 "};
379 let rs = quote! {
380 assert_eq!(ffi::give_bob().b, 4);
381 };
382 run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
383}
384
385#[test]
386fn test_give_pod_class_by_value() {
387 let cxx = indoc! {"
388 Bob give_bob() {
389 Bob a;
390 a.a = 3;
391 a.b = 4;
392 return a;
393 }
394 "};
395 let hdr = indoc! {"
396 #include <cstdint>
397 class Bob {
398 public:
399 uint32_t a;
400 uint32_t b;
401 };
402 Bob give_bob();
403 "};
404 let rs = quote! {
405 assert_eq!(ffi::give_bob().b, 4);
406 };
407 run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
408}
409
410#[test]
411fn test_give_pod_by_up() {
412 let cxx = indoc! {"
413 std::unique_ptr<Bob> give_bob() {
414 auto a = std::make_unique<Bob>();
415 a->a = 3;
416 a->b = 4;
417 return a;
418 }
419 "};
420 let hdr = indoc! {"
421 #include <cstdint>
422 #include <memory>
423 struct Bob {
424 uint32_t a;
425 uint32_t b;
426 };
427 std::unique_ptr<Bob> give_bob();
428 "};
429 let rs = quote! {
430 assert_eq!(ffi::give_bob().as_ref().unwrap().b, 4);
431 };
432 run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
433}
434
435#[test]
436fn test_take_pod_by_value() {
437 let cxx = indoc! {"
438 uint32_t take_bob(Bob a) {
439 return a.a;
440 }
441 "};
442 let hdr = indoc! {"
443 #include <cstdint>
444 struct Bob {
445 uint32_t a;
446 uint32_t b;
447 };
448 uint32_t take_bob(Bob a);
449 "};
450 let rs = quote! {
451 let a = ffi::Bob { a: 12, b: 13 };
452 assert_eq!(ffi::take_bob(a), 12);
453 };
454 run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
455}
456
457#[test]
458fn test_negative_take_as_pod_with_destructor() {
459 let cxx = indoc! {"
460 uint32_t take_bob(Bob a) {
461 return a.a;
462 }
463 "};
464 let hdr = indoc! {"
465 #include <cstdint>
466 struct Bob {
467 uint32_t a;
468 uint32_t b;
469 inline ~Bob() {}
470 };
471 uint32_t take_bob(Bob a);
472 "};
473 let rs = quote! {
474 let a = ffi::Bob { a: 12, b: 13 };
475 assert_eq!(ffi::take_bob(a), 12);
476 };
477 run_test_expect_fail(cxx, hdr, rs, &["take_bob"], &["Bob"]);
478}
479
480#[test]
481fn test_negative_take_as_pod_with_move_constructor() {
482 let cxx = indoc! {"
483 uint32_t take_bob(Bob a) {
484 return a.a;
485 }
486 "};
487 let hdr = indoc! {"
488 #include <cstdint>
489 #include <type_traits>
490 struct Bob {
491 uint32_t a;
492 uint32_t b;
493 inline Bob(Bob&& other_bob) {}
494 };
495 uint32_t take_bob(Bob a);
496 "};
497 let rs = quote! {
498 let a = ffi::Bob { a: 12, b: 13 };
499 assert_eq!(ffi::take_bob(a), 12);
500 };
501 run_test_expect_fail(cxx, hdr, rs, &["take_bob"], &["Bob"]);
502}
503
504#[test]
505fn test_take_as_pod_with_is_relocatable() {
506 let cxx = indoc! {"
507 uint32_t take_bob(Bob a) {
508 return a.a;
509 }
510 "};
511 let hdr = indoc! {"
512 #include <cstdint>
513 #include <type_traits>
514 struct Bob {
515 uint32_t a;
516 uint32_t b;
517 inline Bob() {}
518 inline ~Bob() {}
519 inline Bob(Bob&& other_bob) { a = other_bob.a; b = other_bob.b; }
520 using IsRelocatable = std::true_type;
521 };
522 uint32_t take_bob(Bob a);
523 "};
524 let rs = quote! {
525 let a = ffi::Bob { a: 12, b: 13 };
526 assert_eq!(ffi::take_bob(a), 12);
527 };
528 run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
529}
530
531#[test]
532fn test_take_pod_by_ref() {
533 let cxx = indoc! {"
534 uint32_t take_bob(const Bob& a) {
535 return a.a;
536 }
537 "};
538 let hdr = indoc! {"
539 #include <cstdint>
540 struct Bob {
541 uint32_t a;
542 uint32_t b;
543 };
544 uint32_t take_bob(const Bob& a);
545 "};
546 let rs = quote! {
547 let a = ffi::Bob { a: 12, b: 13 };
548 assert_eq!(ffi::take_bob(&a), 12);
549 };
550 run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
551}
552
553#[test]
554fn test_take_pod_by_ref_and_ptr() {
555 let cxx = indoc! {"
556 uint32_t take_bob_ref(const Bob& a) {
557 return a.a;
558 }
559 uint32_t take_bob_ptr(const Bob* a) {
560 return a->a;
561 }
562 "};
563 let hdr = indoc! {"
564 #include <cstdint>
565 struct Bob {
566 uint32_t a;
567 uint32_t b;
568 };
569 uint32_t take_bob_ref(const Bob& a);
570 uint32_t take_bob_ptr(const Bob* a);
571 "};
572 let rs = quote! {
573 let a = ffi::Bob { a: 12, b: 13 };
574 assert_eq!(ffi::take_bob_ref(&a), 12);
575 };
576 run_test(cxx, hdr, rs, &["take_bob_ref", "take_bob_ptr"], &["Bob"]);
577}
578
579#[test]
580fn test_return_pod_by_ref_and_ptr() {
581 let hdr = indoc! {"
582 #include <cstdint>
583 struct B {
584 uint32_t a;
585 };
586 struct A {
587 B b;
588 };
589 inline const B& return_b_ref(const A& a) {
590 return a.b;
591 }
592 inline const B* return_b_ptr(const A& a) {
593 return &a.b;
594 }
595 "};
596 let rs = quote! {
597 let a = ffi::A { b: ffi::B { a: 3 } };
598 assert_eq!(ffi::return_b_ref(&a).a, 3);
599 let b_ptr = ffi::return_b_ptr(&a);
600 assert_eq!(unsafe { b_ptr.as_ref() }.unwrap().a, 3);
601 };
602 run_test("", hdr, rs, &["return_b_ref", "return_b_ptr"], &["A", "B"]);
603}
604
605#[test]
606fn test_take_pod_by_mut_ref() {
607 let cxx = indoc! {"
608 uint32_t take_bob(Bob& a) {
609 a.b = 14;
610 return a.a;
611 }
612 "};
613 let hdr = indoc! {"
614 #include <cstdint>
615 struct Bob {
616 uint32_t a;
617 uint32_t b;
618 };
619 uint32_t take_bob(Bob& a);
620 "};
621 let rs = quote! {
622 let mut a = Box::pin(ffi::Bob { a: 12, b: 13 });
623 assert_eq!(ffi::take_bob(a.as_mut()), 12);
624 assert_eq!(a.b, 14);
625 };
626 run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
627}
628
629#[test]
630fn test_take_nested_pod_by_value() {
631 let cxx = indoc! {"
632 uint32_t take_bob(Bob a) {
633 return a.a;
634 }
635 "};
636 let hdr = indoc! {"
637 #include <cstdint>
638 struct Phil {
639 uint32_t d;
640 };
641 struct Bob {
642 uint32_t a;
643 uint32_t b;
644 Phil c;
645 };
646 uint32_t take_bob(Bob a);
647 "};
648 let rs = quote! {
649 let a = ffi::Bob { a: 12, b: 13, c: ffi::Phil { d: 4 } };
650 assert_eq!(ffi::take_bob(a), 12);
651 };
652 // Should be no need to allowlist Phil below
653 run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
654}
655
656#[test]
657fn test_take_nonpod_by_value() {
658 let cxx = indoc! {"
659 Bob::Bob(uint32_t a0, uint32_t b0)
660 : a(a0), b(b0) {}
661 uint32_t take_bob(Bob a) {
662 return a.a;
663 }
664 "};
665 let hdr = indoc! {"
666 #include <cstdint>
667 #include <string>
668 struct Bob {
669 Bob(uint32_t a, uint32_t b);
670 uint32_t a;
671 uint32_t b;
672 std::string reason_why_this_is_nonpod;
673 };
674 uint32_t take_bob(Bob a);
675 "};
676 let rs = quote! {
677 let a = ffi::Bob::new(12, 13).within_unique_ptr();
678 assert_eq!(ffi::take_bob(a), 12);
679 };
680 run_test(cxx, hdr, rs, &["take_bob", "Bob"], &[]);
681}
682
683#[test]
684fn test_take_nonpod_by_ref() {
685 let cxx = indoc! {"
686 uint32_t take_bob(const Bob& a) {
687 return a.a;
688 }
689 std::unique_ptr<Bob> make_bob(uint32_t a) {
690 auto b = std::make_unique<Bob>();
691 b->a = a;
692 return b;
693 }
694 "};
695 let hdr = indoc! {"
696 #include <cstdint>
697 #include <memory>
698 struct Bob {
699 uint32_t a;
700 };
701 std::unique_ptr<Bob> make_bob(uint32_t a);
702 uint32_t take_bob(const Bob& a);
703 "};
704 let rs = quote! {
705 let a = ffi::make_bob(12);
706 assert_eq!(ffi::take_bob(&a), 12);
707 };
708 run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
709}
710
711#[test]
712fn test_take_nonpod_by_up() {
713 let cxx = indoc! {"
714 uint32_t take_bob(std::unique_ptr<Bob> a) {
715 return a->a;
716 }
717 std::unique_ptr<Bob> make_bob(uint32_t a) {
718 auto b = std::make_unique<Bob>();
719 b->a = a;
720 return b;
721 }
722 "};
723 let hdr = indoc! {"
724 #include <cstdint>
725 #include <memory>
726 struct Bob {
727 uint32_t a;
728 };
729
730 struct NOP { inline void take_bob(); };
731 std::unique_ptr<Bob> make_bob(uint32_t a);
732 uint32_t take_bob(std::unique_ptr<Bob> a);
733 "};
734 let rs = quote! {
735 let a = ffi::make_bob(12);
736 assert_eq!(ffi::take_bob(a), 12);
737 };
738 run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob", "NOP"], &[]);
739}
740
741#[test]
742fn test_take_nonpod_by_ptr_simple() {
743 let cxx = indoc! {"
744 uint32_t take_bob(const Bob* a) {
745 return a->a;
746 }
747 std::unique_ptr<Bob> make_bob(uint32_t a) {
748 auto b = std::make_unique<Bob>();
749 b->a = a;
750 return b;
751 }
752 "};
753 let hdr = indoc! {"
754 #include <cstdint>
755 #include <memory>
756 struct Bob {
757 uint32_t a;
758 };
759 std::unique_ptr<Bob> make_bob(uint32_t a);
760 uint32_t take_bob(const Bob* a);
761 "};
762 let rs = quote! {
763 let a = ffi::make_bob(12);
764 let a_ptr = a.into_raw();
765 assert_eq!(unsafe { ffi::take_bob(a_ptr) }, 12);
766 unsafe { cxx::UniquePtr::from_raw(a_ptr) }; // so we drop
767 };
768 run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
769}
770
771#[test]
772fn test_take_nonpod_by_ptr_in_method() {
773 let hdr = indoc! {"
774 #include <cstdint>
775 #include <memory>
776 struct Bob {
777 uint32_t a;
778 };
779 #include <cstdint>
780 class A {
781 public:
782 A() {};
783 uint32_t take_bob(const Bob* a) const {
784 return a->a;
785 }
786 std::unique_ptr<Bob> make_bob(uint32_t a) const {
787 auto b = std::make_unique<Bob>();
788 b->a = a;
789 return b;
790 }
791 uint16_t a;
792 };
793
794 "};
795 let rs = quote! {
796 let a = ffi::A::new().within_unique_ptr();
797 let b = a.as_ref().unwrap().make_bob(12);
798 let b_ptr = b.into_raw();
799 assert_eq!(unsafe { a.as_ref().unwrap().take_bob(b_ptr) }, 12);
800 unsafe { cxx::UniquePtr::from_raw(b_ptr) }; // so we drop
801 };
802 run_test("", hdr, rs, &["A", "Bob"], &[]);
803}
804
805#[test]
806fn test_take_nonpod_by_ptr_in_wrapped_method() {
807 let hdr = indoc! {"
808 #include <cstdint>
809 #include <memory>
810 struct C {
811 C() {}
812 uint32_t a;
813 };
814 struct Bob {
815 uint32_t a;
816 };
817 class A {
818 public:
819 A() {};
820 uint32_t take_bob(const Bob* a, C) const {
821 return a->a;
822 }
823 std::unique_ptr<Bob> make_bob(uint32_t a) const {
824 auto b = std::make_unique<Bob>();
825 b->a = a;
826 return b;
827 }
828 uint16_t a;
829 };
830
831 "};
832 let rs = quote! {
833 let a = ffi::A::new().within_unique_ptr();
834 let c = ffi::C::new().within_unique_ptr();
835 let b = a.as_ref().unwrap().make_bob(12);
836 let b_ptr = b.into_raw();
837 assert_eq!(unsafe { a.as_ref().unwrap().take_bob(b_ptr, c) }, 12);
838 unsafe { cxx::UniquePtr::from_raw(b_ptr) }; // so we drop
839 };
840 run_test("", hdr, rs, &["A", "Bob", "C"], &[]);
841}
842
843#[test]
844fn test_take_char_by_ptr_in_wrapped_method() {
845 let hdr = indoc! {"
846 #include <cstdint>
847 #include <memory>
848 struct C {
849 C() { test = \"hi\"; }
850 uint32_t a;
851 const char* test;
852 };
853 class A {
854 public:
855 A() {};
856 uint32_t take_char(const char* a, C) const {
857 return a[0];
858 }
859 const char* make_char(C extra) const {
860 return extra.test;
861 }
862 uint16_t a;
863 };
864
865 "};
866 let rs = quote! {
867 let a = ffi::A::new().within_unique_ptr();
868 let c1 = ffi::C::new().within_unique_ptr();
869 let c2 = ffi::C::new().within_unique_ptr();
870 let ch = a.as_ref().unwrap().make_char(c1);
871 assert_eq!(unsafe { ch.as_ref()}.unwrap(), &104i8);
872 assert_eq!(unsafe { a.as_ref().unwrap().take_char(ch, c2) }, 104);
873 };
874 run_test("", hdr, rs, &["A", "C"], &[]);
875}
876
877#[test]
878fn test_take_nonpod_by_mut_ref() {
879 let cxx = indoc! {"
880 uint32_t take_bob(Bob& a) {
881 return a.a;
882 }
883 std::unique_ptr<Bob> make_bob(uint32_t a) {
884 auto b = std::make_unique<Bob>();
885 b->a = a;
886 return b;
887 }
888 "};
889 let hdr = indoc! {"
890 #include <cstdint>
891 #include <memory>
892 struct Bob {
893 uint32_t a;
894 };
895 std::unique_ptr<Bob> make_bob(uint32_t a);
896 uint32_t take_bob(Bob& a);
897 "};
898 let rs = quote! {
899 let mut a = ffi::make_bob(12);
900 assert_eq!(ffi::take_bob(a.pin_mut()), 12);
901 };
902 // TODO confirm that the object really was mutated by C++ in this
903 // and similar tests.
904 run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
905}
906
907#[test]
908fn test_return_nonpod_by_value() {
909 let cxx = indoc! {"
910 Bob::Bob(uint32_t a0, uint32_t b0)
911 : a(a0), b(b0) {}
912 Bob give_bob(uint32_t a) {
913 Bob c(a, 44);
914 return c;
915 }
916 uint32_t take_bob(std::unique_ptr<Bob> a) {
917 return a->a;
918 }
919 "};
920 let hdr = indoc! {"
921 #include <cstdint>
922 #include <memory>
923 struct Bob {
924 Bob(uint32_t a, uint32_t b);
925 uint32_t a;
926 uint32_t b;
927 };
928 Bob give_bob(uint32_t a);
929 uint32_t take_bob(std::unique_ptr<Bob> a);
930 "};
931 let rs = quote! {
932 let a = ffi::give_bob(13).within_unique_ptr();
933 assert_eq!(ffi::take_bob(a), 13);
934 };
935 run_test(cxx, hdr, rs, &["take_bob", "give_bob", "Bob"], &[]);
936}
937
938#[test]
939fn test_get_str_by_up() {
940 let cxx = indoc! {"
941 std::unique_ptr<std::string> get_str() {
942 return std::make_unique<std::string>(\"hello\");
943 }
944 "};
945 let hdr = indoc! {"
946 #include <string>
947 #include <memory>
948 std::unique_ptr<std::string> get_str();
949 "};
950 let rs = quote! {
951 assert_eq!(ffi::get_str().as_ref().unwrap(), "hello");
952 };
953 run_test(cxx, hdr, rs, &["get_str"], &[]);
954}
955
956#[test]
957fn test_get_str_by_value() {
958 let cxx = indoc! {"
959 std::string get_str() {
960 return \"hello\";
961 }
962 "};
963 let hdr = indoc! {"
964 #include <string>
965 std::string get_str();
966 "};
967 let rs = quote! {
968 assert_eq!(ffi::get_str().as_ref().unwrap(), "hello");
969 };
970 run_test(cxx, hdr, rs, &["get_str"], &[]);
971}
972
973#[test]
974fn test_cycle_nonpod_with_str_by_ref() {
975 let cxx = indoc! {"
976 uint32_t take_bob(const Bob& a) {
977 return a.a;
978 }
979 std::unique_ptr<Bob> make_bob() {
980 auto a = std::make_unique<Bob>();
981 a->a = 32;
982 a->b = \"hello\";
983 return a;
984 }
985 "};
986 let hdr = indoc! {"
987 #include <cstdint>
988 #include <string>
989 #include <memory>
990 struct Bob {
991 uint32_t a;
992 std::string b;
993 };
994 uint32_t take_bob(const Bob& a);
995 std::unique_ptr<Bob> make_bob();
996 "};
997 let rs = quote! {
998 let a = ffi::make_bob();
999 assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 32);
1000 };
1001 run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
1002}
1003
1004#[test]
1005fn test_make_up() {
1006 let cxx = indoc! {"
1007 Bob::Bob() : a(3) {
1008 }
1009 uint32_t take_bob(const Bob& a) {
1010 return a.a;
1011 }
1012 "};
1013 let hdr = indoc! {"
1014 #include <cstdint>
1015 class Bob {
1016 public:
1017 Bob();
1018 uint32_t a;
1019 };
1020 uint32_t take_bob(const Bob& a);
1021 "};
1022 let rs = quote! {
1023 let a = ffi::Bob::new().within_unique_ptr(); // TODO test with all sorts of arguments.
1024 assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 3);
1025 };
1026 run_test(cxx, hdr, rs, &["Bob", "take_bob"], &[]);
1027}
1028
1029#[test]
1030fn test_make_up_with_args() {
1031 let cxx = indoc! {"
1032 Bob::Bob(uint32_t a0, uint32_t b0)
1033 : a(a0), b(b0) {}
1034 uint32_t take_bob(const Bob& a) {
1035 return a.a;
1036 }
1037 "};
1038 let hdr = indoc! {"
1039 #include <cstdint>
1040 struct Bob {
1041 Bob(uint32_t a, uint32_t b);
1042 uint32_t a;
1043 uint32_t b;
1044 };
1045 uint32_t take_bob(const Bob& a);
1046 "};
1047 let rs = quote! {
1048 let a = ffi::Bob::new(12, 13).within_unique_ptr();
1049 assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 12);
1050 };
1051 run_test(cxx, hdr, rs, &["take_bob", "Bob"], &[]);
1052}
1053
1054#[test]
1055#[ignore] // because we don't support unique_ptrs to primitives
1056fn test_make_up_int() {
1057 let cxx = indoc! {"
1058 Bob::Bob(uint32_t a) : b(a) {
1059 }
1060 "};
1061 let hdr = indoc! {"
1062 #include <cstdint>
1063 class Bob {
1064 public:
1065 Bob(uint32_t a);
1066 uint32_t b;
1067 };
1068 "};
1069 let rs = quote! {
1070 let a = ffi::Bob::new(3).within_unique_ptr();
1071 assert_eq!(a.as_ref().unwrap().b, 3);
1072 };
1073 run_test(cxx, hdr, rs, &["Bob"], &[]);
1074}
1075
1076#[test]
1077fn test_enum_with_funcs() {
1078 let cxx = indoc! {"
1079 Bob give_bob() {
1080 return Bob::BOB_VALUE_2;
1081 }
1082 "};
1083 let hdr = indoc! {"
1084 #include <cstdint>
1085 enum Bob {
1086 BOB_VALUE_1,
1087 BOB_VALUE_2,
1088 };
1089 Bob give_bob();
1090 "};
1091 let rs = quote! {
1092 let a = ffi::Bob::BOB_VALUE_2;
1093 let b = ffi::give_bob();
1094 assert!(a == b);
1095 };
1096 run_test(cxx, hdr, rs, &["Bob", "give_bob"], &[]);
1097}
1098
1099#[test]
1100fn test_re_export() {
1101 let cxx = indoc! {"
1102 Bob give_bob() {
1103 return Bob::BOB_VALUE_2;
1104 }
1105 "};
1106 let hdr = indoc! {"
1107 #include <cstdint>
1108 enum Bob {
1109 BOB_VALUE_1,
1110 BOB_VALUE_2,
1111 };
1112 Bob give_bob();
1113 "};
1114 let rs = quote! {
1115 let a = ffi::Bob::BOB_VALUE_2;
1116 let b = ffi::give_bob();
1117 assert!(a == b);
1118 };
1119 run_test_ex(
1120 cxx,
1121 hdr,
1122 rs,
1123 directives_from_lists(&["Bob", "give_bob"], &[], None),
1124 None,
1125 None,
1126 Some(quote! { pub use ffi::Bob; }),
1127 );
1128}
1129
1130#[test]
1131fn test_enum_no_funcs() {
1132 let cxx = indoc! {"
1133 "};
1134 let hdr = indoc! {"
1135 enum Bob {
1136 BOB_VALUE_1,
1137 BOB_VALUE_2,
1138 };
1139 "};
1140 let rs = quote! {
1141 let a = ffi::Bob::BOB_VALUE_1;
1142 let b = ffi::Bob::BOB_VALUE_2;
1143 assert!(a != b);
1144 };
1145 run_test(cxx, hdr, rs, &["Bob"], &[]);
1146}
1147
1148#[test]
1149fn test_enum_with_funcs_as_pod() {
1150 let cxx = indoc! {"
1151 Bob give_bob() {
1152 return Bob::BOB_VALUE_2;
1153 }
1154 "};
1155 let hdr = indoc! {"
1156 #include <cstdint>
1157 enum Bob {
1158 BOB_VALUE_1,
1159 BOB_VALUE_2,
1160 };
1161 Bob give_bob();
1162 "};
1163 let rs = quote! {
1164 let a = ffi::Bob::BOB_VALUE_2;
1165 let b = ffi::give_bob();
1166 assert!(a == b);
1167 };
1168 run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
1169}
1170
1171#[test] // works, but causes compile warnings
1172fn test_take_pod_class_by_value() {
1173 let cxx = indoc! {"
1174 uint32_t take_bob(Bob a) {
1175 return a.a;
1176 }
1177 "};
1178 let hdr = indoc! {"
1179 #include <cstdint>
1180 class Bob {
1181 public:
1182 uint32_t a;
1183 uint32_t b;
1184 };
1185 uint32_t take_bob(Bob a);
1186 "};
1187 let rs = quote! {
1188 let a = ffi::Bob { a: 12, b: 13 };
1189 assert_eq!(ffi::take_bob(a), 12);
1190 };
1191 run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
1192}
1193
1194#[test]
1195fn test_pod_method() {
1196 let cxx = indoc! {"
1197 uint32_t Bob::get_bob() const {
1198 return a;
1199 }
1200 "};
1201 let hdr = indoc! {"
1202 #include <cstdint>
1203 struct Bob {
1204 public:
1205 uint32_t a;
1206 uint32_t b;
1207 uint32_t get_bob() const;
1208 };
1209 "};
1210 let rs = quote! {
1211 let a = ffi::Bob { a: 12, b: 13 };
1212 assert_eq!(a.get_bob(), 12);
1213 };
1214 run_test(cxx, hdr, rs, &[], &["Bob"]);
1215}
1216
1217#[test]
1218#[ignore] // https://github.com/google/autocxx/issues/723
1219fn test_constructors_for_specialized_types() {
1220 // bindgen sometimes makes such opaque types as type Bob = u32[2];
1221 let hdr = indoc! {"
1222 #include <cstdint>
1223 template<typename T>
1224 class A {
1225 uint32_t foo() { return 12; };
1226 private:
1227 T a[2];
1228 };
1229
1230 typedef A<uint32_t> B;
1231 typedef B C;
1232 "};
1233 let rs = quote! {
1234 let a = ffi::C::new().within_unique_ptr();
1235 assert_eq!(a.foo(), 12);
1236 };
1237 run_test("", hdr, rs, &["C"], &[]);
1238}
1239
1240#[test]
1241fn test_pod_mut_method() {
1242 let cxx = indoc! {"
1243 uint32_t Bob::get_bob() {
1244 return a;
1245 }
1246 "};
1247 let hdr = indoc! {"
1248 #include <cstdint>
1249 struct Bob {
1250 public:
1251 uint32_t a;
1252 uint32_t b;
1253 uint32_t get_bob();
1254 };
1255 "};
1256 let rs = quote! {
1257 let mut a = Box::pin(ffi::Bob { a: 12, b: 13 });
1258 assert_eq!(a.as_mut().get_bob(), 12);
1259 };
1260 run_test(cxx, hdr, rs, &[], &["Bob"]);
1261}
1262
1263#[test]
1264fn test_define_int() {
1265 let cxx = indoc! {"
1266 "};
1267 let hdr = indoc! {"
1268 #define BOB 3
1269 "};
1270 let rs = quote! {
1271 assert_eq!(ffi::BOB, 3);
1272 };
1273 run_test(cxx, hdr, rs, &["BOB"], &[]);
1274}
1275
1276#[test]
1277fn test_define_str() {
1278 let cxx = indoc! {"
1279 "};
1280 let hdr = indoc! {"
1281 #define BOB \"foo\"
1282 "};
1283 let rs = quote! {
1284 assert_eq!(std::str::from_utf8(ffi::BOB).unwrap().trim_end_matches(char::from(0)), "foo");
1285 };
1286 run_test(cxx, hdr, rs, &["BOB"], &[]);
1287}
1288
1289#[test]
1290fn test_i32_const() {
1291 let cxx = indoc! {"
1292 "};
1293 let hdr = indoc! {"
1294 #include <cstdint>
1295 const uint32_t BOB = 3;
1296 "};
1297 let rs = quote! {
1298 assert_eq!(ffi::BOB, 3);
1299 };
1300 run_test(cxx, hdr, rs, &["BOB"], &[]);
1301}
1302
1303#[test]
1304fn test_negative_rs_nonsense() {
1305 // Really just testing the test infrastructure.
1306 let cxx = indoc! {"
1307 "};
1308 let hdr = indoc! {"
1309 #include <cstdint>
1310 const uint32_t BOB = 3;
1311 "};
1312 let rs = quote! {
1313 foo bar
1314 };
1315 run_test_expect_fail(cxx, hdr, rs, &["BOB"], &[]);
1316}
1317
1318#[test]
1319fn test_negative_cpp_nonsense() {
1320 // Really just testing the test infrastructure.
1321 let cxx = indoc! {"
1322 "};
1323 let hdr = indoc! {"
1324 #include <cstdint>
1325 const uint32_t BOB = CAT;
1326 "};
1327 let rs = quote! {
1328 assert_eq!(ffi::BOB, 3);
1329 };
1330 run_test_expect_fail(cxx, hdr, rs, &["BOB"], &[]);
1331}
1332
1333#[test]
1334fn test_negative_make_nonpod() {
1335 let cxx = indoc! {"
1336 uint32_t take_bob(const Bob& a) {
1337 return a.a;
1338 }
1339 std::unique_ptr<Bob> make_bob(uint32_t a) {
1340 auto b = std::make_unique<Bob>();
1341 b->a = a;
1342 return b;
1343 }
1344 "};
1345 let hdr = indoc! {"
1346 #include <cstdint>
1347 #include <memory>
1348 struct Bob {
1349 uint32_t a;
1350 };
1351 std::unique_ptr<Bob> make_bob(uint32_t a);
1352 uint32_t take_bob(const Bob& a);
1353 "};
1354 let rs = quote! {
1355 ffi::Bob {};
1356 };
1357 let rs2 = quote! {
1358 ffi::Bob { a: 12 };
1359 };
1360 let rs3 = quote! {
1361 ffi::Bob { do_not_attempt_to_allocate_nonpod_types: [] };
1362 };
1363 run_test_expect_fail(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
1364 run_test_expect_fail(cxx, hdr, rs2, &["take_bob", "Bob", "make_bob"], &[]);
1365 run_test_expect_fail(cxx, hdr, rs3, &["take_bob", "Bob", "make_bob"], &[]);
1366}
1367
1368#[test]
1369fn test_method_pass_pod_by_value() {
1370 let cxx = indoc! {"
1371 uint32_t Bob::get_bob(Anna) const {
1372 return a;
1373 }
1374 "};
1375 let hdr = indoc! {"
1376 #include <cstdint>
1377 struct Anna {
1378 uint32_t a;
1379 };
1380 struct Bob {
1381 public:
1382 uint32_t a;
1383 uint32_t b;
1384 uint32_t get_bob(Anna a) const;
1385 };
1386 "};
1387 let rs = quote! {
1388 let a = ffi::Anna { a: 14 };
1389 let b = ffi::Bob { a: 12, b: 13 };
1390 assert_eq!(b.get_bob(a), 12);
1391 };
1392 run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
1393}
1394
1395fn perform_asan_doom_test(into_raw: TokenStream, box_type: TokenStream) {
1396 if std::env::var_os("AUTOCXX_ASAN").is_none() {
1397 return;
1398 }
1399 // Testing that we get an asan fail when it's enabled.
1400 // Really just testing our CI is working to spot ASAN mistakes.
1401 let hdr = indoc! {"
1402 #include <cstddef>
1403 struct A {
1404 int a;
1405 };
1406 inline size_t how_big_is_a() {
1407 return sizeof(A);
1408 }
1409 "};
1410 let rs = quote! {
1411 let a = #box_type::emplace(ffi::A::new());
1412 unsafe {
1413 let a_raw = #into_raw;
1414 // Intentional memory unsafety. Don't @ me.
1415 let a_offset_into_doom = a_raw.offset(ffi::how_big_is_a().try_into().unwrap());
1416 a_offset_into_doom.write_bytes(0x69, 1);
1417 #box_type::from_raw(a_raw); // to delete. If we haven't yet crashed.
1418 }
1419 };
1420 run_test_expect_fail("", hdr, rs, &["A", "how_big_is_a"], &[]);
1421}
1422
1423#[test]
1424fn test_asan_working_as_expected_for_cpp_allocations() {
1425 perform_asan_doom_test(quote! { a.into_raw() }, quote! { UniquePtr })
1426}
1427
1428#[test]
1429fn test_asan_working_as_expected_for_rust_allocations() {
1430 perform_asan_doom_test(
1431 quote! { Box::into_raw(std::pin::Pin::into_inner_unchecked(a)) },
1432 quote! { Box },
1433 )
1434}
1435
1436#[test]
1437fn test_inline_method() {
1438 let hdr = indoc! {"
1439 #include <cstdint>
1440 struct Anna {
1441 uint32_t a;
1442 };
1443 struct Bob {
1444 public:
1445 uint32_t a;
1446 uint32_t b;
1447 uint32_t get_bob(Anna) const {
1448 return a;
1449 }
1450 };
1451 "};
1452 let rs = quote! {
1453 let a = ffi::Anna { a: 14 };
1454 let b = ffi::Bob { a: 12, b: 13 };
1455 assert_eq!(b.get_bob(a), 12);
1456 };
1457 run_test("", hdr, rs, &[], &["Bob", "Anna"]);
1458}
1459
1460#[test]
1461fn test_method_pass_pod_by_reference() {
1462 let cxx = indoc! {"
1463 uint32_t Bob::get_bob(const Anna&) const {
1464 return a;
1465 }
1466 "};
1467 let hdr = indoc! {"
1468 #include <cstdint>
1469 struct Anna {
1470 uint32_t a;
1471 };
1472 struct Bob {
1473 public:
1474 uint32_t a;
1475 uint32_t b;
1476 uint32_t get_bob(const Anna& a) const;
1477 };
1478 "};
1479 let rs = quote! {
1480 let a = ffi::Anna { a: 14 };
1481 let b = ffi::Bob { a: 12, b: 13 };
1482 assert_eq!(b.get_bob(&a), 12);
1483 };
1484 run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
1485}
1486
1487#[test]
1488fn test_method_pass_pod_by_mut_reference() {
1489 let cxx = indoc! {"
1490 uint32_t Bob::get_bob(Anna&) const {
1491 return a;
1492 }
1493 "};
1494 let hdr = indoc! {"
1495 #include <cstdint>
1496 struct Anna {
1497 uint32_t a;
1498 };
1499 struct Bob {
1500 public:
1501 uint32_t a;
1502 uint32_t b;
1503 uint32_t get_bob(Anna& a) const;
1504 };
1505 "};
1506 let rs = quote! {
1507 let mut a = Box::pin(ffi::Anna { a: 14 });
1508 let b = ffi::Bob { a: 12, b: 13 };
1509 assert_eq!(b.get_bob(a.as_mut()), 12);
1510 };
1511 run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
1512}
1513
1514#[test]
1515fn test_method_pass_pod_by_up() {
1516 let cxx = indoc! {"
1517 uint32_t Bob::get_bob(std::unique_ptr<Anna>) const {
1518 return a;
1519 }
1520 "};
1521 let hdr = indoc! {"
1522 #include <cstdint>
1523 #include <memory>
1524 struct Anna {
1525 uint32_t a;
1526 };
1527 struct Bob {
1528 public:
1529 uint32_t a;
1530 uint32_t b;
1531 uint32_t get_bob(std::unique_ptr<Anna> z) const;
1532 };
1533 "};
1534 let rs = quote! {
1535 let a = ffi::Anna { a: 14 };
1536 let b = ffi::Bob { a: 12, b: 13 };
1537 assert_eq!(b.get_bob(cxx::UniquePtr::new(a)), 12);
1538 };
1539 run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
1540}
1541
1542#[test]
1543fn test_method_pass_nonpod_by_value() {
1544 let cxx = indoc! {"
1545 uint32_t Bob::get_bob(Anna) const {
1546 return a;
1547 }
1548 Anna give_anna() {
1549 Anna a;
1550 a.a = 10;
1551 return a;
1552 }
1553 "};
1554 let hdr = indoc! {"
1555 #include <cstdint>
1556 #include <string>
1557 struct Anna {
1558 uint32_t a;
1559 std::string b;
1560 };
1561 Anna give_anna();
1562 struct Bob {
1563 public:
1564 uint32_t a;
1565 uint32_t b;
1566 uint32_t get_bob(Anna a) const;
1567 };
1568 "};
1569 let rs = quote! {
1570 let a = ffi::give_anna().within_box();
1571 let b = ffi::Bob { a: 12, b: 13 };
1572 assert_eq!(b.get_bob(a), 12);
1573 };
1574 run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
1575}
1576
1577#[test]
1578fn test_pass_two_nonpod_by_value() {
1579 let cxx = indoc! {"
1580 void take_a(A, A) {
1581 }
1582 "};
1583 let hdr = indoc! {"
1584 #include <string>
1585 struct A {
1586 std::string b;
1587 };
1588 void take_a(A, A);
1589 "};
1590 let rs = quote! {
1591 let a = ffi::A::new().within_unique_ptr();
1592 let a2 = ffi::A::new().within_unique_ptr();
1593 ffi::take_a(a, a2);
1594 };
1595 run_test(cxx, hdr, rs, &["A", "take_a"], &[]);
1596}
1597
1598#[test]
1599fn test_issue_931() {
1600 let cxx = "";
1601 let hdr = indoc! {"
1602 namespace a {
1603 struct __cow_string {
1604 __cow_string();
1605 };
1606 class b {
1607 public:
1608 __cow_string c;
1609 };
1610 class j {
1611 public:
1612 b d;
1613 };
1614 template <typename> class e;
1615 } // namespace a
1616 template <typename> struct f {};
1617 namespace llvm {
1618 template <class> class g {
1619 union {
1620 f<a::j> h;
1621 };
1622 };
1623 class MemoryBuffer {
1624 public:
1625 g<a::e<MemoryBuffer>> i;
1626 };
1627 } // namespace llvm
1628 "};
1629 let rs = quote! {};
1630 run_test(cxx, hdr, rs, &["llvm::MemoryBuffer"], &[]);
1631}
1632
1633#[test]
1634fn test_issue_936() {
1635 let cxx = "";
1636 let hdr = indoc! {"
1637 struct a;
1638 class B {
1639 public:
1640 B(a &, bool);
1641 };
1642 "};
1643 let rs = quote! {};
1644 run_test(cxx, hdr, rs, &["B"], &[]);
1645}
1646
1647#[test]
1648fn test_method_pass_nonpod_by_value_with_up() {
1649 // Checks that existing UniquePtr params are not wrecked
1650 // by the conversion we do here.
1651 let cxx = indoc! {"
1652 uint32_t Bob::get_bob(Anna, std::unique_ptr<Anna>) const {
1653 return a;
1654 }
1655 Anna give_anna() {
1656 Anna a;
1657 a.a = 10;
1658 return a;
1659 }
1660 "};
1661 let hdr = indoc! {"
1662 #include <cstdint>
1663 #include <string>
1664 #include <memory>
1665 struct Anna {
1666 uint32_t a;
1667 std::string b;
1668 };
1669 Anna give_anna();
1670 struct Bob {
1671 public:
1672 uint32_t a;
1673 uint32_t b;
1674 uint32_t get_bob(Anna a, std::unique_ptr<Anna>) const;
1675 };
1676 "};
1677 let rs = quote! {
1678 let a = ffi::give_anna().within_unique_ptr();
1679 let a2 = ffi::give_anna().within_unique_ptr();
1680 let b = ffi::Bob { a: 12, b: 13 };
1681 assert_eq!(b.get_bob(a, a2), 12);
1682 };
1683 run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
1684}
1685
1686#[test]
1687fn test_issue_940() {
1688 let cxx = "";
1689 let hdr = indoc! {"
1690 template <class> class b;
1691 template <class = void> struct c;
1692 struct identity;
1693 template <class, class, class e, class> class f {
1694 using g = e;
1695 g h;
1696 };
1697 template <class i, class k = c<>, class l = b<i>>
1698 using j = f<i, identity, k, l>;
1699 class n;
1700 class RenderFrameHost {
1701 public:
1702 virtual void o(const j<n> &);
1703 virtual ~RenderFrameHost() {}
1704 };
1705 "};
1706 let rs = quote! {};
1707 run_test_ex(
1708 cxx,
1709 hdr,
1710 rs,
1711 directives_from_lists(&["RenderFrameHost"], &[], None),
1712 make_cpp17_adder(),
1713 None,
1714 None,
1715 );
1716}
1717
1718#[test]
1719fn test_method_pass_nonpod_by_reference() {
1720 let cxx = indoc! {"
1721 uint32_t Bob::get_bob(const Anna&) const {
1722 return a;
1723 }
1724 Anna give_anna() {
1725 Anna a;
1726 a.a = 10;
1727 return a;
1728 }
1729 "};
1730 let hdr = indoc! {"
1731 #include <cstdint>
1732 #include <string>
1733 struct Anna {
1734 uint32_t a;
1735 std::string b;
1736 };
1737 Anna give_anna();
1738 struct Bob {
1739 public:
1740 uint32_t a;
1741 uint32_t b;
1742 uint32_t get_bob(const Anna& a) const;
1743 };
1744 "};
1745 let rs = quote! {
1746 let a = ffi::give_anna().within_box();
1747 let b = ffi::Bob { a: 12, b: 13 };
1748 assert_eq!(b.get_bob(a.as_ref().get_ref()), 12);
1749 };
1750 run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
1751}
1752
1753#[test]
1754fn test_method_pass_nonpod_by_mut_reference() {
1755 let cxx = indoc! {"
1756 uint32_t Bob::get_bob(Anna&) const {
1757 return a;
1758 }
1759 Anna give_anna() {
1760 Anna a;
1761 a.a = 10;
1762 return a;
1763 }
1764 "};
1765 let hdr = indoc! {"
1766 #include <cstdint>
1767 #include <string>
1768 struct Anna {
1769 uint32_t a;
1770 std::string b;
1771 };
1772 Anna give_anna();
1773 struct Bob {
1774 public:
1775 uint32_t a;
1776 uint32_t b;
1777 uint32_t get_bob(Anna& a) const;
1778 };
1779 "};
1780 let rs = quote! {
1781 let mut a = ffi::give_anna().within_unique_ptr();
1782 let b = ffi::Bob { a: 12, b: 13 };
1783 assert_eq!(b.get_bob(a.as_mut().unwrap()), 12);
1784 };
1785 run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
1786}
1787
1788#[test]
1789fn test_method_pass_nonpod_by_up() {
1790 let cxx = indoc! {"
1791 uint32_t Bob::get_bob(std::unique_ptr<Anna>) const {
1792 return a;
1793 }
1794 Anna give_anna() {
1795 Anna a;
1796 a.a = 10;
1797 return a;
1798 }
1799 "};
1800 let hdr = indoc! {"
1801 #include <cstdint>
1802 #include <memory>
1803 #include <string>
1804 struct Anna {
1805 uint32_t a;
1806 std::string b;
1807 };
1808 Anna give_anna();
1809 struct Bob {
1810 public:
1811 uint32_t a;
1812 uint32_t b;
1813 uint32_t get_bob(std::unique_ptr<Anna> z) const;
1814 };
1815 "};
1816 let rs = quote! {
1817 let a = ffi::give_anna().within_unique_ptr();
1818 let b = ffi::Bob { a: 12, b: 13 };
1819 assert_eq!(b.get_bob(a), 12);
1820 };
1821 run_test(cxx, hdr, rs, &["give_anna"], &["Bob"]);
1822}
1823
1824#[test]
1825fn test_method_return_nonpod_by_value() {
1826 let cxx = indoc! {"
1827 Anna Bob::get_anna() const {
1828 Anna a;
1829 a.a = 12;
1830 return a;
1831 }
1832 "};
1833 let hdr = indoc! {"
1834 #include <cstdint>
1835 #include <string>
1836 struct Anna {
1837 uint32_t a;
1838 std::string b;
1839 };
1840 struct Bob {
1841 public:
1842 uint32_t a;
1843 uint32_t b;
1844 Anna get_anna() const;
1845 };
1846 "};
1847 let rs = quote! {
1848 let b = ffi::Bob { a: 12, b: 13 };
1849 let a = b.get_anna().within_unique_ptr();
1850 assert!(!a.is_null());
1851 };
1852 run_test(cxx, hdr, rs, &["Anna"], &["Bob"]);
1853}
1854
1855#[test]
1856fn test_pass_string_by_value() {
1857 let cxx = indoc! {"
1858 uint32_t measure_string(std::string z) {
1859 return z.length();
1860 }
1861 std::unique_ptr<std::string> get_msg() {
1862 return std::make_unique<std::string>(\"hello\");
1863 }
1864 "};
1865 let hdr = indoc! {"
1866 #include <cstdint>
1867 #include <string>
1868 #include <memory>
1869 uint32_t measure_string(std::string a);
1870 std::unique_ptr<std::string> get_msg();
1871 "};
1872 let rs = quote! {
1873 let a = ffi::get_msg();
1874 let c = ffi::measure_string(a);
1875 assert_eq!(c, 5);
1876 };
1877 run_test(cxx, hdr, rs, &["measure_string", "get_msg"], &[]);
1878}
1879
1880#[test]
1881fn test_return_string_by_value() {
1882 let cxx = indoc! {"
1883 std::string get_msg() {
1884 return \"hello\";
1885 }
1886 "};
1887 let hdr = indoc! {"
1888 #include <string>
1889 std::string get_msg();
1890 "};
1891 let rs = quote! {
1892 let a = ffi::get_msg();
1893 assert!(a.as_ref().unwrap() == "hello");
1894 };
1895 run_test(cxx, hdr, rs, &["get_msg"], &[]);
1896}
1897
1898#[test]
1899#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
1900fn test_method_pass_string_by_value() {
1901 let cxx = indoc! {"
1902 uint32_t Bob::measure_string(std::string z) const {
1903 return z.length();
1904 }
1905 std::unique_ptr<std::string> get_msg() {
1906 return std::make_unique<std::string>(\"hello\");
1907 }
1908 "};
1909 let hdr = indoc! {"
1910 #include <cstdint>
1911 #include <string>
1912 #include <memory>
1913 struct Bob {
1914 public:
1915 uint32_t a;
1916 uint32_t b;
1917 uint32_t measure_string(std::string a) const;
1918 };
1919 std::unique_ptr<std::string> get_msg();
1920 "};
1921 let rs = quote! {
1922 let a = ffi::get_msg();
1923 let b = ffi::Bob { a: 12, b: 13 };
1924 let c = b.measure_string(a);
1925 assert_eq!(c, 5);
1926 };
1927 run_test(cxx, hdr, rs, &["Bob", "get_msg"], &["Bob"]);
1928}
1929
1930#[test]
1931fn test_method_return_string_by_value() {
1932 let cxx = indoc! {"
1933 std::string Bob::get_msg() const {
1934 return \"hello\";
1935 }
1936 "};
1937 let hdr = indoc! {"
1938 #include <cstdint>
1939 #include <string>
1940 struct Bob {
1941 public:
1942 uint32_t a;
1943 uint32_t b;
1944 std::string get_msg() const;
1945 };
1946 "};
1947 let rs = quote! {
1948 let b = ffi::Bob { a: 12, b: 13 };
1949 let a = b.get_msg();
1950 assert!(a.as_ref().unwrap() == "hello");
1951 };
1952 run_test(cxx, hdr, rs, &[], &["Bob"]);
1953}
1954
1955#[test]
1956fn test_pass_rust_string_by_ref() {
1957 let cxx = indoc! {"
1958 uint32_t measure_string(const rust::String& z) {
1959 return std::string(z).length();
1960 }
1961 "};
1962 let hdr = indoc! {"
1963 #include <cstdint>
1964 #include <cxx.h>
1965 uint32_t measure_string(const rust::String& z);
1966 "};
1967 let rs = quote! {
1968 let c = ffi::measure_string(&"hello".to_string());
1969 assert_eq!(c, 5);
1970 };
1971 run_test(cxx, hdr, rs, &["measure_string"], &[]);
1972}
1973
1974#[test]
1975fn test_pass_rust_string_by_value() {
1976 let cxx = indoc! {"
1977 uint32_t measure_string(rust::String z) {
1978 return std::string(z).length();
1979 }
1980 "};
1981 let hdr = indoc! {"
1982 #include <cstdint>
1983 #include <cxx.h>
1984 uint32_t measure_string(rust::String z);
1985 "};
1986 let rs = quote! {
1987 let c = ffi::measure_string("hello".into());
1988 assert_eq!(c, 5);
1989 };
1990 run_test(cxx, hdr, rs, &["measure_string"], &[]);
1991}
1992
1993#[test]
1994fn test_pass_rust_str() {
1995 // passing by value is the only legal option
1996 let cxx = indoc! {"
1997 uint32_t measure_string(rust::Str z) {
1998 return std::string(z).length();
1999 }
2000 "};
2001 let hdr = indoc! {"
2002 #include <cstdint>
2003 #include <cxx.h>
2004 uint32_t measure_string(rust::Str z);
2005 "};
2006 let rs = quote! {
2007 let c = ffi::measure_string("hello");
2008 assert_eq!(c, 5);
2009 };
2010 run_test(cxx, hdr, rs, &["measure_string"], &[]);
2011}
2012
2013#[test]
2014fn test_multiple_classes_with_methods() {
2015 let hdr = indoc! {"
2016 #include <cstdint>
2017
2018 struct TrivialStruct {
2019 uint32_t val = 0;
2020
2021 uint32_t get() const;
2022 uint32_t inc();
2023 };
2024 TrivialStruct make_trivial_struct();
2025
2026 class TrivialClass {
2027 public:
2028 uint32_t get() const;
2029 uint32_t inc();
2030
2031 private:
2032 uint32_t val_ = 1;
2033 };
2034 TrivialClass make_trivial_class();
2035
2036 struct OpaqueStruct {
2037 // ~OpaqueStruct();
2038 uint32_t val = 2;
2039
2040 uint32_t get() const;
2041 uint32_t inc();
2042 };
2043 OpaqueStruct make_opaque_struct();
2044
2045 class OpaqueClass {
2046 public:
2047 // ~OpaqueClass();
2048 uint32_t get() const;
2049 uint32_t inc();
2050
2051 private:
2052 uint32_t val_ = 3;
2053 };
2054 OpaqueClass make_opaque_class();
2055 "};
2056 let cxx = indoc! {"
2057 TrivialStruct make_trivial_struct() { return {}; }
2058 TrivialClass make_trivial_class() { return {}; }
2059 OpaqueStruct make_opaque_struct() { return {}; }
2060 OpaqueClass make_opaque_class() { return {}; }
2061
2062 uint32_t TrivialStruct::get() const { return val;}
2063 uint32_t TrivialClass::get() const { return val_; }
2064 uint32_t OpaqueStruct::get() const { return val;}
2065 uint32_t OpaqueClass::get() const { return val_; }
2066
2067 uint32_t TrivialStruct::inc() { return ++val; }
2068 uint32_t TrivialClass::inc() { return ++val_; }
2069 uint32_t OpaqueStruct::inc() { return ++val; }
2070 uint32_t OpaqueClass::inc() { return ++val_; }
2071 "};
2072 let rs = quote! {
2073 use ffi::*;
2074
2075 let mut ts = Box::pin(make_trivial_struct());
2076 assert_eq!(ts.get(), 0);
2077 assert_eq!(ts.as_mut().inc(), 1);
2078 assert_eq!(ts.as_mut().inc(), 2);
2079
2080 let mut tc = Box::pin(make_trivial_class());
2081 assert_eq!(tc.get(), 1);
2082 assert_eq!(tc.as_mut().inc(), 2);
2083 assert_eq!(tc.as_mut().inc(), 3);
2084
2085 let mut os= make_opaque_struct().within_unique_ptr();
2086 assert_eq!(os.get(), 2);
2087 assert_eq!(os.pin_mut().inc(), 3);
2088 assert_eq!(os.pin_mut().inc(), 4);
2089
2090 let mut oc = make_opaque_class().within_unique_ptr();
2091 assert_eq!(oc.get(), 3);
2092 assert_eq!(oc.pin_mut().inc(), 4);
2093 assert_eq!(oc.pin_mut().inc(), 5);
2094 };
2095 run_test(
2096 cxx,
2097 hdr,
2098 rs,
2099 &[
2100 "make_trivial_struct",
2101 "make_trivial_class",
2102 "make_opaque_struct",
2103 "make_opaque_class",
2104 "OpaqueStruct",
2105 "OpaqueClass",
2106 ],
2107 &["TrivialStruct", "TrivialClass"],
2108 );
2109}
2110
2111#[test]
2112fn test_ns_return_struct() {
2113 let cxx = indoc! {"
2114 A::B::Bob give_bob() {
2115 A::B::Bob a;
2116 a.a = 3;
2117 a.b = 4;
2118 return a;
2119 }
2120 "};
2121 let hdr = indoc! {"
2122 #include <cstdint>
2123 namespace A {
2124 namespace B {
2125 struct Bob {
2126 uint32_t a;
2127 uint32_t b;
2128 };
2129 }
2130 }
2131 A::B::Bob give_bob();
2132 "};
2133 let rs = quote! {
2134 assert_eq!(ffi::give_bob().b, 4);
2135 };
2136 run_test(cxx, hdr, rs, &["give_bob"], &["A::B::Bob"]);
2137}
2138
2139#[test]
2140fn test_ns_take_struct() {
2141 let cxx = indoc! {"
2142 uint32_t take_bob(A::B::Bob a) {
2143 return a.a;
2144 }
2145 "};
2146 let hdr = indoc! {"
2147 #include <cstdint>
2148 namespace A {
2149 namespace B {
2150 struct Bob {
2151 uint32_t a;
2152 uint32_t b;
2153 };
2154 }
2155 }
2156 uint32_t take_bob(A::B::Bob a);
2157 "};
2158 let rs = quote! {
2159 let a = ffi::A::B::Bob { a: 12, b: 13 };
2160 assert_eq!(ffi::take_bob(a), 12);
2161 };
2162 run_test(cxx, hdr, rs, &["take_bob"], &["A::B::Bob"]);
2163}
2164
2165#[test]
2166fn test_ns_func() {
2167 let cxx = indoc! {"
2168 using namespace C;
2169 A::B::Bob C::give_bob() {
2170 A::B::Bob a;
2171 a.a = 3;
2172 a.b = 4;
2173 return a;
2174 }
2175 "};
2176 let hdr = indoc! {"
2177 #include <cstdint>
2178 namespace A {
2179 namespace B {
2180 struct Bob {
2181 uint32_t a;
2182 uint32_t b;
2183 };
2184 }
2185 }
2186 namespace C {
2187 ::A::B::Bob give_bob();
2188 }
2189 "};
2190 let rs = quote! {
2191 assert_eq!(ffi::C::give_bob().b, 4);
2192 };
2193 run_test(cxx, hdr, rs, &["C::give_bob"], &["A::B::Bob"]);
2194}
2195
2196#[test]
2197fn test_overload_constructors() {
2198 let cxx = indoc! {"
2199 Bob::Bob() {}
2200 Bob::Bob(uint32_t _a) :a(_a) {}
2201 "};
2202 let hdr = indoc! {"
2203 #include <cstdint>
2204 #include <memory>
2205 struct Bob {
2206 Bob();
2207 Bob(uint32_t a);
2208 uint32_t a;
2209 uint32_t b;
2210 };
2211 "};
2212 let rs = quote! {
2213 ffi::Bob::new().within_unique_ptr();
2214 ffi::Bob::new1(32).within_unique_ptr();
2215 };
2216 run_test(cxx, hdr, rs, &["Bob"], &[]);
2217}
2218
2219#[test]
2220fn test_overload_functions() {
2221 let cxx = indoc! {"
2222 void daft(uint32_t) {}
2223 void daft(uint8_t) {}
2224 void daft(std::string) {}
2225 void daft(Fred) {}
2226 void daft(Norma) {}
2227 "};
2228 let hdr = indoc! {"
2229 #include <cstdint>
2230 #include <string>
2231 struct Fred {
2232 uint32_t a;
2233 };
2234 struct Norma {
2235 Norma() {}
2236 uint32_t a;
2237 };
2238 void daft(uint32_t);
2239 void daft(uint8_t);
2240 void daft(std::string);
2241 void daft(Fred);
2242 void daft(Norma);
2243 "};
2244 let rs = quote! {
2245 use ffi::ToCppString;
2246 ffi::daft(32);
2247 ffi::daft1(8);
2248 ffi::daft2("hello".into_cpp());
2249 let b = ffi::Fred { a: 3 };
2250 ffi::daft3(b);
2251 let c = ffi::Norma::new().within_unique_ptr();
2252 ffi::daft4(c);
2253 };
2254 run_test(
2255 cxx,
2256 hdr,
2257 rs,
2258 &["Norma", "daft", "daft1", "daft2", "daft3", "daft4"],
2259 &["Fred"],
2260 );
2261}
2262
2263#[test]
2264#[ignore] // At present, bindgen generates two separate 'daft1'
2265 // functions here, and there's not much we can do about that.
2266fn test_overload_numeric_functions() {
2267 // Because bindgen deals with conflicting overloaded functions by
2268 // appending a numeric suffix, let's see if we can cope.
2269 let cxx = indoc! {"
2270 void daft1(uint32_t) {}
2271 void daft2(uint8_t) {}
2272 void daft(std::string) {}
2273 void daft(Fred) {}
2274 void daft(Norma) {}
2275 "};
2276 let hdr = indoc! {"
2277 #include <cstdint>
2278 #include <string>
2279 struct Fred {
2280 uint32_t a;
2281 };
2282 struct Norma {
2283 uint32_t a;
2284 };
2285 void daft1(uint32_t a);
2286 void daft2(uint8_t a);
2287 void daft(std::string a);
2288 void daft(Fred a);
2289 void daft(Norma a);
2290 "};
2291 let rs = quote! {
2292 use ffi::ToCppString;
2293 ffi::daft(32);
2294 ffi::daft1(8);
2295 ffi::daft2("hello".into_cpp());
2296 let b = ffi::Fred { a: 3 };
2297 ffi::daft3(b);
2298 let c = ffi::Norma::new().within_unique_ptr();
2299 ffi::daft4(c);
2300 };
2301 run_test(
2302 cxx,
2303 hdr,
2304 rs,
2305 &["Norma", "daft", "daft1", "daft2", "daft3", "daft4"],
2306 &["Fred"],
2307 );
2308}
2309
2310#[test]
2311fn test_overload_methods() {
2312 let cxx = indoc! {"
2313 void Bob::daft(uint32_t) const {}
2314 void Bob::daft(uint8_t) const {}
2315 void Bob::daft(std::string) const {}
2316 void Bob::daft(Fred) const {}
2317 void Bob::daft(Norma) const {}
2318 "};
2319 let hdr = indoc! {"
2320 #include <cstdint>
2321 #include <string>
2322 struct Fred {
2323 uint32_t a;
2324 };
2325 struct Norma {
2326 Norma() {}
2327 uint32_t a;
2328 };
2329 struct Bob {
2330 uint32_t a;
2331 void daft(uint32_t) const;
2332 void daft(uint8_t) const;
2333 void daft(std::string) const;
2334 void daft(Fred) const;
2335 void daft(Norma) const;
2336 };
2337 "};
2338 let rs = quote! {
2339 use ffi::ToCppString;
2340 let a = ffi::Bob { a: 12 };
2341 a.daft(32);
2342 a.daft1(8);
2343 a.daft2("hello".into_cpp());
2344 let b = ffi::Fred { a: 3 };
2345 a.daft3(b);
2346 let c = ffi::Norma::new().within_unique_ptr();
2347 a.daft4(c);
2348 };
2349 run_test(cxx, hdr, rs, &["Norma"], &["Fred", "Bob"]);
2350}
2351
2352#[test]
2353fn test_ns_constructor() {
2354 let cxx = indoc! {"
2355 A::Bob::Bob() {}
2356 "};
2357 let hdr = indoc! {"
2358 #include <cstdint>
2359 #include <memory>
2360 namespace A {
2361 struct Bob {
2362 Bob();
2363 uint32_t a;
2364 uint32_t b;
2365 };
2366 }
2367 "};
2368 let rs = quote! {
2369 ffi::A::Bob::new().within_unique_ptr();
2370 };
2371 run_test(cxx, hdr, rs, &["A::Bob"], &[]);
2372}
2373
2374#[test]
2375fn test_ns_up_direct() {
2376 let cxx = indoc! {"
2377 std::unique_ptr<A::Bob> A::get_bob() {
2378 A::Bob b;
2379 b.a = 2;
2380 b.b = 3;
2381 return std::make_unique<A::Bob>(b);
2382 }
2383 uint32_t give_bob(A::Bob bob) {
2384 return bob.a;
2385 }
2386 "};
2387 let hdr = indoc! {"
2388 #include <cstdint>
2389 #include <memory>
2390 namespace A {
2391 struct Bob {
2392 uint32_t a;
2393 uint32_t b;
2394 };
2395 std::unique_ptr<Bob> get_bob();
2396 }
2397 uint32_t give_bob(A::Bob bob);
2398 "};
2399 let rs = quote! {
2400 assert_eq!(ffi::give_bob(ffi::A::get_bob()), 2);
2401 };
2402 run_test(cxx, hdr, rs, &["give_bob", "A::get_bob"], &[]);
2403}
2404
2405#[test]
2406fn test_ns_up_wrappers() {
2407 let cxx = indoc! {"
2408 A::Bob get_bob() {
2409 A::Bob b;
2410 b.a = 2;
2411 b.b = 3;
2412 return b;
2413 }
2414 uint32_t give_bob(A::Bob bob) {
2415 return bob.a;
2416 }
2417 "};
2418 let hdr = indoc! {"
2419 #include <cstdint>
2420 namespace A {
2421 struct Bob {
2422 uint32_t a;
2423 uint32_t b;
2424 };
2425 }
2426 A::Bob get_bob();
2427 uint32_t give_bob(A::Bob bob);
2428 "};
2429 let rs = quote! {
2430 assert_eq!(ffi::give_bob(as_new(ffi::get_bob())), 2);
2431 };
2432 run_test(cxx, hdr, rs, &["give_bob", "get_bob"], &[]);
2433}
2434
2435#[test]
2436fn test_ns_up_wrappers_in_up() {
2437 let cxx = indoc! {"
2438 A::Bob A::get_bob() {
2439 A::Bob b;
2440 b.a = 2;
2441 b.b = 3;
2442 return b;
2443 }
2444 uint32_t give_bob(A::Bob bob) {
2445 return bob.a;
2446 }
2447 "};
2448 let hdr = indoc! {"
2449 #include <cstdint>
2450 namespace A {
2451 struct Bob {
2452 uint32_t a;
2453 uint32_t b;
2454 };
2455 Bob get_bob();
2456 }
2457 uint32_t give_bob(A::Bob bob);
2458 "};
2459 let rs = quote! {
2460 assert_eq!(ffi::give_bob(as_new(ffi::A::get_bob())), 2);
2461 };
2462 run_test(cxx, hdr, rs, &["give_bob", "A::get_bob"], &[]);
2463}
2464
2465#[test]
2466fn test_return_reference() {
2467 let cxx = indoc! {"
2468 const Bob& give_bob(const Bob& input_bob) {
2469 return input_bob;
2470 }
2471 "};
2472 let hdr = indoc! {"
2473 #include <cstdint>
2474 struct Bob {
2475 uint32_t a;
2476 uint32_t b;
2477 };
2478 const Bob& give_bob(const Bob& input_bob);
2479 "};
2480 let rs = quote! {
2481 let b = ffi::Bob { a: 3, b: 4 };
2482 assert_eq!(ffi::give_bob(&b).b, 4);
2483 };
2484 run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
2485}
2486
2487#[test]
2488fn test_return_reference_non_pod() {
2489 let cxx = indoc! {"
2490 const Bob& give_bob(const Bob& input_bob) {
2491 return input_bob;
2492 }
2493 "};
2494 let hdr = indoc! {"
2495 #include <cstdint>
2496 struct Bob {
2497 uint32_t a;
2498 uint32_t b;
2499 };
2500 namespace A {
2501 void give_bob(); // force wrapper generation
2502 }
2503 const Bob& give_bob(const Bob& input_bob);
2504 "};
2505 let rs = quote! {};
2506 run_test(cxx, hdr, rs, &["give_bob", "Bob", "A::give_bob"], &[]);
2507}
2508
2509#[test]
2510fn test_return_reference_non_pod_string() {
2511 let cxx = indoc! {"
2512 const std::string& give_bob(const Bob& input_bob) {
2513 return input_bob.a;
2514 }
2515 "};
2516 let hdr = indoc! {"
2517 #include <string>
2518 struct Bob {
2519 std::string a;
2520 };
2521 // namespace A {
2522 // void give_bob(); // force wrapper generation
2523 // }
2524 const std::string& give_bob(const Bob& input_bob);
2525 "};
2526 let rs = quote! {};
2527 run_test(cxx, hdr, rs, &["give_bob", "Bob"], &[]);
2528}
2529
2530#[test]
2531fn test_member_return_reference() {
2532 let hdr = indoc! {"
2533 #include <string>
2534 class A {
2535 public:
2536 virtual const std::string& get_str() { return a; }
2537 virtual ~A() {}
2538 std::string a;
2539 };
2540 "};
2541 let rs = quote! {
2542 let mut b = ffi::A::new().within_unique_ptr();
2543 b.pin_mut().get_str();
2544 };
2545 run_test("", hdr, rs, &["A"], &[]);
2546}
2547
2548#[test]
2549fn test_destructor() {
2550 let hdr = indoc! {"
2551 struct WithDtor {
2552 ~WithDtor();
2553 };
2554 WithDtor make_with_dtor();
2555 "};
2556 let cxx = indoc! {"
2557 WithDtor::~WithDtor() {}
2558 WithDtor make_with_dtor() {
2559 return {};
2560 }
2561 "};
2562 let rs = quote! {
2563 use ffi::*;
2564 let with_dtor: cxx::UniquePtr<WithDtor> = make_with_dtor().within_unique_ptr();
2565 drop(with_dtor);
2566 };
2567 run_test(cxx, hdr, rs, &["WithDtor", "make_with_dtor"], &[]);
2568}
2569
2570#[test]
2571fn test_nested_with_destructor() {
2572 // Regression test, naming the destructor in the generated C++ is a bit tricky.
2573 let hdr = indoc! {"
2574 struct A {
2575 struct B {
2576 B() = default;
2577 ~B() = default;
2578 };
2579 };
2580 "};
2581 let rs = quote! {
2582 ffi::A_B::new().within_unique_ptr();
2583 };
2584 run_test("", hdr, rs, &["A", "A_B"], &[]);
2585}
2586
2587// Even without a `safety!`, we still need to generate a safe `fn drop`.
2588#[test]
2589fn test_destructor_no_safety() {
2590 let hdr = indoc! {"
2591 struct WithDtor {
2592 ~WithDtor();
2593 };
2594 "};
2595 let cxx = indoc! {"
2596 WithDtor::~WithDtor() {}
2597 "};
2598 let hexathorpe = Token![#](Span::call_site());
2599 let unexpanded_rust = quote! {
2600 use autocxx::prelude::*;
2601
2602 include_cpp!(
2603 #hexathorpe include "input.h"
2604 generate!("WithDtor")
2605 );
2606
2607 fn main() {}
2608 };
2609
2610 do_run_test_manual(cxx, hdr, unexpanded_rust, None, None).unwrap();
2611}
2612
2613#[test]
2614fn test_static_func() {
2615 let hdr = indoc! {"
2616 #include <cstdint>
2617 struct WithStaticMethod {
2618 static uint32_t call();
2619 };
2620 "};
2621 let cxx = indoc! {"
2622 uint32_t WithStaticMethod::call() {
2623 return 42;
2624 }
2625 "};
2626 let rs = quote! {
2627 assert_eq!(ffi::WithStaticMethod::call(), 42);
2628 };
2629 run_test(cxx, hdr, rs, &["WithStaticMethod"], &[]);
2630}
2631
2632#[test]
2633fn test_static_func_wrapper() {
2634 let hdr = indoc! {"
2635 #include <cstdint>
2636 #include <string>
2637 struct A {
2638 std::string a;
2639 static A CreateA(std::string a, std::string) {
2640 A c;
2641 c.a = a;
2642 return c;
2643 }
2644 };
2645 "};
2646 let rs = quote! {
2647 use ffi::ToCppString;
2648 ffi::A::CreateA("a".into_cpp(), "b".into_cpp());
2649 };
2650 run_test("", hdr, rs, &["A"], &[]);
2651}
2652
2653#[test]
2654fn test_give_pod_typedef_by_value() {
2655 let cxx = indoc! {"
2656 Horace give_bob() {
2657 Horace a;
2658 a.a = 3;
2659 a.b = 4;
2660 return a;
2661 }
2662 "};
2663 let hdr = indoc! {"
2664 #include <cstdint>
2665 struct Bob {
2666 uint32_t a;
2667 uint32_t b;
2668 };
2669 using Horace = Bob;
2670 Horace give_bob();
2671 "};
2672 let rs = quote! {
2673 assert_eq!(ffi::give_bob().b, 4);
2674 };
2675 run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
2676}
2677
2678#[ignore] // because we need to put some aliases in the output ffi mod.
2679#[test]
2680fn test_use_pod_typedef() {
2681 let cxx = indoc! {"
2682 "};
2683 let hdr = indoc! {"
2684 #include <cstdint>
2685 struct Bob {
2686 uint32_t a;
2687 uint32_t b;
2688 };
2689 using Horace = Bob;
2690 "};
2691 let rs = quote! {
2692 let h = Horace { a: 3, b: 4 };
2693 assert_eq!(h.b, 4);
2694 };
2695 run_test(cxx, hdr, rs, &[], &["Bob"]);
2696}
2697
2698#[test]
2699fn test_typedef_to_ns() {
2700 let hdr = indoc! {"
2701 #include <cstdint>
2702 namespace A {
2703 template<typename T>
2704 struct C {
2705 T* t;
2706 };
2707 typedef C<char> B;
2708 }
2709 "};
2710 let rs = quote! {};
2711 run_test("", hdr, rs, &["A::B"], &[]);
2712}
2713
2714#[ignore] // we don't yet allow typedefs to be listed in allow_pod
2715#[test]
2716fn test_use_pod_typedef_with_allowpod() {
2717 let cxx = indoc! {"
2718 "};
2719 let hdr = indoc! {"
2720 #include <cstdint>
2721 struct Bob {
2722 uint32_t a;
2723 uint32_t b;
2724 };
2725 using Horace = Bob;
2726 "};
2727 let rs = quote! {
2728 let h = Horace { a: 3, b: 4 };
2729 assert_eq!(h.b, 4);
2730 };
2731 run_test(cxx, hdr, rs, &[], &["Horace"]);
2732}
2733
2734#[test]
2735fn test_give_nonpod_typedef_by_value() {
2736 let cxx = indoc! {"
2737 Horace give_bob() {
2738 Horace a;
2739 a.a = 3;
2740 a.b = 4;
2741 return a;
2742 }
2743 "};
2744 let hdr = indoc! {"
2745 #include <cstdint>
2746 struct Bob {
2747 uint32_t a;
2748 uint32_t b;
2749 };
2750 using Horace = Bob;
2751 Horace give_bob();
2752 inline uint32_t take_horace(const Horace& horace) { return horace.b; }
2753 "};
2754 let rs = quote! {
2755 assert_eq!(ffi::take_horace(&moveit!(ffi::give_bob())), 4);
2756 };
2757 run_test(cxx, hdr, rs, &["give_bob", "take_horace"], &[]);
2758}
2759
2760#[test]
2761fn test_conflicting_static_functions() {
2762 let cxx = indoc! {"
2763 Bob Bob::create() { Bob a; return a; }
2764 Fred Fred::create() { Fred b; return b; }
2765 "};
2766 let hdr = indoc! {"
2767 #include <cstdint>
2768 struct Bob {
2769 Bob() : a(0) {}
2770 uint32_t a;
2771 static Bob create();
2772 };
2773 struct Fred {
2774 Fred() : b(0) {}
2775 uint32_t b;
2776 static Fred create();
2777 };
2778 "};
2779 let rs = quote! {
2780 ffi::Bob::create();
2781 ffi::Fred::create();
2782 };
2783 run_test(cxx, hdr, rs, &[], &["Bob", "Fred"]);
2784}
2785
2786#[test]
2787fn test_conflicting_ns_up_functions() {
2788 let cxx = indoc! {"
2789 uint32_t A::create(C) { return 3; }
2790 uint32_t B::create(C) { return 4; }
2791 "};
2792 let hdr = indoc! {"
2793 #include <cstdint>
2794 struct C {
2795 C() {}
2796 uint32_t a;
2797 };
2798 namespace A {
2799 uint32_t create(C c);
2800 };
2801 namespace B {
2802 uint32_t create(C c);
2803 };
2804 "};
2805 let rs = quote! {
2806 let c = ffi::C::new().within_unique_ptr();
2807 let c2 = ffi::C::new().within_unique_ptr();
2808 assert_eq!(ffi::A::create(c), 3);
2809 assert_eq!(ffi::B::create(c2), 4);
2810 };
2811 run_test(cxx, hdr, rs, &["A::create", "B::create", "C"], &[]);
2812}
2813
2814#[test]
2815fn test_conflicting_methods() {
2816 let cxx = indoc! {"
2817 uint32_t Bob::get() const { return a; }
2818 uint32_t Fred::get() const { return b; }
2819 "};
2820 let hdr = indoc! {"
2821 #include <cstdint>
2822 struct Bob {
2823 uint32_t a;
2824 uint32_t get() const;
2825 };
2826 struct Fred {
2827 uint32_t b;
2828 uint32_t get() const;
2829 };
2830 "};
2831 let rs = quote! {
2832 let a = ffi::Bob { a: 10 };
2833 let b = ffi::Fred { b: 20 };
2834 assert_eq!(a.get(), 10);
2835 assert_eq!(b.get(), 20);
2836 };
2837 run_test(cxx, hdr, rs, &[], &["Bob", "Fred"]);
2838}
2839
2840#[test]
2841// There's a bindgen bug here. bindgen generates
2842// functions called 'get' and 'get1' but then generates impl
2843// blocks which call 'get' and 'get'. By luck, we currently
2844// should not be broken by this, but at some point we should take
2845// the time to create a minimal bindgen test case and submit it
2846// as a bindgen bug.
2847fn test_conflicting_up_wrapper_methods_not_in_ns() {
2848 // Ensures the two names 'get' do not conflict in the flat
2849 // cxx::bridge mod namespace.
2850 let cxx = indoc! {"
2851 Bob::Bob() : a(\"hello\") {}
2852 Fred::Fred() : b(\"goodbye\") {}
2853 std::string Bob::get() const { return a; }
2854 std::string Fred::get() const { return b; }
2855 "};
2856 let hdr = indoc! {"
2857 #include <cstdint>
2858 #include <string>
2859 struct Bob {
2860 Bob();
2861 std::string a;
2862 std::string get() const;
2863 };
2864 struct Fred {
2865 Fred();
2866 std::string b;
2867 std::string get() const;
2868 };
2869 "};
2870 let rs = quote! {
2871 let a = ffi::Bob::new().within_unique_ptr();
2872 let b = ffi::Fred::new().within_unique_ptr();
2873 assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello");
2874 assert_eq!(b.get().as_ref().unwrap().to_str().unwrap(), "goodbye");
2875 };
2876 run_test(cxx, hdr, rs, &["Bob", "Fred"], &[]);
2877}
2878
2879#[test]
2880fn test_conflicting_methods_in_ns() {
2881 let cxx = indoc! {"
2882 uint32_t A::Bob::get() const { return a; }
2883 uint32_t B::Fred::get() const { return b; }
2884 "};
2885 let hdr = indoc! {"
2886 #include <cstdint>
2887 namespace A {
2888 struct Bob {
2889 uint32_t a;
2890 uint32_t get() const;
2891 };
2892 }
2893 namespace B {
2894 struct Fred {
2895 uint32_t b;
2896 uint32_t get() const;
2897 };
2898 }
2899 "};
2900 let rs = quote! {
2901 let a = ffi::A::Bob { a: 10 };
2902 let b = ffi::B::Fred { b: 20 };
2903 assert_eq!(a.get(), 10);
2904 assert_eq!(b.get(), 20);
2905 };
2906 run_test(cxx, hdr, rs, &[], &["A::Bob", "B::Fred"]);
2907}
2908
2909#[test]
2910fn test_conflicting_up_wrapper_methods_in_ns() {
2911 let cxx = indoc! {"
2912 A::Bob::Bob() : a(\"hello\") {}
2913 B::Fred::Fred() : b(\"goodbye\") {}
2914 std::string A::Bob::get() const { return a; }
2915 std::string B::Fred::get() const { return b; }
2916 "};
2917 let hdr = indoc! {"
2918 #include <cstdint>
2919 #include <string>
2920 namespace A {
2921 struct Bob {
2922 Bob();
2923 std::string a;
2924 std::string get() const;
2925 };
2926 }
2927 namespace B {
2928 struct Fred {
2929 Fred();
2930 std::string b;
2931 std::string get() const;
2932 };
2933 }
2934 "};
2935 let rs = quote! {
2936 let a = ffi::A::Bob::new().within_unique_ptr();
2937 let b = ffi::B::Fred::new().within_unique_ptr();
2938 assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello");
2939 assert_eq!(b.get().as_ref().unwrap().to_str().unwrap(), "goodbye");
2940 };
2941 run_test(cxx, hdr, rs, &["A::Bob", "B::Fred"], &[]);
2942}
2943
2944#[test]
2945fn test_ns_struct_pod_request() {
2946 let hdr = indoc! {"
2947 #include <cstdint>
2948 namespace A {
2949 struct Bob {
2950 uint32_t a;
2951 };
2952 }
2953 "};
2954 let rs = quote! {
2955 ffi::A::Bob { a: 12 };
2956 };
2957 run_test("", hdr, rs, &[], &["A::Bob"]);
2958}
2959
2960#[test]
2961fn test_conflicting_ns_funcs() {
2962 let cxx = indoc! {"
2963 uint32_t A::get() { return 10; }
2964 uint32_t B::get() { return 20; }
2965 "};
2966 let hdr = indoc! {"
2967 #include <cstdint>
2968 namespace A {
2969 uint32_t get();
2970 }
2971 namespace B {
2972 uint32_t get();
2973 }
2974 "};
2975 let rs = quote! {
2976 assert_eq!(ffi::A::get(), 10);
2977 assert_eq!(ffi::B::get(), 20);
2978 };
2979 run_test(cxx, hdr, rs, &["A::get", "B::get"], &[]);
2980}
2981
2982#[ignore]
2983// because currently we feed a flat namespace to cxx
2984// This would be relatively easy to enable now that we have the facility
2985// to add aliases to the 'use' statements we generate, plus
2986// bridge_name_tracker to pick a unique name. TODO.
2987#[test]
2988fn test_conflicting_ns_structs() {
2989 let hdr = indoc! {"
2990 #include <cstdint>
2991 namespace A {
2992 struct Bob {
2993 uint32_t a;
2994 };
2995 }
2996 namespace B {
2997 struct Bob {
2998 uint32_t a;
2999 };
3000 }
3001 "};
3002 let rs = quote! {
3003 ffi::A::Bob { a: 12 };
3004 ffi::B::Bob { b: 12 };
3005 };
3006 run_test("", hdr, rs, &[], &["A::Bob", "B::Bob"]);
3007}
3008
3009#[test]
3010fn test_make_string() {
3011 let hdr = indoc! {"
3012 #include <cstdint>
3013 struct Bob {
3014 uint32_t a;
3015 };
3016 "};
3017 let rs = quote! {
3018 use ffi::ToCppString;
3019 let a = "hello".into_cpp();
3020 assert_eq!(a.to_str().unwrap(), "hello");
3021 };
3022 run_test("", hdr, rs, &["Bob"], &[]);
3023}
3024
3025#[test]
3026fn test_string_make_unique() {
3027 let hdr = indoc! {"
3028 #include <string>
3029 inline void take_string(const std::string*) {};
3030 "};
3031 let rs = quote! {
3032 let s = ffi::make_string("");
3033 unsafe { ffi::take_string(s.as_ref().unwrap()) };
3034 };
3035 run_test("", hdr, rs, &["take_string"], &[]);
3036}
3037
3038#[test]
3039fn test_string_constant() {
3040 let hdr = indoc! {"
3041 #include <cstdint>
3042 const char* STRING = \"Foo\";
3043 "};
3044 let rs = quote! {
3045 let a = std::str::from_utf8(ffi::STRING).unwrap().trim_end_matches(char::from(0));
3046 assert_eq!(a, "Foo");
3047 };
3048 run_test("", hdr, rs, &["STRING"], &[]);
3049}
3050
3051#[test]
3052fn test_string_let_cxx_string() {
3053 let hdr = indoc! {"
3054 #include <string>
3055 inline void take_string(const std::string&) {};
3056 "};
3057 let rs = quote! {
3058 autocxx::cxx::let_cxx_string!(s = "hello");
3059 ffi::take_string(&s);
3060 };
3061 run_test("", hdr, rs, &["take_string"], &[]);
3062}
3063
3064#[test]
3065fn test_pod_constant_harmless_inside_type() {
3066 // Check that the presence of this constant doesn't break anything.
3067 let hdr = indoc! {"
3068 #include <cstdint>
3069 struct Bob {
3070 uint32_t a;
3071 };
3072 struct Anna {
3073 uint32_t a;
3074 const Bob BOB = Bob { 10 };
3075 };
3076 "};
3077 let rs = quote! {};
3078 run_test("", hdr, rs, &[], &["Anna"]);
3079}
3080
3081#[test]
3082#[ignore] // https://github.com/google/autocxx/issues/93
3083fn test_pod_constant() {
3084 let hdr = indoc! {"
3085 #include <cstdint>
3086 struct Bob {
3087 uint32_t a;
3088 };
3089 const Bob BOB = Bob { 10 };
3090 "};
3091 let rs = quote! {
3092 let a = &ffi::BOB;
3093 assert_eq!(a.a, 10);
3094 };
3095 run_test("", hdr, rs, &["BOB"], &["Bob"]);
3096}
3097
3098#[test]
3099fn test_pod_static_harmless_inside_type() {
3100 // Check that the presence of this constant doesn't break anything.
3101 // Remove this test when the following one is enabled.
3102 let hdr = indoc! {"
3103 #include <cstdint>
3104 struct Bob {
3105 uint32_t a;
3106 };
3107 struct Anna {
3108 uint32_t a;
3109 static Bob BOB;
3110 };
3111 Bob Anna::BOB = Bob { 10 };
3112 "};
3113 let rs = quote! {};
3114 run_test("", hdr, rs, &[], &["Anna"]);
3115}
3116
3117#[test]
3118#[ignore] // https://github.com/google/autocxx/issues/93
3119fn test_pod_static() {
3120 let hdr = indoc! {"
3121 #include <cstdint>
3122 struct Bob {
3123 uint32_t a;
3124 };
3125 static Bob BOB = Bob { 10 };
3126 "};
3127 let rs = quote! {
3128 let a = &ffi::BOB;
3129 assert_eq!(a.a, 10);
3130 };
3131 run_test("", hdr, rs, &["BOB"], &["Bob"]);
3132}
3133
3134#[test]
3135#[ignore] // this probably requires code generation on the C++
3136 // side. It's not at all clear how best to handle this.
3137fn test_non_pod_constant() {
3138 let hdr = indoc! {"
3139 #include <cstdint>
3140 #include <string>
3141 struct Bob {
3142 std::string a;
3143 std::string get() { return a };
3144 };
3145 const Bob BOB = Bob { \"hello\" };
3146 "};
3147 let rs = quote! {
3148 let a = ffi::BOB;
3149 // following line assumes that 'a' is a &Bob
3150 // but who knows how we'll really do this.
3151 assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello");
3152 };
3153 run_test("", hdr, rs, &["BOB"], &[]);
3154}
3155
3156#[test]
3157fn test_templated_typedef() {
3158 let hdr = indoc! {"
3159 #include <string>
3160 #include <cstdint>
3161
3162 template <typename STRING_TYPE> class BasicStringPiece {
3163 public:
3164 const STRING_TYPE* ptr_;
3165 size_t length_;
3166 };
3167 typedef BasicStringPiece<uint8_t> StringPiece;
3168
3169 struct Origin {
3170 Origin() {}
3171 StringPiece host;
3172 };
3173 "};
3174 let rs = quote! {
3175 ffi::Origin::new().within_unique_ptr();
3176 };
3177 run_test("", hdr, rs, &["Origin"], &[]);
3178}
3179
3180#[test]
3181fn test_struct_templated_typedef() {
3182 let hdr = indoc! {"
3183 #include <string>
3184 #include <cstdint>
3185
3186 struct Concrete {
3187 uint8_t a;
3188 };
3189 template <typename STRING_TYPE> class BasicStringPiece {
3190 public:
3191 const STRING_TYPE* ptr_;
3192 size_t length_;
3193 };
3194 typedef BasicStringPiece<Concrete> StringPiece;
3195
3196 struct Origin {
3197 Origin() {}
3198 StringPiece host;
3199 };
3200 "};
3201 let rs = quote! {
3202 ffi::Origin::new().within_unique_ptr();
3203 };
3204 run_test("", hdr, rs, &["Origin"], &[]);
3205}
3206
3207#[test]
3208fn test_enum_typedef() {
3209 let hdr = indoc! {"
3210 enum ConstraintSolverParameters_TrailCompression : int {
3211 ConstraintSolverParameters_TrailCompression_NO_COMPRESSION = 0,
3212 ConstraintSolverParameters_TrailCompression_COMPRESS_WITH_ZLIB = 1
3213 };
3214 typedef ConstraintSolverParameters_TrailCompression TrailCompression;
3215 "};
3216 let rs = quote! {
3217 let _ = ffi::TrailCompression::ConstraintSolverParameters_TrailCompression_NO_COMPRESSION;
3218 };
3219 run_test("", hdr, rs, &["TrailCompression"], &[]);
3220}
3221
3222#[test]
3223#[ignore] // https://github.com/google/autocxx/issues/264
3224fn test_conflicting_usings() {
3225 let hdr = indoc! {"
3226 #include <cstdint>
3227 #include <cstddef>
3228 typedef size_t diff;
3229 struct A {
3230 using diff = diff;
3231 diff a;
3232 };
3233 struct B {
3234 using diff = diff;
3235 diff a;
3236 };
3237 "};
3238 let rs = quote! {};
3239 run_test("", hdr, rs, &[], &["A", "B"]);
3240}
3241
3242#[test]
3243fn test_conflicting_usings_with_self_declaration1() {
3244 let hdr = indoc! {"
3245 #include <cstdint>
3246 #include <cstddef>
3247 struct common_params {
3248 using difference_type = ptrdiff_t;
3249 };
3250 template <typename Params>
3251 class btree_node {
3252 public:
3253 using difference_type = typename Params::difference_type;
3254 Params params;
3255 };
3256 template <typename Tree>
3257 class btree_container {
3258 public:
3259 using difference_type = typename Tree::difference_type;
3260 void clear() {}
3261 Tree b;
3262 uint32_t a;
3263 };
3264 typedef btree_container<btree_node<common_params>> my_tree;
3265 "};
3266 let rs = quote! {};
3267 run_test("", hdr, rs, &["my_tree"], &[]);
3268}
3269
3270#[test]
3271#[ignore] // https://github.com/google/autocxx/issues/106
3272fn test_string_templated_typedef() {
3273 let hdr = indoc! {"
3274 #include <string>
3275 #include <cstdint>
3276
3277 template <typename STRING_TYPE> class BasicStringPiece {
3278 public:
3279 const STRING_TYPE* ptr_;
3280 size_t length_;
3281 };
3282 typedef BasicStringPiece<std::string> StringPiece;
3283
3284 struct Origin {
3285 Origin() {}
3286 StringPiece host;
3287 };
3288 "};
3289 let rs = quote! {
3290 ffi::Origin::new().within_unique_ptr();
3291 };
3292 run_test("", hdr, rs, &["Origin"], &[]);
3293}
3294
3295#[test]
3296fn test_associated_type_problem() {
3297 // Regression test for a potential bindgen bug
3298 let hdr = indoc! {"
3299 namespace a {
3300 template <typename> class b {};
3301 } // namespace a
3302 class bl {
3303 public:
3304 a::b<bl> bm;
3305 };
3306 struct B {
3307 int a;
3308 };
3309 "};
3310 let rs = quote! {};
3311 run_test("", hdr, rs, &["B"], &[]);
3312}
3313
3314#[test]
3315fn test_two_type_constructors() {
3316 // https://github.com/google/autocxx/issues/877
3317 let hdr = indoc! {"
3318 struct A {
3319 int a;
3320 };
3321 struct B {
3322 int B;
3323 };
3324 "};
3325 let rs = quote! {};
3326 run_test("", hdr, rs, &["A", "B"], &[]);
3327}
3328
3329#[ignore] // https://github.com/rust-lang/rust-bindgen/issues/1924
3330#[test]
3331fn test_associated_type_templated_typedef_in_struct() {
3332 let hdr = indoc! {"
3333 #include <string>
3334 #include <cstdint>
3335
3336 template <typename STRING_TYPE> class BasicStringPiece {
3337 public:
3338 typedef size_t size_type;
3339 typedef typename STRING_TYPE::value_type value_type;
3340 const value_type* ptr_;
3341 size_type length_;
3342 };
3343
3344 typedef BasicStringPiece<std::string> StringPiece;
3345
3346 struct Origin {
3347 // void SetHost(StringPiece host);
3348 StringPiece host;
3349 };
3350 "};
3351 let rs = quote! {
3352 ffi::Origin::new().within_unique_ptr();
3353 };
3354 run_test("", hdr, rs, &["Origin"], &[]);
3355}
3356
3357#[test]
3358fn test_associated_type_templated_typedef() {
3359 let hdr = indoc! {"
3360 #include <string>
3361 #include <cstdint>
3362
3363 template <typename STRING_TYPE> class BasicStringPiece {
3364 public:
3365 typedef size_t size_type;
3366 typedef typename STRING_TYPE::value_type value_type;
3367 const value_type* ptr_;
3368 size_type length_;
3369 };
3370
3371 typedef BasicStringPiece<std::string> StringPiece;
3372
3373 struct Container {
3374 Container() {}
3375 const StringPiece& get_string_piece() const { return sp; }
3376 StringPiece sp;
3377 };
3378
3379 inline void take_string_piece(const StringPiece&) {}
3380 "};
3381 let rs = quote! {
3382 let sp = ffi::Container::new().within_box();
3383 ffi::take_string_piece(sp.get_string_piece());
3384 };
3385 run_test("", hdr, rs, &["take_string_piece", "Container"], &[]);
3386}
3387
3388#[test]
3389fn test_associated_type_templated_typedef_by_value_regular() {
3390 let hdr = indoc! {"
3391 #include <string>
3392 #include <cstdint>
3393
3394 template <typename STRING_TYPE> class BasicStringPiece {
3395 public:
3396 BasicStringPiece() : ptr_(nullptr), length_(0) {}
3397 typedef size_t size_type;
3398 typedef typename STRING_TYPE::value_type value_type;
3399 const value_type* ptr_;
3400 size_type length_;
3401 };
3402
3403 typedef BasicStringPiece<std::string> StringPiece;
3404
3405 inline StringPiece give_string_piece() {
3406 StringPiece s;
3407 return s;
3408 }
3409 inline void take_string_piece(StringPiece) {}
3410 "};
3411 let rs = quote! {
3412 let sp = ffi::give_string_piece();
3413 ffi::take_string_piece(sp);
3414 };
3415 run_test_ex(
3416 "",
3417 hdr,
3418 rs,
3419 quote! {
3420 generate!("take_string_piece")
3421 generate!("give_string_piece")
3422 instantiable!("StringPiece")
3423 },
3424 None,
3425 None,
3426 None,
3427 );
3428}
3429
3430#[test]
3431fn test_associated_type_templated_typedef_by_value_forward_declaration() {
3432 let hdr = indoc! {"
3433 #include <string>
3434 #include <cstdint>
3435
3436 template <typename STRING_TYPE> class BasicStringPiece;
3437
3438 typedef BasicStringPiece<std::string> StringPiece;
3439
3440 struct Container {
3441 StringPiece give_string_piece() const;
3442 void take_string_piece(StringPiece string_piece) const;
3443 const StringPiece& get_string_piece() const;
3444 uint32_t b;
3445 };
3446
3447 inline void take_string_piece_by_ref(const StringPiece&) {}
3448 "};
3449 let cpp = indoc! {"
3450 template <typename STRING_TYPE> class BasicStringPiece {
3451 public:
3452 BasicStringPiece() : ptr_(nullptr), length_(0) {}
3453 typedef size_t size_type;
3454 typedef typename STRING_TYPE::value_type value_type;
3455 const value_type* ptr_;
3456 size_type length_;
3457 };
3458
3459 StringPiece Container::give_string_piece() const {
3460 StringPiece s;
3461 return s;
3462 }
3463 void Container::take_string_piece(StringPiece) const {}
3464
3465 StringPiece a;
3466
3467 const StringPiece& Container::get_string_piece() const {
3468 return a;
3469 }
3470 "};
3471 // As this template is forward declared we shouldn't be able to pass it by
3472 // value, but we still want to be able to use it by reference.
3473 let rs = quote! {
3474 let cont = ffi::Container::new().within_box();
3475 ffi::take_string_piece_by_ref(cont.as_ref().get_string_piece());
3476 };
3477 run_test(
3478 cpp,
3479 hdr,
3480 rs,
3481 &["take_string_piece_by_ref", "Container"],
3482 &[],
3483 );
3484}
3485
3486#[test]
3487fn test_remove_cv_t_pathological() {
3488 let hdr = indoc! {"
3489 template <class _Ty>
3490 struct remove_cv {
3491 using type = _Ty;
3492 template <template <class> class _Fn>
3493 using _Apply = _Fn<_Ty>;
3494 };
3495
3496 template <class _Ty>
3497 struct remove_cv<const _Ty> {
3498 using type = _Ty;
3499 template <template <class> class _Fn>
3500 using _Apply = const _Fn<_Ty>;
3501 };
3502
3503 template <class _Ty>
3504 struct remove_cv<volatile _Ty> {
3505 using type = _Ty;
3506 template <template <class> class _Fn>
3507 using _Apply = volatile _Fn<_Ty>;
3508 };
3509
3510 template <class _Ty>
3511 struct remove_cv<const volatile _Ty> {
3512 using type = _Ty;
3513 template <template <class> class _Fn>
3514 using _Apply = const volatile _Fn<_Ty>;
3515 };
3516
3517 template <class _Ty>
3518 using remove_cv_t = typename remove_cv<_Ty>::type;
3519
3520 template <class _Ty>
3521 struct remove_reference {
3522 using type = _Ty;
3523 using _Const_thru_ref_type = const _Ty;
3524 };
3525
3526 template <class _Ty>
3527 struct remove_reference<_Ty&> {
3528 using type = _Ty;
3529 using _Const_thru_ref_type = const _Ty&;
3530 };
3531
3532 template <class _Ty>
3533 struct remove_reference<_Ty&&> {
3534 using type = _Ty;
3535 using _Const_thru_ref_type = const _Ty&&;
3536 };
3537
3538 template <class _Ty>
3539 using remove_reference_t = typename remove_reference<_Ty>::type;
3540
3541 template <class _Ty>
3542 using _Remove_cvref_t = remove_cv_t<remove_reference_t<_Ty>>;
3543 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07003544 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -07003545}
3546
3547#[test]
3548fn test_foreign_ns_func_arg_pod() {
3549 let hdr = indoc! {"
3550 #include <cstdint>
3551 #include <memory>
3552 namespace A {
3553 struct Bob {
3554 uint32_t a;
3555 };
3556 }
3557 namespace B {
3558 inline uint32_t daft(A::Bob a) { return a.a; }
3559 }
3560 "};
3561 let rs = quote! {
3562 let a = ffi::A::Bob { a: 12 };
3563 assert_eq!(ffi::B::daft(a), 12);
3564 };
3565 run_test("", hdr, rs, &["B::daft"], &["A::Bob"]);
3566}
3567
3568#[test]
3569fn test_foreign_ns_func_arg_nonpod() {
3570 let hdr = indoc! {"
3571 #include <cstdint>
3572 #include <memory>
3573 namespace A {
3574 struct Bob {
3575 uint32_t a;
3576 Bob(uint32_t _a) :a(_a) {}
3577 };
3578 }
3579 namespace B {
3580 inline uint32_t daft(A::Bob a) { return a.a; }
3581 }
3582 "};
3583 let rs = quote! {
3584 let a = ffi::A::Bob::new(12).within_unique_ptr();
3585 assert_eq!(ffi::B::daft(a), 12);
3586 };
3587 run_test("", hdr, rs, &["B::daft", "A::Bob"], &[]);
3588}
3589
3590#[test]
3591fn test_foreign_ns_meth_arg_pod() {
3592 let hdr = indoc! {"
3593 #include <cstdint>
3594 #include <memory>
3595 namespace A {
3596 struct Bob {
3597 uint32_t a;
3598 };
3599 }
3600 namespace B {
3601 struct C {
3602 uint32_t a;
3603 uint32_t daft(A::Bob a) const { return a.a; }
3604 };
3605 }
3606 "};
3607 let rs = quote! {
3608 let a = ffi::A::Bob { a: 12 };
3609 let b = ffi::B::C { a: 12 };
3610 assert_eq!(b.daft(a), 12);
3611 };
3612 run_test("", hdr, rs, &[], &["A::Bob", "B::C"]);
3613}
3614
3615#[test]
3616fn test_foreign_ns_meth_arg_nonpod() {
3617 let hdr = indoc! {"
3618 #include <cstdint>
3619 #include <memory>
3620 namespace A {
3621 struct Bob {
3622 uint32_t a;
3623 Bob(uint32_t _a) :a(_a) {}
3624 };
3625 }
3626 namespace B {
3627 struct C {
3628 uint32_t a;
3629 uint32_t daft(A::Bob a) const { return a.a; }
3630 };
3631 }
3632 "};
3633 let rs = quote! {
3634 let a = ffi::A::Bob::new(12).within_unique_ptr();
3635 let b = ffi::B::C { a: 12 };
3636 assert_eq!(b.daft(a), 12);
3637 };
3638 run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
3639}
3640
3641#[test]
3642fn test_foreign_ns_cons_arg_pod() {
3643 let hdr = indoc! {"
3644 #include <cstdint>
3645 #include <memory>
3646 namespace A {
3647 struct Bob {
3648 uint32_t a;
3649 };
3650 }
3651 namespace B {
3652 struct C {
3653 uint32_t a;
3654 C(const A::Bob& input) : a(input.a) {}
3655 };
3656 }
3657 "};
3658 let rs = quote! {
3659 let a = ffi::A::Bob { a: 12 };
3660 let b = ffi::B::C::new(&a).within_unique_ptr();
3661 assert_eq!(b.as_ref().unwrap().a, 12);
3662 };
3663 run_test("", hdr, rs, &[], &["B::C", "A::Bob"]);
3664}
3665
3666#[test]
3667fn test_foreign_ns_cons_arg_nonpod() {
3668 let hdr = indoc! {"
3669 #include <cstdint>
3670 #include <memory>
3671 namespace A {
3672 struct Bob {
3673 Bob(uint32_t _a) :a(_a) {}
3674 uint32_t a;
3675 };
3676 }
3677 namespace B {
3678 struct C {
3679 uint32_t a;
3680 C(const A::Bob& input) : a(input.a) {}
3681 };
3682 }
3683 "};
3684 let rs = quote! {
3685 let a = ffi::A::Bob::new(12).within_unique_ptr();
3686 let b = ffi::B::C::new(&a).within_unique_ptr();
3687 assert_eq!(b.as_ref().unwrap().a, 12);
3688 };
3689 run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
3690}
3691
3692#[test]
3693fn test_foreign_ns_func_ret_pod() {
3694 let hdr = indoc! {"
3695 #include <cstdint>
3696 #include <memory>
3697 namespace A {
3698 struct Bob {
3699 uint32_t a;
3700 };
3701 }
3702 namespace B {
3703 inline A::Bob daft() { A::Bob bob; bob.a = 12; return bob; }
3704 }
3705 "};
3706 let rs = quote! {
3707 assert_eq!(ffi::B::daft().a, 12);
3708 };
3709 run_test("", hdr, rs, &["B::daft"], &["A::Bob"]);
3710}
3711
3712#[test]
3713fn test_foreign_ns_func_ret_nonpod() {
3714 let hdr = indoc! {"
3715 #include <cstdint>
3716 #include <memory>
3717 namespace A {
3718 struct Bob {
3719 uint32_t a;
3720 };
3721 }
3722 namespace B {
3723 inline A::Bob daft() { A::Bob bob; bob.a = 12; return bob; }
3724 }
3725 "};
3726 let rs = quote! {
3727 ffi::B::daft().within_box().as_ref();
3728 };
3729 run_test("", hdr, rs, &["B::daft", "A::Bob"], &[]);
3730}
3731
3732#[test]
3733fn test_foreign_ns_meth_ret_pod() {
3734 let hdr = indoc! {"
3735 #include <cstdint>
3736 #include <memory>
3737 namespace A {
3738 struct Bob {
3739 uint32_t a;
3740 };
3741 }
3742 namespace B {
3743 struct C {
3744 uint32_t a;
3745 A::Bob daft() const { A::Bob bob; bob.a = 12; return bob; }
3746 };
3747 }
3748 "};
3749 let rs = quote! {
3750 let b = ffi::B::C { a: 12 };
3751 assert_eq!(b.daft().a, 12);
3752 };
3753 run_test("", hdr, rs, &[], &["A::Bob", "B::C"]);
3754}
3755
3756#[test]
3757fn test_foreign_ns_meth_ret_nonpod() {
3758 let hdr = indoc! {"
3759 #include <cstdint>
3760 #include <memory>
3761 namespace A {
3762 struct Bob {
3763 uint32_t a;
3764 };
3765 }
3766 namespace B {
3767 struct C {
3768 uint32_t a;
3769 A::Bob daft() const { A::Bob bob; bob.a = 12; return bob; }
3770 };
3771 }
3772 "};
3773 let rs = quote! {
3774 let b = ffi::B::C { a: 14 };
3775 b.daft().within_unique_ptr().as_ref().unwrap();
3776 };
3777 run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
3778}
3779
3780#[test]
3781fn test_root_ns_func_arg_pod() {
3782 let hdr = indoc! {"
3783 #include <cstdint>
3784 #include <memory>
3785 struct Bob {
3786 uint32_t a;
3787 };
3788 namespace B {
3789 inline uint32_t daft(Bob a) { return a.a; }
3790 }
3791 "};
3792 let rs = quote! {
3793 let a = ffi::Bob { a: 12 };
3794 assert_eq!(ffi::B::daft(a), 12);
3795 };
3796 run_test("", hdr, rs, &["B::daft"], &["Bob"]);
3797}
3798
3799#[test]
3800fn test_root_ns_func_arg_nonpod() {
3801 let hdr = indoc! {"
3802 #include <cstdint>
3803 #include <memory>
3804 struct Bob {
3805 uint32_t a;
3806 Bob(uint32_t _a) :a(_a) {}
3807 };
3808 namespace B {
3809 inline uint32_t daft(Bob a) { return a.a; }
3810 }
3811 "};
3812 let rs = quote! {
3813 let a = ffi::Bob::new(12).within_unique_ptr();
3814 assert_eq!(ffi::B::daft(a), 12);
3815 };
3816 run_test("", hdr, rs, &["B::daft", "Bob"], &[]);
3817}
3818
3819#[test]
3820fn test_root_ns_meth_arg_pod() {
3821 let hdr = indoc! {"
3822 #include <cstdint>
3823 #include <memory>
3824 struct Bob {
3825 uint32_t a;
3826 };
3827 namespace B {
3828 struct C {
3829 uint32_t a;
3830 uint32_t daft(Bob a) const { return a.a; }
3831 };
3832 }
3833 "};
3834 let rs = quote! {
3835 let a = ffi::Bob { a: 12 };
3836 let b = ffi::B::C { a: 12 };
3837 assert_eq!(b.daft(a), 12);
3838 };
3839 run_test("", hdr, rs, &[], &["Bob", "B::C"]);
3840}
3841
3842#[test]
3843fn test_root_ns_meth_arg_nonpod() {
3844 let hdr = indoc! {"
3845 #include <cstdint>
3846 #include <memory>
3847 struct Bob {
3848 uint32_t a;
3849 Bob(uint32_t _a) :a(_a) {}
3850 };
3851 namespace B {
3852 struct C {
3853 uint32_t a;
3854 uint32_t daft(Bob a) const { return a.a; }
3855 };
3856 }
3857 "};
3858 let rs = quote! {
3859 let a = ffi::Bob::new(12).within_unique_ptr();
3860 let b = ffi::B::C { a: 12 };
3861 assert_eq!(b.daft(a), 12);
3862 };
3863 run_test("", hdr, rs, &["Bob"], &["B::C"]);
3864}
3865
3866#[test]
3867fn test_root_ns_cons_arg_pod() {
3868 let hdr = indoc! {"
3869 #include <cstdint>
3870 #include <memory>
3871 struct Bob {
3872 uint32_t a;
3873 };
3874 namespace B {
3875 struct C {
3876 uint32_t a;
3877 C(const Bob& input) : a(input.a) {}
3878 };
3879 }
3880 "};
3881 let rs = quote! {
3882 let a = ffi::Bob { a: 12 };
3883 let b = ffi::B::C::new(&a).within_unique_ptr();
3884 assert_eq!(b.as_ref().unwrap().a, 12);
3885 };
3886 run_test("", hdr, rs, &[], &["B::C", "Bob"]);
3887}
3888
3889#[test]
3890fn test_root_ns_cons_arg_nonpod() {
3891 let hdr = indoc! {"
3892 #include <cstdint>
3893 #include <memory>
3894 struct Bob {
3895 Bob(uint32_t _a) :a(_a) {}
3896 uint32_t a;
3897 };
3898 namespace B {
3899 struct C {
3900 uint32_t a;
3901 C(const Bob& input) : a(input.a) {}
3902 };
3903 }
3904 "};
3905 let rs = quote! {
3906 let a = ffi::Bob::new(12).within_unique_ptr();
3907 let b = ffi::B::C::new(&a).within_unique_ptr();
3908 assert_eq!(b.as_ref().unwrap().a, 12);
3909 };
3910 run_test("", hdr, rs, &["Bob"], &["B::C"]);
3911}
3912
3913#[test]
3914fn test_root_ns_func_ret_pod() {
3915 let hdr = indoc! {"
3916 #include <cstdint>
3917 #include <memory>
3918 struct Bob {
3919 uint32_t a;
3920 };
3921 namespace B {
3922 inline Bob daft() { Bob bob; bob.a = 12; return bob; }
3923 }
3924 "};
3925 let rs = quote! {
3926 assert_eq!(ffi::B::daft().a, 12);
3927 };
3928 run_test("", hdr, rs, &["B::daft"], &["Bob"]);
3929}
3930
3931#[test]
3932fn test_root_ns_func_ret_nonpod() {
3933 let hdr = indoc! {"
3934 #include <cstdint>
3935 #include <memory>
3936 struct Bob {
3937 uint32_t a;
3938 };
3939 namespace B {
3940 inline Bob daft() { Bob bob; bob.a = 12; return bob; }
3941 }
3942 "};
3943 let rs = quote! {
3944 ffi::B::daft().within_unique_ptr().as_ref().unwrap();
3945 };
3946 run_test("", hdr, rs, &["B::daft", "Bob"], &[]);
3947}
3948
3949#[test]
3950fn test_root_ns_meth_ret_pod() {
3951 let hdr = indoc! {"
3952 #include <cstdint>
3953 #include <memory>
3954 struct Bob {
3955 uint32_t a;
3956 };
3957 namespace B {
3958 struct C {
3959 uint32_t a;
3960 Bob daft() const { Bob bob; bob.a = 12; return bob; }
3961 };
3962 }
3963 "};
3964 let rs = quote! {
3965 let b = ffi::B::C { a: 12 };
3966 assert_eq!(b.daft().a, 12);
3967 };
3968 run_test("", hdr, rs, &[], &["Bob", "B::C"]);
3969}
3970
3971#[test]
3972fn test_root_ns_meth_ret_nonpod() {
3973 let hdr = indoc! {"
3974 #include <cstdint>
3975 #include <memory>
3976 struct Bob {
3977 uint32_t a;
3978 };
3979 namespace B {
3980 struct C {
3981 uint32_t a;
3982 Bob daft() const { Bob bob; bob.a = 12; return bob; }
3983 };
3984 }
3985 "};
3986 let rs = quote! {
3987 let b = ffi::B::C { a: 12 };
3988 b.daft().within_unique_ptr().as_ref().unwrap();
3989 };
3990 run_test("", hdr, rs, &["Bob"], &["B::C"]);
3991}
3992
3993#[test]
3994fn test_forward_declaration() {
3995 let hdr = indoc! {"
3996 #include <cstdint>
3997 #include <memory>
3998 struct A;
3999 struct B {
4000 B() : a(0) {}
4001 uint32_t a;
4002 void daft(const A&) const {}
4003 static B daft3(const A&) { B b; return b; }
4004 A daft4();
4005 std::unique_ptr<A> daft5();
4006 const std::unique_ptr<A>& daft6();
4007 };
4008 A* get_a();
4009 void delete_a(A*);
4010 "};
4011 let cpp = indoc! {"
4012 struct A {
4013 A() : a(0) {}
4014 uint32_t a;
4015 };
4016 A* get_a() {
4017 return new A();
4018 }
4019 void delete_a(A* a) {
4020 delete a;
4021 }
4022 A B::daft4() {
4023 A a;
4024 return a;
4025 }
4026 std::unique_ptr<A> B::daft5() {
4027 return std::make_unique<A>();
4028 }
4029 std::unique_ptr<A> fixed;
4030 const std::unique_ptr<A>& B::daft6() {
4031 return fixed;
4032 }
4033 "};
4034 let rs = quote! {
4035 let b = ffi::B::new().within_unique_ptr();
4036 let a = ffi::get_a();
4037 b.daft(unsafe { a.as_ref().unwrap() });
4038 unsafe { ffi::delete_a(a) };
4039 };
4040 run_test(cpp, hdr, rs, &["B", "get_a", "delete_a"], &[]);
4041}
4042
4043#[test]
4044fn test_ulong() {
4045 let hdr = indoc! {"
4046 inline unsigned long daft(unsigned long a) { return a; }
4047 "};
4048 let rs = quote! {
4049 assert_eq!(ffi::daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
4050 };
4051 run_test("", hdr, rs, &["daft"], &[]);
4052}
4053
4054#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4055#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
4056#[test]
4057fn test_typedef_to_ulong() {
4058 let hdr = indoc! {"
4059 typedef unsigned long fiddly;
4060 inline fiddly daft(fiddly a) { return a; }
4061 "};
4062 let rs = quote! {
4063 assert_eq!(ffi::daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
4064 };
4065 run_test("", hdr, rs, &["daft"], &[]);
4066}
4067
4068#[test]
4069fn test_generate_typedef_to_ulong() {
4070 let hdr = indoc! {"
4071 #include <cstdint>
4072 typedef uint32_t fish_t;
4073 "};
4074 let rs = quote! {
4075 let _: ffi::fish_t;
4076 };
4077 run_test("", hdr, rs, &[], &["fish_t"]);
4078}
4079
4080#[test]
4081fn test_ulong_method() {
4082 let hdr = indoc! {"
4083 class A {
4084 public:
4085 A() {};
4086 unsigned long daft(unsigned long a) const { return a; }
4087 };
4088 "};
4089 let rs = quote! {
4090 let a = ffi::A::new().within_unique_ptr();
4091 assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
4092 };
4093 run_test("", hdr, rs, &["A"], &[]);
4094}
4095
4096#[test]
4097fn test_ulong_wrapped_method() {
4098 let hdr = indoc! {"
4099 #include <cstdint>
4100 struct B {
4101 B() {};
4102 uint32_t a;
4103 };
4104 class A {
4105 public:
4106 A() {};
4107 unsigned long daft(unsigned long a, B) const { return a; }
4108 };
4109 "};
4110 let rs = quote! {
4111 let b = ffi::B::new().within_unique_ptr();
4112 let a = ffi::A::new().within_unique_ptr();
4113 assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34), b), autocxx::c_ulong(34));
4114 };
4115 run_test("", hdr, rs, &["A", "B"], &[]);
4116}
4117
4118#[test]
4119fn test_reserved_name() {
4120 let hdr = indoc! {"
4121 #include <cstdint>
4122 inline uint32_t async(uint32_t a) { return a; }
4123 "};
4124 let rs = quote! {
4125 assert_eq!(ffi::async_(34), 34);
4126 };
4127 run_test("", hdr, rs, &["async_"], &[]);
4128}
4129
4130#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4131#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
4132#[test]
4133fn test_nested_type() {
4134 // Test that we can import APIs that use nested types.
4135 // As a regression test, we also test that the nested type `A::B` doesn't conflict with the
4136 // top-level type `B`. This used to cause compile errors.
4137 let hdr = indoc! {"
4138 struct A {
4139 A() {}
4140 struct B {
4141 B() {}
4142 };
4143 enum C {};
4144 using D = int;
4145 };
4146 struct B {
4147 B() {}
4148 void method_on_top_level_type() const {}
4149 };
4150 void take_A_B(A::B);
4151 void take_A_C(A::C);
4152 void take_A_D(A::D);
4153 "};
4154 let rs = quote! {
4155 let _ = ffi::A::new().within_unique_ptr();
4156 let b = ffi::B::new().within_unique_ptr();
4157 b.as_ref().unwrap().method_on_top_level_type();
4158 };
4159 run_test("", hdr, rs, &["A", "B", "take_A_B", "take_A_C"], &[]);
4160}
4161
4162#[test]
4163fn test_nested_type_in_namespace() {
4164 // Test that we can import APIs that use nested types in a namespace.
4165 // We can't make this part of the previous test as autocxx drops the
4166 // namespace, so `A::B` and `N::A::B` would be imported as the same
4167 // type.
4168 let hdr = indoc! {"
4169 namespace N {
4170 struct A {
4171 A() {}
4172 struct B {
4173 B() {}
4174 };
4175 };
4176 };
4177 void take_A_B(N::A::B);
4178 "};
4179 let rs = quote! {};
4180 run_test("", hdr, rs, &["take_A_B"], &[]);
4181}
4182
4183#[test]
4184fn test_nested_enum_in_namespace() {
4185 let hdr = indoc! {"
4186 namespace N {
4187 struct A {
4188 A() {}
4189 enum B {
4190 C,
4191 D,
4192 };
4193 };
4194 };
4195 void take_A_B(N::A::B);
4196 "};
4197 let rs = quote! {};
4198 run_test("", hdr, rs, &["take_A_B"], &[]);
4199}
4200
4201#[test]
4202fn test_abstract_nested_type() {
4203 let hdr = indoc! {"
4204 namespace N {
4205 class A {
4206 public:
4207 A() {}
4208 class B {
4209 private:
4210 B() {}
4211 public:
4212 virtual ~B() {}
4213 virtual void Foo() = 0;
4214 };
4215 };
4216 };
4217 void take_A_B(const N::A::B&);
4218 "};
4219 let rs = quote! {};
4220 run_test("", hdr, rs, &["take_A_B", "N::A_B"], &[]);
4221}
4222
4223#[test]
4224fn test_nested_type_constructor() {
4225 let hdr = indoc! {"
4226 #include <string>
4227 class A {
4228 public:
4229 class B {
4230 public:
4231 B(const std::string&) {}
4232 int b;
4233 };
4234 int a;
4235 };
4236 "};
4237 let rs = quote! {
4238 ffi::A_B::new(&ffi::make_string("Hello")).within_unique_ptr();
4239 };
4240 run_test("", hdr, rs, &["A_B"], &[]);
4241}
4242
4243#[test]
4244fn test_generic_type() {
4245 let hdr = indoc! {"
4246 #include <cstdint>
4247 #include <string>
4248 template<typename TY>
4249 struct Container {
4250 Container(TY a_) : a(a_) {}
4251 TY a;
4252 };
4253 struct Secondary {
4254 Secondary() {}
4255 void take_a(const Container<char>) const {}
4256 void take_b(const Container<uint16_t>) const {}
4257 uint16_t take_c(std::string a) const { return 10 + a.size(); }
4258 };
4259 "};
4260 let rs = quote! {
4261 use ffi::ToCppString;
4262 let item = ffi::Secondary::new().within_unique_ptr();
4263 assert_eq!(item.take_c("hello".into_cpp()), 15)
4264 };
4265 run_test("", hdr, rs, &["Secondary"], &[]);
4266}
4267
4268#[test]
4269fn test_cycle_generic_type() {
4270 let hdr = indoc! {"
4271 #include <cstdint>
4272 template<typename TY>
4273 struct Container {
4274 Container(TY a_) : a(a_) {}
4275 TY a;
4276 };
4277 inline Container<char> make_thingy() {
4278 Container<char> a('a');
4279 return a;
4280 }
4281 typedef Container<char> Concrete;
4282 inline uint32_t take_thingy(Concrete a) {
4283 return a.a;
4284 }
4285 "};
4286 let rs = quote! {
4287 assert_eq!(ffi::take_thingy(ffi::make_thingy()), 'a' as u32)
4288 };
4289 run_test("", hdr, rs, &["take_thingy", "make_thingy"], &[]);
4290}
4291
4292#[test]
4293fn test_virtual_fns() {
4294 let hdr = indoc! {"
4295 #include <cstdint>
4296 class A {
4297 public:
4298 A(uint32_t num) : b(num) {}
4299 virtual uint32_t foo(uint32_t a) { return a+1; };
4300 virtual ~A() {}
4301 uint32_t b;
4302 };
4303 class B: public A {
4304 public:
4305 B() : A(3), c(4) {}
4306 virtual uint32_t foo(uint32_t a) { return a+2; };
4307 uint32_t c;
4308 };
4309 "};
4310 let rs = quote! {
4311 let mut a = ffi::A::new(12).within_unique_ptr();
4312 assert_eq!(a.pin_mut().foo(2), 3);
4313 let mut b = ffi::B::new().within_unique_ptr();
4314 assert_eq!(b.pin_mut().foo(2), 4);
4315 };
4316 run_test("", hdr, rs, &["A", "B"], &[]);
4317}
4318
4319#[test]
4320fn test_const_virtual_fns() {
4321 let hdr = indoc! {"
4322 #include <cstdint>
4323 class A {
4324 public:
4325 A(uint32_t num) : b(num) {}
4326 virtual uint32_t foo(uint32_t a) const { return a+1; };
4327 virtual ~A() {}
4328 uint32_t b;
4329 };
4330 class B: public A {
4331 public:
4332 B() : A(3), c(4) {}
4333 virtual uint32_t foo(uint32_t a) const { return a+2; };
4334 uint32_t c;
4335 };
4336 "};
4337 let rs = quote! {
4338 let a = ffi::A::new(12).within_unique_ptr();
4339 assert_eq!(a.foo(2), 3);
4340 let b = ffi::B::new().within_unique_ptr();
4341 assert_eq!(b.foo(2), 4);
4342 };
4343 run_test("", hdr, rs, &["A", "B"], &[]);
4344}
4345
4346#[test]
4347#[ignore] // https://github.com/google/autocxx/issues/197
4348fn test_virtual_fns_inheritance() {
4349 let hdr = indoc! {"
4350 #include <cstdint>
4351 class A {
4352 public:
4353 A(uint32_t num) : b(num) {}
4354 virtual uint32_t foo(uint32_t a) { return a+1; };
4355 virtual ~A() {}
4356 uint32_t b;
4357 };
4358 class B: public A {
4359 public:
4360 B() : A(3), c(4) {}
4361 uint32_t c;
4362 };
4363 "};
4364 let rs = quote! {
4365 let mut b = ffi::B::new().within_unique_ptr();
4366 assert_eq!(b.pin_mut().foo(2), 3);
4367 };
4368 run_test("", hdr, rs, &["B"], &[]);
4369}
4370
4371#[test]
4372fn test_vector_cycle_up() {
4373 let hdr = indoc! {"
4374 #include <cstdint>
4375 #include <vector>
4376 #include <memory>
4377 struct A {
4378 uint32_t a;
4379 };
4380 inline uint32_t take_vec(std::unique_ptr<std::vector<A>> many_as) {
4381 return many_as->size();
4382 }
4383 inline std::unique_ptr<std::vector<A>> get_vec() {
4384 auto items = std::make_unique<std::vector<A>>();
4385 items->push_back(A { 3 });
4386 items->push_back(A { 4 });
4387 return items;
4388 }
4389 "};
4390 let rs = quote! {
4391 let v = ffi::get_vec();
4392 assert_eq!(v.as_ref().unwrap().is_empty(), false);
4393 assert_eq!(ffi::take_vec(v), 2);
4394 };
4395 run_test("", hdr, rs, &["take_vec", "get_vec"], &[]);
4396}
4397
4398#[test]
4399fn test_vector_cycle_bare() {
4400 let hdr = indoc! {"
4401 #include <cstdint>
4402 #include <vector>
4403 struct A {
4404 uint32_t a;
4405 };
4406 inline uint32_t take_vec(std::vector<A> many_as) {
4407 return many_as.size();
4408 }
4409 inline std::vector<A> get_vec() {
4410 std::vector<A> items;
4411 items.push_back(A { 3 });
4412 items.push_back(A { 4 });
4413 return items;
4414 }
4415 "};
4416 let rs = quote! {
4417 assert_eq!(ffi::take_vec(ffi::get_vec()), 2);
4418 };
4419 run_test("", hdr, rs, &["take_vec", "get_vec"], &[]);
4420}
4421
4422#[test]
4423fn test_typedef_to_std() {
4424 let hdr = indoc! {"
4425 #include <string>
4426 typedef std::string my_string;
4427 inline uint32_t take_str(my_string a) {
4428 return a.size();
4429 }
4430 "};
4431 let rs = quote! {
4432 use ffi::ToCppString;
4433 assert_eq!(ffi::take_str("hello".into_cpp()), 5);
4434 };
4435 run_test("", hdr, rs, &["take_str"], &[]);
4436}
4437
4438#[test]
4439fn test_typedef_to_up_in_fn_call() {
4440 let hdr = indoc! {"
4441 #include <string>
4442 #include <memory>
4443 typedef std::unique_ptr<std::string> my_string;
4444 inline uint32_t take_str(my_string a) {
4445 return a->size();
4446 }
4447 "};
4448 let rs = quote! {
4449 use ffi::ToCppString;
4450 assert_eq!(ffi::take_str("hello".into_cpp()), 5);
4451 };
4452 run_test("", hdr, rs, &["take_str"], &[]);
4453}
4454
4455#[test]
4456fn test_typedef_in_pod_struct() {
4457 let hdr = indoc! {"
4458 #include <string>
4459 typedef uint32_t my_int;
4460 struct A {
4461 my_int a;
4462 };
4463 inline uint32_t take_a(A a) {
4464 return a.a;
4465 }
4466 "};
4467 let rs = quote! {
4468 let a = ffi::A {
4469 a: 32,
4470 };
4471 assert_eq!(ffi::take_a(a), 32);
4472 };
4473 run_test("", hdr, rs, &["take_a"], &["A"]);
4474}
4475
4476#[test]
4477fn test_cint_in_pod_struct() {
4478 let hdr = indoc! {"
4479 #include <string>
4480 struct A {
4481 int a;
4482 };
4483 inline uint32_t take_a(A a) {
4484 return a.a;
4485 }
4486 "};
4487 let rs = quote! {
4488 let a = ffi::A {
4489 a: 32,
4490 };
4491 assert_eq!(ffi::take_a(a), 32);
4492 };
4493 run_test("", hdr, rs, &["take_a"], &["A"]);
4494}
4495
4496#[test]
4497fn test_string_in_struct() {
4498 let hdr = indoc! {"
4499 #include <string>
4500 #include <memory>
4501 struct A {
4502 std::string a;
4503 };
4504 inline A make_a(std::string b) {
4505 A bob;
4506 bob.a = b;
4507 return bob;
4508 }
4509 inline uint32_t take_a(A a) {
4510 return a.a.size();
4511 }
4512 "};
4513 let rs = quote! {
4514 use ffi::ToCppString;
4515 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4516 };
4517 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4518}
4519
4520#[test]
4521#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4522fn test_up_in_struct() {
4523 let hdr = indoc! {"
4524 #include <string>
4525 #include <memory>
4526 struct A {
4527 std::unique_ptr<std::string> a;
4528 };
4529 inline A make_a(std::string b) {
4530 A bob;
4531 bob.a = std::make_unique<std::string>(b);
4532 return bob;
4533 }
4534 inline uint32_t take_a(A a) {
4535 return a.a->size();
4536 }
4537 "};
4538 let rs = quote! {
4539 use ffi::ToCppString;
4540 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4541 };
4542 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4543}
4544
4545#[test]
4546fn test_typedef_to_std_in_struct() {
4547 let hdr = indoc! {"
4548 #include <string>
4549 typedef std::string my_string;
4550 struct A {
4551 my_string a;
4552 };
4553 inline A make_a(std::string b) {
4554 A bob;
4555 bob.a = b;
4556 return bob;
4557 }
4558 inline uint32_t take_a(A a) {
4559 return a.a.size();
4560 }
4561 "};
4562 let rs = quote! {
4563 use ffi::ToCppString;
4564 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4565 };
4566 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4567}
4568
4569#[test]
4570#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4571fn test_typedef_to_up_in_struct() {
4572 let hdr = indoc! {"
4573 #include <string>
4574 #include <memory>
4575 typedef std::unique_ptr<std::string> my_string;
4576 struct A {
4577 my_string a;
4578 };
4579 inline A make_a(std::string b) {
4580 A bob;
4581 bob.a = std::make_unique<std::string>(b);
4582 return bob;
4583 }
4584 inline uint32_t take_a(A a) {
4585 return a.a->size();
4586 }
4587 "};
4588 let rs = quote! {
4589 use ffi::ToCppString;
4590 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4591 };
4592 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4593}
4594
4595#[test]
4596fn test_float() {
4597 let hdr = indoc! {"
4598 inline float daft(float a) { return a; }
4599 "};
4600 let rs = quote! {
4601 assert_eq!(ffi::daft(34.0f32), 34.0f32);
4602 };
4603 run_test("", hdr, rs, &["daft"], &[]);
4604}
4605
4606#[test]
4607fn test_double() {
4608 let hdr = indoc! {"
4609 inline double daft(double a) { return a; }
4610 "};
4611 let rs = quote! {
4612 assert_eq!(ffi::daft(34.0f64), 34.0f64);
4613 };
4614 run_test("", hdr, rs, &["daft"], &[]);
4615}
4616
4617#[test]
4618fn test_issues_217_222() {
4619 let hdr = indoc! {"
4620 #include <string>
4621 #include <cstdint>
4622 #include <cstddef>
4623
4624 template <typename STRING_TYPE> class BasicStringPiece {
4625 public:
4626 typedef size_t size_type;
4627 typedef typename STRING_TYPE::traits_type traits_type;
4628 typedef typename STRING_TYPE::value_type value_type;
4629 typedef const value_type* pointer;
4630 typedef const value_type& reference;
4631 typedef const value_type& const_reference;
4632 typedef ptrdiff_t difference_type;
4633 typedef const value_type* const_iterator;
4634 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4635 static const size_type npos;
4636 };
4637
4638 template<typename CHAR>
4639 class Replacements {
4640 public:
4641 Replacements() {
4642 }
4643 void SetScheme(const CHAR*) {
4644 }
4645 uint16_t a;
4646 };
4647
4648 struct Component {
4649 uint16_t a;
4650 };
4651
4652 template <typename STR>
4653 class StringPieceReplacements : public Replacements<typename STR::value_type> {
4654 private:
4655 using CharT = typename STR::value_type;
4656 using StringPieceT = BasicStringPiece<STR>;
4657 using ParentT = Replacements<CharT>;
4658 using SetterFun = void (ParentT::*)(const CharT*, const Component&);
4659 void SetImpl(SetterFun, StringPieceT) {
4660 }
4661 public:
4662 void SetSchemeStr(const CharT* str) { SetImpl(&ParentT::SetScheme, str); }
4663 };
4664
4665 class GURL {
4666 public:
4667 typedef StringPieceReplacements<std::string> UrlReplacements;
4668 GURL() {}
4669 GURL ReplaceComponents(const Replacements<char>&) const {
4670 return GURL();
4671 }
4672 uint16_t a;
4673 };
4674 "};
4675 let rs = quote! {
4676 ffi::GURL::new().within_unique_ptr();
4677 };
4678 // The block! directives here are to avoid running into
4679 // https://github.com/rust-lang/rust-bindgen/pull/1975
4680 run_test_ex(
4681 "",
4682 hdr,
4683 rs,
4684 quote! { generate!("GURL") block!("StringPiece") block!("Replacements") },
4685 None,
4686 None,
4687 None,
4688 );
4689}
4690
4691#[test]
4692#[ignore] // https://github.com/rust-lang/rust-bindgen/pull/1975, https://github.com/google/autocxx/issues/106
4693fn test_dependent_qualified_type() {
4694 let hdr = indoc! {"
4695 #include <stddef.h>
4696 struct MyString {
4697 typedef char value_type;
4698 };
4699 template<typename T> struct MyStringView {
4700 typedef typename T::value_type view_value_type;
4701 const view_value_type* start;
4702 size_t length;
4703 };
4704 const char* HELLO = \"hello\";
4705 inline MyStringView<MyString> make_string_view() {
4706 MyStringView<MyString> r;
4707 r.start = HELLO;
4708 r.length = 2;
4709 return r;
4710 }
4711 inline size_t take_string_view(const MyStringView<MyString>& bit) {
4712 return bit.length;
4713 }
4714 "};
4715 let rs = quote! {
4716 let sv = ffi::make_string_view();
4717 assert_eq!(ffi::take_string_view(sv.as_ref().unwrap()), 2);
4718 };
4719 run_test("", hdr, rs, &["take_string_view", "make_string_view"], &[]);
4720}
4721
4722#[test]
4723fn test_simple_dependent_qualified_type() {
4724 // bindgen seems to cope with this case just fine
4725 let hdr = indoc! {"
4726 #include <stddef.h>
4727 #include <stdint.h>
4728 struct MyString {
4729 typedef char value_type;
4730 };
4731 template<typename T> struct MyStringView {
4732 typedef typename T::value_type view_value_type;
4733 const view_value_type* start;
4734 size_t length;
4735 };
4736 typedef MyStringView<MyString>::view_value_type MyChar;
4737 inline MyChar make_char() {
4738 return 'a';
4739 }
4740 inline uint32_t take_char(MyChar c) {
4741 return static_cast<unsigned char>(c);
4742 }
4743 "};
4744 let rs = quote! {
4745 let c = ffi::make_char();
4746 assert_eq!(ffi::take_char(c), 97);
4747 };
4748 run_test("", hdr, rs, &["make_char", "take_char"], &[]);
4749}
4750
4751#[test]
4752fn test_ignore_dependent_qualified_type() {
4753 let hdr = indoc! {"
4754 #include <stddef.h>
4755 struct MyString {
4756 typedef char value_type;
4757 };
4758 template<typename T> struct MyStringView {
4759 typedef typename T::value_type view_value_type;
4760 const view_value_type* start;
4761 size_t length;
4762 };
4763 MyStringView<MyString> make_string_view();
4764 struct B {
4765 B() {}
4766 inline size_t take_string_view(const MyStringView<MyString> bit) {
4767 return bit.length;
4768 }
4769 };
4770 "};
4771 let cpp = indoc! {"
4772 const char* HELLO = \"hello\";
4773 MyStringView<MyString> make_string_view() {
4774 MyStringView<MyString> r;
4775 r.start = HELLO;
4776 r.length = 2;
4777 return r;
4778 }
4779 "};
4780 let rs = quote! {
4781 ffi::B::new().within_unique_ptr();
4782 };
4783 run_test(cpp, hdr, rs, &["B"], &[]);
4784}
4785
4786#[test]
4787fn test_ignore_dependent_qualified_type_reference() {
4788 let hdr = indoc! {"
4789 #include <stddef.h>
4790 struct MyString {
4791 typedef char value_type;
4792 };
4793 template<typename T> struct MyStringView {
4794 typedef typename T::value_type view_value_type;
4795 const view_value_type* start;
4796 size_t length;
4797 };
4798 MyStringView<MyString> make_string_view();
4799 struct B {
4800 B() {}
4801 inline size_t take_string_view(const MyStringView<MyString>& bit) {
4802 return bit.length;
4803 }
4804 };
4805 "};
4806 let cpp = indoc! {"
4807 const char* HELLO = \"hello\";
4808 MyStringView<MyString> make_string_view() {
4809 MyStringView<MyString> r;
4810 r.start = HELLO;
4811 r.length = 2;
4812 return r;
4813 }
4814 "};
4815 let rs = quote! {
4816 ffi::B::new().within_unique_ptr();
4817 };
4818 run_test(cpp, hdr, rs, &["B"], &[]);
4819}
4820
4821#[test]
4822fn test_specialization() {
4823 let hdr = indoc! {"
4824 #include <stddef.h>
4825 #include <stdint.h>
4826 #include <string>
4827 #include <type_traits>
4828
4829 template <typename T, bool = std::is_trivially_destructible<T>::value>
4830 struct OptionalStorageBase {
4831 T value_;
4832 };
4833
4834 template <typename T,
4835 bool = std::is_trivially_copy_constructible<T>::value,
4836 bool = std::is_trivially_move_constructible<T>::value>
4837 struct OptionalStorage : OptionalStorageBase<T> {};
4838
4839 template <typename T>
4840 struct OptionalStorage<T,
4841 true /* trivially copy constructible */,
4842 false /* trivially move constructible */>
4843 : OptionalStorageBase<T> {
4844 };
4845
4846 template <typename T>
4847 struct OptionalStorage<T,
4848 false /* trivially copy constructible */,
4849 true /* trivially move constructible */>
4850 : OptionalStorageBase<T> {
4851 };
4852
4853 template <typename T>
4854 struct OptionalStorage<T,
4855 true /* trivially copy constructible */,
4856 true /* trivially move constructible */>
4857 : OptionalStorageBase<T> {
4858 };
4859
4860 template <typename T>
4861 class OptionalBase {
4862 private:
4863 OptionalStorage<T> storage_;
4864 };
4865
4866 template <typename T>
4867 class Optional : public OptionalBase<T> {
4868
4869 };
4870
4871 struct B {
4872 B() {}
4873 void take_optional(Optional<std::string>) {}
4874 uint32_t a;
4875 };
4876 "};
4877 let rs = quote! {
4878 ffi::B::new().within_unique_ptr();
4879 };
4880 run_test("", hdr, rs, &["B"], &[]);
4881}
4882
4883#[test]
4884fn test_private_constructor_make_unique() {
4885 let hdr = indoc! {"
4886 #include <stdint.h>
4887 struct A {
4888 private:
4889 A() {};
4890 public:
4891 uint32_t a;
4892 };
4893 "};
4894 let rs = quote! {};
4895 run_test("", hdr, rs, &["A"], &[]);
4896}
4897
4898#[test]
4899#[ignore] // https://github.com/google/autocxx/issues/266
4900fn test_take_array() {
4901 let hdr = indoc! {"
4902 #include <cstdint>
4903 uint32_t take_array(const uint32_t a[4]) {
4904 return a[0] + a[2];
4905 }
4906 "};
4907 let rs = quote! {
4908 let c: [u32; 4usize] = [ 10, 20, 30, 40 ];
4909 let c = c as *const [_];
4910 assert_eq!(ffi::take_array(&c), 40);
4911 };
4912 run_test("", hdr, rs, &["take_array"], &[]);
4913}
4914
4915#[test]
4916fn test_take_array_in_struct() {
4917 let hdr = indoc! {"
4918 #include <cstdint>
4919 struct data {
4920 char a[4];
4921 };
4922 uint32_t take_array(const data a) {
4923 return a.a[0] + a.a[2];
4924 }
4925 "};
4926 let rs = quote! {
4927 let c = ffi::data { a: [ 10, 20, 30, 40 ] };
4928 assert_eq!(ffi::take_array(c), 40);
4929 };
4930 run_test("", hdr, rs, &["take_array"], &["data"]);
4931}
4932
4933#[test]
4934fn test_union_ignored() {
4935 let hdr = indoc! {"
4936 #include <cstdint>
4937 union A {
4938 uint32_t a;
4939 float b;
4940 };
4941 struct B {
4942 B() :a(1) {}
4943 uint32_t take_union(A) const {
4944 return 3;
4945 }
4946 uint32_t get_a() const { return 2; }
4947 uint32_t a;
4948 };
4949 "};
4950 let rs = quote! {
4951 let b = ffi::B::new().within_unique_ptr();
4952 assert_eq!(b.get_a(), 2);
4953 };
4954 run_test("", hdr, rs, &["B"], &[]);
4955}
4956
4957#[test]
4958fn test_double_underscores_ignored() {
4959 let hdr = indoc! {"
4960 #include <cstdint>
4961 struct __FOO {
4962 uint32_t a;
4963 };
4964 struct B {
4965 B() :a(1) {}
4966 uint32_t take_foo(__FOO) const {
4967 return 3;
4968 }
4969 void do__something() const { }
4970 uint32_t get_a() const { return 2; }
4971 uint32_t a;
4972 };
4973
4974 struct __default { __default() = default; };
4975 struct __destructor { ~__destructor() = default; };
4976 struct __copy { __copy(const __copy&) = default; };
4977 struct __copy_operator { __copy_operator &operator=(const __copy_operator&) = default; };
4978 struct __move { __move(__move&&) = default; };
4979 struct __move_operator { __move_operator &operator=(const __move_operator&) = default; };
4980 "};
4981 let rs = quote! {
4982 let b = ffi::B::new().within_unique_ptr();
4983 assert_eq!(b.get_a(), 2);
4984 };
4985 run_test(
4986 "",
4987 hdr,
4988 rs,
4989 &[
4990 "B",
4991 "__default",
4992 "__destructor",
4993 "__copy",
4994 "__copy_operator",
4995 "__move",
4996 "__move_operator",
4997 ],
4998 &[],
4999 );
5000}
5001
5002// This test fails on Windows gnu but not on Windows msvc
5003#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
5004#[test]
5005fn test_double_underscore_typedef_ignored() {
5006 let hdr = indoc! {"
5007 #include <cstdint>
5008 typedef int __int32_t;
5009 typedef __int32_t __darwin_pid_t;
5010 typedef __darwin_pid_t pid_t;
5011 struct B {
5012 B() :a(1) {}
5013 uint32_t take_foo(pid_t) const {
5014 return 3;
5015 }
5016 uint32_t get_a() const { return 2; }
5017 uint32_t a;
5018 };
5019 "};
5020 let rs = quote! {
5021 let b = ffi::B::new().within_unique_ptr();
5022 assert_eq!(b.get_a(), 2);
5023 };
5024 run_test("", hdr, rs, &["B"], &[]);
5025}
5026
5027#[test]
5028fn test_double_underscores_fn_namespace() {
5029 let hdr = indoc! {"
5030 namespace __B {
5031 inline void a() {}
5032 };
5033 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07005034 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -07005035}
5036
5037#[test]
5038fn test_typedef_to_ptr_is_marked_unsafe() {
5039 let hdr = indoc! {"
5040 struct _xlocalefoo; /* forward reference */
5041 typedef struct _xlocalefoo * locale_tfoo;
5042 extern \"C\" {
5043 locale_tfoo duplocalefoo(locale_tfoo);
5044 }
5045 "};
5046 let rs = quote! {};
5047 run_test("", hdr, rs, &["duplocalefoo"], &[]);
5048}
5049
5050#[test]
5051fn test_issue_264() {
5052 let hdr = indoc! {"
5053 namespace a {
5054 typedef int b;
5055 //inline namespace c {}
5056 template <typename> class aa;
5057 inline namespace c {
5058 template <typename d, typename = d, typename = aa<d>> class e;
5059 }
5060 typedef e<char> f;
5061 template <typename g, typename, template <typename> typename> struct h {
5062 using i = g;
5063 };
5064 template <typename g, template <typename> class k> using j = h<g, void, k>;
5065 template <typename g, template <typename> class k>
5066 using m = typename j<g, k>::i;
5067 template <typename> struct l { typedef b ab; };
5068 template <typename p> class aa {
5069 public:
5070 typedef p n;
5071 };
5072 struct r {
5073 template <typename p> using o = typename p::c;
5074 };
5075 template <typename ad> struct u : r {
5076 typedef typename ad::n n;
5077 using ae = m<n, o>;
5078 template <typename af, typename> struct v { using i = typename l<f>::ab; };
5079 using ab = typename v<ad, ae>::i;
5080 };
5081 } // namespace a
5082 namespace q {
5083 template <typename ad> struct w : a::u<ad> {};
5084 } // namespace q
5085 namespace a {
5086 inline namespace c {
5087 template <typename, typename, typename ad> class e {
5088 typedef q::w<ad> s;
5089 public:
5090 typedef typename s::ab ab;
5091 };
5092 } // namespace c
5093 } // namespace a
5094 namespace ag {
5095 namespace ah {
5096 typedef a::f::ab t;
5097 class ai {
5098 public:
5099 t aj;
5100 };
5101 class al;
5102 namespace am {
5103 class an {
5104 public:
5105 void ao(ai);
5106 };
5107 } // namespace am
5108 class ap {
5109 public:
5110 al aq();
5111 };
5112 class ar {
5113 public:
5114 am::an as;
5115 };
5116 class al {
5117 public:
5118 ar at;
5119 };
5120 struct au {
5121 ap av;
5122 };
5123 } // namespace ah
5124 } // namespace ag
5125 namespace operations_research {
5126 class aw {
5127 public:
5128 ag::ah::au ax;
5129 };
5130 class Solver {
5131 public:
5132 aw ay;
5133 };
5134 } // namespace operations_research
5135 "};
5136 let rs = quote! {};
5137 run_test_ex(
5138 "",
5139 hdr,
5140 rs,
5141 directives_from_lists(&["operations_research::Solver"], &[], None),
5142 make_cpp17_adder(),
5143 None,
5144 None,
5145 );
5146}
5147
5148#[test]
5149fn test_unexpected_use() {
5150 // https://github.com/google/autocxx/issues/303
5151 let hdr = indoc! {"
5152 typedef int a;
5153 namespace b {
5154 namespace c {
5155 enum d : a;
5156 }
5157 } // namespace b
5158 namespace {
5159 using d = b::c::d;
5160 }
5161 namespace content {
5162 class RenderFrameHost {
5163 public:
5164 RenderFrameHost() {}
5165 d e;
5166 };
5167 } // namespace content
5168 "};
5169 let rs = quote! {
5170 let _ = ffi::content::RenderFrameHost::new().within_unique_ptr();
5171 };
5172 run_test("", hdr, rs, &["content::RenderFrameHost"], &[]);
5173}
5174
5175#[test]
5176fn test_get_pure_virtual() {
5177 let hdr = indoc! {"
5178 #include <cstdint>
5179 class A {
5180 public:
5181 virtual ~A() {}
5182 virtual uint32_t get_val() const = 0;
5183 };
5184 class B : public A {
5185 public:
5186 virtual uint32_t get_val() const { return 3; }
5187 };
5188 const B b;
5189 inline const A* get_a() { return &b; };
5190 "};
5191 let rs = quote! {
5192 let a = ffi::get_a();
5193 let a_ref = unsafe { a.as_ref() }.unwrap();
5194 assert_eq!(a_ref.get_val(), 3);
5195 };
5196 run_test("", hdr, rs, &["A", "get_a"], &[]);
5197}
5198
5199#[test]
5200fn test_abstract_class_no_make_unique() {
5201 // We shouldn't generate a new().within_unique_ptr() for abstract classes.
5202 // The test is successful if the bindings compile, i.e. if autocxx doesn't
5203 // attempt to instantiate the class.
5204 let hdr = indoc! {"
5205 class A {
5206 public:
5207 A() {}
5208 virtual ~A() {}
5209 virtual void foo() const = 0;
5210 };
5211 "};
5212 let rs = quote! {};
5213 run_test("", hdr, rs, &["A"], &[]);
5214}
5215
5216#[test]
5217fn test_derived_abstract_class_no_make_unique() {
5218 let hdr = indoc! {"
5219 class A {
5220 public:
5221 A();
5222 virtual ~A() {}
5223 virtual void foo() const = 0;
5224 };
5225
5226 class B : public A {
5227 public:
5228 B();
5229 };
5230 "};
5231 let rs = quote! {};
5232 run_test("", hdr, rs, &["A", "B"], &[]);
5233}
5234
5235#[test]
5236fn test_recursive_derived_abstract_class_no_make_unique() {
5237 let hdr = indoc! {"
5238 class A {
5239 public:
5240 A() {}
5241 virtual ~A() {}
5242 virtual void foo() const = 0;
5243 };
5244
5245 class B : public A {
5246 public:
5247 B() {};
5248 };
5249
5250 class C : public B {
5251 public:
5252 C() {};
5253 };
5254 "};
5255 let rs = quote! {};
5256 run_test("", hdr, rs, &["A", "B", "C"], &[]);
5257}
5258
5259#[test]
5260fn test_derived_abstract_class_with_no_allowlisting_no_make_unique() {
5261 let hdr = indoc! {"
5262 class A {
5263 public:
5264 A();
5265 virtual ~A() {}
5266 virtual void foo() const = 0;
5267 };
5268
5269 class B : public A {
5270 public:
5271 B();
5272 };
5273 "};
5274 let rs = quote! {};
5275 run_test("", hdr, rs, &["B"], &[]);
5276}
5277
5278#[test]
5279fn test_vector_of_pointers() {
5280 // Just ensures the troublesome API is ignored
5281 let hdr = indoc! {"
5282 #include <vector>
5283 namespace operations_research {
5284 class a;
5285 class Solver {
5286 public:
5287 struct b c(std::vector<a *>);
5288 };
5289 class a {};
5290 } // namespace operations_research
5291 "};
5292 let rs = quote! {};
5293 run_test("", hdr, rs, &["operations_research::Solver"], &[]);
5294}
5295
5296#[test]
5297fn test_vec_and_up_of_primitives() {
5298 let hdr = indoc! {"
5299 #include <vector>
5300 #include <memory>
5301 #include <cstdint>
5302 class Value {
5303 public:
5304 Value(std::vector<uint32_t>) {} // OK
5305 Value(std::unique_ptr<uint32_t>) {} // should be ignored
5306 Value(std::vector<int>) {} // should be ignored
5307 Value(std::unique_ptr<int>) {} // should be ignored
5308 Value(std::vector<char>) {} // should be ignored
5309 Value(std::unique_ptr<char>) {} // should be ignored
5310 Value(std::vector<float>) {} // OK
5311 Value(std::unique_ptr<float>) {} // should be ignored
5312 Value(std::vector<bool>) {} // should be ignored
5313 Value(std::unique_ptr<bool>) {} // should be ignored
5314 Value(std::vector<size_t>) {} // OK
5315 Value(std::unique_ptr<size_t>) {} // should be ignored
5316 };
5317 inline std::vector<uint32_t> make_vec_uint32_t() {
5318 std::vector<uint32_t> a;
5319 return a;
5320 }
5321 inline std::vector<float> make_vec_float() {
5322 std::vector<float> a;
5323 return a;
5324 }
5325 inline std::vector<size_t> make_vec_size_t() {
5326 std::vector<size_t> a;
5327 return a;
5328 }
5329 "};
5330 let rs = quote! {
5331 ffi::Value::new(ffi::make_vec_uint32_t()).within_box();
5332 ffi::Value::new6(ffi::make_vec_float()).within_box();
5333 ffi::Value::new10(ffi::make_vec_size_t()).within_box();
5334 };
5335 run_test(
5336 "",
5337 hdr,
5338 rs,
5339 &[
5340 "Value",
5341 "make_vec_uint32_t",
5342 "make_vec_float",
5343 "make_vec_size_t",
5344 ],
5345 &[],
5346 );
5347}
5348
5349#[test]
5350fn test_pointer_to_pointer() {
5351 // Just ensures the troublesome API is ignored
5352 let hdr = indoc! {"
5353 namespace operations_research {
5354 class a;
5355 class Solver {
5356 public:
5357 struct b c(a **);
5358 };
5359 class a {};
5360 } // namespace operations_research
5361 "};
5362 let rs = quote! {};
5363 run_test("", hdr, rs, &["operations_research::Solver"], &[]);
5364}
5365
5366#[test]
5367fn test_defines_effective() {
5368 let hdr = indoc! {"
5369 #include <cstdint>
5370 #ifdef FOO
5371 inline uint32_t a() { return 4; }
5372 #endif
5373 "};
5374 let rs = quote! {
5375 ffi::a();
5376 };
5377 run_test_ex(
5378 "",
5379 hdr,
5380 rs,
5381 quote! { generate!("a") },
5382 make_clang_arg_adder(&["-DFOO"]),
5383 None,
5384 None,
5385 );
5386}
5387
5388#[test]
5389#[ignore] // https://github.com/google/autocxx/issues/227
5390fn test_function_pointer_template() {
5391 let hdr = indoc! {"
5392 typedef int a;
5393 namespace std {
5394 template <typename> class b;
5395 }
5396 typedef a c;
5397 namespace operations_research {
5398 class d;
5399 class Solver {
5400 public:
5401 typedef std::b<c()> IndexEvaluator3;
5402 d e(IndexEvaluator3);
5403 };
5404 class d {};
5405 } // namespace operations_research
5406 "};
5407 let rs = quote! {};
5408 run_test("", hdr, rs, &["operations_research::Solver"], &[]);
5409}
5410
5411#[test]
5412fn test_cvoid() {
5413 let hdr = indoc! {"
5414 #include <memory>
5415 #include <cstdint>
5416 inline void* a() {
5417 return static_cast<void*>(new int(3));
5418 }
5419 inline uint32_t b(void* p) {
5420 int* p_int = static_cast<int*>(p);
5421 auto val = *p_int;
5422 delete p_int;
5423 return val;
5424 }
5425 "};
5426 let rs = quote! {
5427 let ptr = ffi::a();
5428 let res = unsafe { ffi::b(ptr) };
5429 assert_eq!(res, 3);
5430 };
5431 run_test("", hdr, rs, &["a", "b"], &[]);
5432}
5433
5434#[test]
5435fn test_c_schar() {
5436 let hdr = indoc! {"
5437 inline signed char a() {
5438 return 8;
5439 }
5440 "};
5441 let rs = quote! {
5442 assert_eq!(ffi::a(), 8);
5443 };
5444 run_test("", hdr, rs, &["a"], &[]);
5445}
5446
5447#[test]
5448fn test_c_uchar() {
5449 let hdr = indoc! {"
5450 inline unsigned char a() {
5451 return 8;
5452 }
5453 "};
5454 let rs = quote! {
5455 assert_eq!(ffi::a(), 8);
5456 };
5457 run_test("", hdr, rs, &["a"], &[]);
5458}
5459
5460#[test]
5461fn test_c_ulonglong() {
5462 // We don't test all the different variable-length integer types which we populate.
5463 // If one works, they probably all do. Hopefully.
5464 let hdr = indoc! {"
5465 inline unsigned long long a() {
5466 return 8;
5467 }
5468 "};
5469 let rs = quote! {
5470 assert_eq!(ffi::a(), autocxx::c_ulonglong(8));
5471 };
5472 run_test("", hdr, rs, &["a"], &[]);
5473}
5474
5475#[test]
5476fn test_string_transparent_function() {
5477 let hdr = indoc! {"
5478 #include <string>
5479 #include <cstdint>
5480 inline uint32_t take_string(std::string a) { return a.size(); }
5481 "};
5482 let rs = quote! {
5483 assert_eq!(ffi::take_string("hello"), 5);
5484 };
5485 run_test("", hdr, rs, &["take_string"], &[]);
5486}
5487
5488#[test]
5489fn test_string_transparent_method() {
5490 let hdr = indoc! {"
5491 #include <string>
5492 #include <cstdint>
5493 struct A {
5494 A() {}
5495 inline uint32_t take_string(std::string a) const { return a.size(); }
5496 };
5497 "};
5498 let rs = quote! {
5499 let a = ffi::A::new().within_unique_ptr();
5500 assert_eq!(a.take_string("hello"), 5);
5501 };
5502 run_test("", hdr, rs, &["A"], &[]);
5503}
5504
5505#[test]
5506fn test_string_transparent_static_method() {
5507 let hdr = indoc! {"
5508 #include <string>
5509 #include <cstdint>
5510 struct A {
5511 A() {}
5512 static inline uint32_t take_string(std::string a) { return a.size(); }
5513 };
5514 "};
5515 let rs = quote! {
5516 assert_eq!(ffi::A::take_string("hello"), 5);
5517 };
5518 run_test("", hdr, rs, &["A"], &[]);
5519}
5520
5521#[test]
5522#[ignore] // https://github.com/google/autocxx/issues/490
5523fn test_issue_490() {
5524 let hdr = indoc! {"
5525 typedef int a;
5526 typedef long unsigned size_t;
5527 namespace std {
5528 namespace {
5529 using ::size_t;
5530 template <class b, b c> struct g { static const b value = c; };
5531 template <bool d> using e = g<bool, d>;
5532 typedef e<true> true_type;
5533 template <size_t, size_t> struct ag {};
5534 template <class b> typename b ::h move();
5535 template <class> class allocator;
5536 template <class> class vector;
5537 } // namespace
5538 } // namespace std
5539 void *operator new(size_t, void *);
5540 namespace std {
5541 namespace {
5542 template <class> struct iterator;
5543 template <class b, class> struct ay { using h = b *; };
5544 template <class b> struct bj { b bk; };
5545 template <class bm, class> class bn : bj<bm> {};
5546 template <class b, class i = b> class unique_ptr {
5547 typedef i bp;
5548 typedef typename ay<b, bp>::h bh;
5549 bn<bh, bp> bq;
5550
5551 public:
5552 unique_ptr();
5553 unique_ptr(bh);
5554 bh get() const;
5555 bh release();
5556 };
5557 template <class = void> struct bt;
5558 } // namespace
5559 } // namespace std
5560 typedef a bv;
5561 namespace absl {
5562 template <typename ce> class cj {
5563 public:
5564 using bh = ce *;
5565 using iterator = bh;
5566 };
5567 namespace j {
5568 template <class ce> struct cp {
5569 using k = ce;
5570 using cq = std::bt<>;
5571 };
5572 template <class ce> using cr = typename cp<ce>::k;
5573 template <class ce> using cs = typename cp<ce>::cq;
5574 template <class, class, class, class> class ct {
5575 public:
5576 class iterator {};
5577 class cu {
5578 cu(iterator);
5579 iterator cv;
5580 };
5581 };
5582 template <typename> struct cw;
5583 } // namespace j
5584 template <class ce, class k = j::cr<ce>, class cq = j::cs<ce>,
5585 class cx = std::allocator<ce>>
5586 class cy : public j::ct<j::cw<ce>, k, cq, cx> {};
5587 } // namespace absl
5588 namespace cz {
5589 template <typename da> class db { std::ag<sizeof(a), alignof(da)> c; };
5590 } // namespace cz
5591 namespace spanner {
5592 class l;
5593 class ColumnList {
5594 public:
5595 typedef absl::cj<l>::iterator iterator;
5596 iterator begin();
5597 };
5598 class dd {
5599 union {
5600 cz::db<absl::cy<bv>::cu> e;
5601 };
5602 };
5603 class Row {
5604 public:
5605 bool f(dd);
5606 };
5607 } // namespace spanner
5608 "};
5609 let rs = quote! {};
5610 run_test("", hdr, rs, &["spanner::Row", "spanner::ColumnList"], &[]);
5611}
5612
5613#[test]
5614fn test_immovable_object() {
5615 let hdr = indoc! {"
5616 class A {
5617 public:
5618 A();
5619 A(A&&) = delete;
5620 };
5621
5622 class B{
5623 public:
5624 B();
5625 B(const B&) = delete;
5626 };
5627 "};
5628 let rs = quote! {};
5629 run_test("", hdr, rs, &["A", "B"], &[]);
5630}
5631
5632#[test]
5633fn test_struct_with_reference() {
5634 let hdr = indoc! {"
5635 #include <cstdint>
5636 #include <utility>
5637 struct A {
5638 uint32_t a;
5639 };
5640 struct B {
5641 B(const A& param) : a(param) {}
5642 const A& a;
5643 };
5644 "};
5645 let rs = quote! {};
5646 run_test("", hdr, rs, &["A", "B"], &[]);
5647}
5648
5649#[test]
5650fn test_struct_with_rvalue() {
5651 let hdr = indoc! {"
5652 #include <cstdint>
5653 #include <utility>
5654 struct A {
5655 uint32_t a;
5656 };
5657 struct B {
5658 B(A&& param) : a(std::move(param)) {}
5659 A&& a;
5660 };
5661 "};
5662 let rs = quote! {};
5663 run_test("", hdr, rs, &["A", "B"], &[]);
5664}
5665
5666#[test]
5667fn test_immovable_nested_object() {
5668 let hdr = indoc! {"
5669 struct C {
5670 class A {
5671 public:
5672 A();
5673 A(A&&) = delete;
5674 };
5675
5676 class B{
5677 public:
5678 B();
5679 B(const B&) = delete;
5680 };
5681 };
5682 "};
5683 let rs = quote! {};
5684 run_test("", hdr, rs, &["C_A", "C_B"], &[]);
5685}
5686
5687#[test]
5688fn test_type_called_type() {
5689 let hdr = indoc! {"
5690 namespace a {
5691 template<int _Len>
5692 struct b
5693 {
5694 union type
5695 {
5696 unsigned char __data[_Len];
5697 struct foo {
5698 int a;
5699 };
5700 };
5701 };
5702 }
5703 inline void take_type(a::b<4>::type) {}
5704 "};
5705 let rs = quote! {};
5706 run_test("", hdr, rs, &["take_type"], &[]);
5707}
5708
5709#[test]
5710fn test_bridge_conflict_ty() {
5711 let hdr = indoc! {"
5712 namespace a {
5713 struct Key { int a; };
5714 }
5715 namespace b {
5716 struct Key { int a; };
5717 }
5718 "};
5719 let rs = quote! {};
5720 run_test("", hdr, rs, &["a::Key", "b::Key"], &[]);
5721}
5722
5723#[test]
5724fn test_bridge_conflict_ty_fn() {
5725 let hdr = indoc! {"
5726 namespace a {
5727 struct Key { int a; };
5728 }
5729 namespace b {
5730 inline void Key() {}
5731 }
5732 "};
5733 let rs = quote! {};
5734 run_test("", hdr, rs, &["a::Key", "b::Key"], &[]);
5735}
5736
5737#[test]
5738fn test_issue_506() {
5739 let hdr = indoc! {"
5740 namespace std {
5741 template <class, class> class am;
5742 typedef am<char, char> an;
5743 } // namespace std
5744 namespace be {
5745 class bf {
5746 virtual std::an bg() = 0;
5747 };
5748 class bh : bf {};
5749 } // namespace be
5750 namespace spanner {
5751 class Database;
5752 class Row {
5753 public:
5754 Row(be::bh *);
5755 };
5756 } // namespace spanner
5757 "};
5758 let rs = quote! {};
5759 run_test("", hdr, rs, &["spanner::Database", "spanner::Row"], &[]);
5760}
5761
5762#[test]
5763fn test_private_inheritance() {
5764 let hdr = indoc! {"
5765 class A {
5766 public:
5767 void foo() {}
5768 int a;
5769 };
5770 class B : A {
5771 public:
5772 void bar() {}
5773 int b;
5774 };
5775 "};
5776 let rs = quote! {};
5777 run_test("", hdr, rs, &["A", "B"], &[]);
5778}
5779
5780#[test]
5781fn test_error_generated_for_static_data() {
5782 let hdr = indoc! {"
5783 #include <cstdint>
5784 struct A {
5785 A() {}
5786 uint32_t a;
5787 };
5788 static A FOO = A();
5789 "};
5790 let rs = quote! {};
5791 run_test_ex(
5792 "",
5793 hdr,
5794 rs,
5795 quote! { generate!("FOO")},
5796 None,
5797 Some(make_error_finder("FOO")),
5798 None,
5799 );
5800}
5801
5802#[test]
5803fn test_error_generated_for_array_dependent_function() {
5804 let hdr = indoc! {"
5805 #include <cstdint>
5806 #include <functional>
5807 inline void take_func(std::function<bool(const uint32_t number)>) {
5808 }
5809 "};
5810 let rs = quote! {};
5811 run_test_ex(
5812 "",
5813 hdr,
5814 rs,
5815 quote! { generate! ("take_func")},
5816 None,
5817 Some(make_error_finder("take_func")),
5818 None,
5819 );
5820}
5821
5822#[test]
5823#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
5824#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
5825fn test_error_generated_for_array_dependent_method() {
5826 let hdr = indoc! {"
5827 #include <cstdint>
5828 #include <functional>
5829 struct A {
5830 void take_func(std::function<bool(const uint32_t number)>) {
5831 }
5832 };
5833 "};
5834 let rs = quote! {};
5835 run_test_ex(
5836 "",
5837 hdr,
5838 rs,
5839 quote! { generate! ("A")},
5840 None,
5841 Some(make_string_finder(
5842 ["take_func", "couldn't be generated"]
5843 .map(|s| s.to_string())
5844 .to_vec(),
5845 )),
5846 None,
5847 );
5848}
5849
5850#[test]
5851fn test_error_generated_for_pod_with_nontrivial_destructor() {
5852 // take_a is necessary here because cxx won't generate the required
5853 // static assertions unless the type is actually used in some context
5854 // where cxx needs to decide it's trivial or non-trivial.
5855 let hdr = indoc! {"
5856 #include <cstdint>
5857 #include <functional>
5858 struct A {
5859 ~A() {}
5860 };
5861 inline void take_a(A) {}
5862 "};
5863 let rs = quote! {};
5864 run_test_expect_fail("", hdr, rs, &["take_a"], &["A"]);
5865}
5866
5867#[test]
5868fn test_error_generated_for_pod_with_nontrivial_move_constructor() {
5869 // take_a is necessary here because cxx won't generate the required
5870 // static assertions unless the type is actually used in some context
5871 // where cxx needs to decide it's trivial or non-trivial.
5872 let hdr = indoc! {"
5873 #include <cstdint>
5874 #include <functional>
5875 struct A {
5876 A() = default;
5877 A(A&&) {}
5878 };
5879 inline void take_a(A) {}
5880 "};
5881 let rs = quote! {};
5882 run_test_expect_fail("", hdr, rs, &["take_a"], &["A"]);
5883}
5884
5885#[test]
5886fn test_double_destruction() {
5887 let hdr = indoc! {"
5888 #include <stdio.h>
5889 #include <stdlib.h>
5890 // A simple type to let Rust verify the destructor is run.
5891 struct NotTriviallyDestructible {
5892 NotTriviallyDestructible() = default;
5893 NotTriviallyDestructible(const NotTriviallyDestructible&) = default;
5894 NotTriviallyDestructible(NotTriviallyDestructible&&) = default;
5895
5896 ~NotTriviallyDestructible() {}
5897 };
5898
5899 struct ExplicitlyDefaulted {
5900 ExplicitlyDefaulted() = default;
5901 ~ExplicitlyDefaulted() = default;
5902
5903 NotTriviallyDestructible flag;
5904 };
5905 "};
5906 let rs = quote! {
5907 moveit! {
5908 let mut moveit_t = ffi::ExplicitlyDefaulted::new();
5909 }
5910 };
5911 match do_run_test(
5912 "",
5913 hdr,
5914 rs,
5915 directives_from_lists(
5916 &[],
5917 &["NotTriviallyDestructible", "ExplicitlyDefaulted"],
5918 None,
5919 ),
5920 None,
5921 None,
5922 None,
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07005923 "unsafe_ffi",
Brian Silverman4e662aa2022-05-11 23:10:19 -07005924 ) {
5925 Err(TestError::CppBuild(_)) => {} // be sure this fails due to a static_assert
5926 // rather than some runtime problem
5927 _ => panic!("Test didn't fail as expected"),
5928 };
5929}
5930
5931#[test]
5932fn test_keyword_function() {
5933 let hdr = indoc! {"
5934 inline void move(int) {};
5935 "};
5936 let rs = quote! {};
5937 run_test("", hdr, rs, &["move_"], &[]);
5938}
5939
5940#[test]
5941fn test_keyword_method() {
5942 let hdr = indoc! {"
5943 struct A {
5944 int a;
5945 inline void move() {};
5946 };
5947 "};
5948 let rs = quote! {};
5949 run_test("", hdr, rs, &["A"], &[]);
5950}
5951
5952#[test]
5953fn test_doc_passthru() {
5954 let hdr = indoc! {"
5955 #include <cstdint>
5956 /// Elephants!
5957 struct A {
5958 uint32_t a;
5959 };
5960 /// Giraffes!
5961 struct B {
5962 uint32_t a;
5963 };
5964 /// Rhinos!
5965 inline uint32_t get_a() { return 3; }
5966 "};
5967 let rs = quote! {};
5968 run_test_ex(
5969 "",
5970 hdr,
5971 rs,
5972 directives_from_lists(&["A", "get_a"], &["B"], None),
5973 None,
5974 Some(make_string_finder(
5975 ["Giraffes", "Elephants", "Rhinos"]
5976 .map(|s| s.to_string())
5977 .to_vec(),
5978 )),
5979 None,
5980 );
5981}
5982
5983#[test]
5984fn test_closure() {
5985 // Ensuring presence of this closure doesn't break other things
5986 let hdr = indoc! {"
5987 #include <functional>
5988 #include <cstdint>
5989
5990 inline bool take_closure(std::function<bool(const uint32_t number)> fn) {
5991 return fn(5);
5992 }
5993 inline uint32_t get_a() {
5994 return 3;
5995 }
5996 "};
5997 let rs = quote! {
5998 assert_eq!(ffi::get_a(), 3);
5999 };
6000 run_test("", hdr, rs, &["get_a"], &[]);
6001}
6002
6003#[test]
6004fn test_multiply_nested_inner_type() {
6005 let hdr = indoc! {"
6006 struct Turkey {
6007 struct Duck {
6008 struct Hen {
6009 int wings;
6010 };
6011 struct HenWithDefault {
6012 HenWithDefault() = default;
6013 int wings;
6014 };
6015 struct HenWithDestructor {
6016 ~HenWithDestructor() = default;
6017 int wings;
6018 };
6019 struct HenWithCopy {
6020 HenWithCopy() = default;
6021 HenWithCopy(const HenWithCopy&) = default;
6022 int wings;
6023 };
6024 struct HenWithMove {
6025 HenWithMove() = default;
6026 HenWithMove(HenWithMove&&) = default;
6027 int wings;
6028 };
6029 };
6030 };
6031 "};
6032 let rs = quote! {
6033 ffi::Turkey_Duck_Hen::new().within_unique_ptr();
6034 ffi::Turkey_Duck_HenWithDefault::new().within_unique_ptr();
6035 ffi::Turkey_Duck_HenWithDestructor::new().within_unique_ptr();
6036 ffi::Turkey_Duck_HenWithCopy::new().within_unique_ptr();
6037 ffi::Turkey_Duck_HenWithMove::new().within_unique_ptr();
6038
6039 moveit! {
6040 let hen = ffi::Turkey_Duck_Hen::new();
6041 let moved_hen = autocxx::moveit::new::mov(hen);
6042 let _copied_hen = autocxx::moveit::new::copy(moved_hen);
6043
6044 let hen = ffi::Turkey_Duck_HenWithDefault::new();
6045 let moved_hen = autocxx::moveit::new::mov(hen);
6046 let _copied_hen = autocxx::moveit::new::copy(moved_hen);
6047
6048 let _hen = ffi::Turkey_Duck_HenWithDestructor::new();
6049
6050 let hen = ffi::Turkey_Duck_HenWithCopy::new();
6051 let _copied_hen = autocxx::moveit::new::copy(hen);
6052
6053 let hen = ffi::Turkey_Duck_HenWithMove::new();
6054 let _moved_hen = autocxx::moveit::new::mov(hen);
6055 }
6056 };
6057 run_test(
6058 "",
6059 hdr,
6060 rs,
6061 &[],
6062 &[
6063 "Turkey_Duck_Hen",
6064 "Turkey_Duck_HenWithDefault",
6065 "Turkey_Duck_HenWithDestructor",
6066 "Turkey_Duck_HenWithCopy",
6067 "Turkey_Duck_HenWithMove",
6068 ],
6069 );
6070}
6071
6072#[test]
6073fn test_underscored_namespace_for_inner_type() {
6074 let hdr = indoc! {"
6075 namespace __foo {
6076 struct daft {
6077 struct bob {
6078 int a;
6079 };
6080 int a;
6081 };
6082 }
6083 inline void bar(__foo::daft::bob) {}
6084 "};
6085 let rs = quote! {};
6086 run_test("", hdr, rs, &["bar"], &[]);
6087}
6088
6089#[test]
6090fn test_blocklist_not_overly_broad() {
6091 // This is a regression test. We used to block anything that starts with "rust" or "std",
6092 // not just items in the "rust" and "std" namespaces. We therefore test that functions starting
6093 // with "rust" or "std" get imported.
6094 let hdr = indoc! {"
6095 inline void rust_func() { }
6096 inline void std_func() { }
6097 "};
6098 let rs = quote! {
6099 ffi::rust_func();
6100 ffi::std_func();
6101 };
6102 run_test("", hdr, rs, &["rust_func", "std_func"], &[]);
6103}
6104
6105#[test]
6106#[ignore] // https://github.com/google/autocxx/issues/837
6107fn test_ref_qualified_method() {
6108 let hdr = indoc! {"
6109 struct A {
6110 void foo() & {}
6111 };
6112 "};
6113 let rs = quote! {
6114 A::new().within_unique_ptr().foo();
6115 };
6116 run_test("", hdr, rs, &["A"], &[]);
6117}
6118
6119#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
6120#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
6121#[test]
6122fn test_stringview() {
6123 // Test that APIs using std::string_view do not otherwise cause errors.
6124 let hdr = indoc! {"
6125 #include <string_view>
6126 #include <string>
6127 void take_string_view(std::string_view) {}
6128 std::string_view return_string_view(const std::string& a) { return std::string_view(a); }
6129 "};
6130 let rs = quote! {};
6131 run_test_ex(
6132 "",
6133 hdr,
6134 rs,
6135 directives_from_lists(&["take_string_view", "return_string_view"], &[], None),
6136 make_cpp17_adder(),
6137 None,
6138 None,
6139 );
6140}
6141
6142#[test]
6143fn test_include_cpp_alone() {
6144 let hdr = indoc! {"
6145 #include <cstdint>
6146 inline uint32_t give_int() {
6147 return 5;
6148 }
6149 "};
6150 let hexathorpe = Token![#](Span::call_site());
6151 let rs = quote! {
6152 use autocxx::include_cpp;
6153 include_cpp! {
6154 #hexathorpe include "input.h"
6155 safety!(unsafe_ffi)
6156 generate!("give_int")
6157 }
6158 fn main() {
6159 assert_eq!(ffi::give_int(), 5);
6160 }
6161 };
6162 do_run_test_manual("", hdr, rs, None, None).unwrap();
6163}
6164
6165#[test]
6166fn test_include_cpp_in_path() {
6167 let hdr = indoc! {"
6168 #include <cstdint>
6169 inline uint32_t give_int() {
6170 return 5;
6171 }
6172 "};
6173 let hexathorpe = Token![#](Span::call_site());
6174 let rs = quote! {
6175 autocxx::include_cpp! {
6176 #hexathorpe include "input.h"
6177 safety!(unsafe_ffi)
6178 generate!("give_int")
6179 }
6180 fn main() {
6181 assert_eq!(ffi::give_int(), 5);
6182 }
6183 };
6184 do_run_test_manual("", hdr, rs, None, None).unwrap();
6185}
6186
6187#[test]
6188fn test_bitset() {
6189 let hdr = indoc! {"
6190 #include <cstddef>
6191 template <size_t _N_words, size_t _Size>
6192 class __bitset
6193 {
6194 public:
6195 typedef size_t __storage_type;
6196 __storage_type __first_[_N_words];
6197 inline bool all() {
6198 return false;
6199 }
6200 };
6201
6202 template <size_t _Size>
6203 class bitset
6204 : private __bitset<_Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) * 8) + 1, _Size>
6205 {
6206 public:
6207 static const unsigned __n_words = _Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) * 8) + 1;
6208 typedef __bitset<__n_words, _Size> base;
6209 bool all() const noexcept;
6210 };
6211
6212
6213 typedef bitset<1> mybitset;
6214 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07006215 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -07006216}
6217
6218#[test]
6219fn test_cint_vector() {
6220 let hdr = indoc! {"
6221 #include <vector>
6222 #include <cstdint>
6223 inline std::vector<int32_t> give_vec() {
6224 return std::vector<int32_t> {1,2};
6225 }
6226 "};
6227
6228 let rs = quote! {
6229 assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[1,2]);
6230 };
6231
6232 run_test("", hdr, rs, &["give_vec"], &[]);
6233}
6234
6235#[test]
6236#[ignore] // https://github.com/google/autocxx/issues/422
6237fn test_int_vector() {
6238 let hdr = indoc! {"
6239 #include <vector>
6240 std::vector<int> give_vec() {
6241 return std::vector<int> {1,2};
6242 }
6243 "};
6244
6245 let rs = quote! {
6246 assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[autocxx::c_int(1),autocxx::c_int(2)]);
6247 };
6248
6249 run_test("", hdr, rs, &["give_vec"], &[]);
6250}
6251
6252#[test]
6253fn test_size_t() {
6254 let hdr = indoc! {"
6255 #include <cstddef>
6256 inline size_t get_count() { return 7; }
6257 "};
6258
6259 let rs = quote! {
6260 ffi::get_count();
6261 };
6262
6263 run_test_ex(
6264 "",
6265 hdr,
6266 rs,
6267 directives_from_lists(&["get_count"], &[], None),
6268 None,
6269 Some(make_rust_code_finder(vec![
6270 quote! {fn get_count() -> usize},
6271 ])),
6272 None,
6273 );
6274}
6275
6276#[test]
6277fn test_deleted_function() {
6278 // We shouldn't generate bindings for deleted functions.
6279 // The test is successful if the bindings compile, i.e. if autocxx doesn't
6280 // attempt to call the deleted function.
6281 let hdr = indoc! {"
6282 class A {
6283 public:
6284 void foo() = delete;
6285 };
6286 "};
6287 let rs = quote! {};
6288 run_test("", hdr, rs, &["A"], &[]);
6289}
6290
6291#[test]
6292fn test_ignore_move_constructor() {
6293 let hdr = indoc! {"
6294 class A {
6295 public:
6296 A() {}
6297 A(A&&) {};
6298 };
6299 "};
6300 let rs = quote! {};
6301 run_test("", hdr, rs, &["A"], &[]);
6302}
6303
6304#[test]
6305fn test_ignore_function_with_rvalue_ref() {
6306 let hdr = indoc! {"
6307 #include <string>
6308
6309 void moveme(std::string &&);
6310 "};
6311 let rs = quote! {};
6312 run_test("", hdr, rs, &["moveme"], &[]);
6313}
6314
6315#[test]
6316fn test_take_nonpod_rvalue_from_up() {
6317 let hdr = indoc! {"
6318 #include <string>
6319 struct A {
6320 std::string a;
6321 };
6322 inline void take_a(A&&) {};
6323 "};
6324 let rs = quote! {
6325 let a = ffi::A::new().within_unique_ptr();
6326 ffi::take_a(a);
6327
6328 let a2 = ffi::A::new().within_box();
6329 ffi::take_a(a2);
6330 };
6331 run_test("", hdr, rs, &["A", "take_a"], &[]);
6332}
6333
6334#[test]
6335fn test_take_nonpod_rvalue_from_stack() {
6336 let hdr = indoc! {"
6337 #include <string>
6338 struct A {
6339 std::string a;
6340 };
6341 inline void take_a(A&&) {};
6342 "};
6343 let rs = quote! {
6344 moveit! { let a = ffi::A::new() };
6345 ffi::take_a(a);
6346 };
6347 run_test("", hdr, rs, &["A", "take_a"], &[]);
6348}
6349
6350#[test]
6351fn test_overloaded_ignored_function() {
6352 // When overloaded functions are ignored during import, the placeholder
6353 // functions generated for them should have unique names, just as they
6354 // would have if they had been imported successfully.
6355 // The test is successful if the bindings compile.
6356 let hdr = indoc! {"
6357 struct Blocked {};
6358 class A {
6359 public:
6360 void take_blocked(Blocked);
6361 void take_blocked(Blocked, int);
6362 };
6363 "};
6364 let rs = quote! {};
6365 run_test_ex(
6366 "",
6367 hdr,
6368 rs,
6369 quote! {
6370 generate!("A")
6371 block!("Blocked")
6372 },
6373 None,
6374 None,
6375 None,
6376 );
6377}
6378
6379#[test]
6380fn test_namespaced_constant() {
6381 let hdr = indoc! {"
6382 namespace A {
6383 const int kConstant = 3;
6384 }
6385 "};
6386 let rs = quote! {
6387 assert_eq!(ffi::A::kConstant, 3);
6388 };
6389 run_test("", hdr, rs, &["A::kConstant"], &[]);
6390}
6391
6392#[test]
6393fn test_issue_470_492() {
6394 let hdr = indoc! {"
6395 namespace std {
6396 template <bool, typename _Iftrue, typename _Iffalse> struct a;
6397 }
6398 template <typename> struct b;
6399 template <typename d> struct c {
6400 typedef std::a<b<d>::c, int, int> e;
6401 };
6402 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07006403 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -07006404}
6405
6406#[test]
6407fn test_no_impl() {
6408 let hdr = indoc! {"
6409 struct A {
6410 int a;
6411 };
6412 "};
6413 let rs = quote! {};
6414 run_test_ex(
6415 "",
6416 hdr,
6417 rs,
6418 quote! {
6419 exclude_impls!()
6420 exclude_utilities!()
6421 generate!("A")
6422 },
6423 None,
6424 None,
6425 None,
6426 );
6427}
6428
6429#[test]
6430fn test_generate_all() {
6431 let hdr = indoc! {"
6432 #include <cstdint>
6433 inline uint32_t give_int() {
6434 return 5;
6435 }
6436 "};
6437 let rs = quote! {
6438 assert_eq!(ffi::give_int(), 5);
6439 };
6440 run_test_ex(
6441 "",
6442 hdr,
6443 rs,
6444 quote! {
6445 generate_all!()
6446 },
6447 None,
6448 None,
6449 None,
6450 );
6451}
6452
6453#[test]
6454fn test_std_thing() {
6455 let hdr = indoc! {"
6456 #include <cstdint>
6457 namespace std {
6458 struct A {
6459 uint8_t a;
6460 };
6461 }
6462 typedef char daft;
6463 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07006464 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -07006465}
6466
6467#[test]
6468fn test_two_mods() {
6469 let hdr = indoc! {"
6470 #include <cstdint>
6471 struct A {
6472 uint32_t a;
6473 };
6474 inline A give_a() {
6475 A a;
6476 a.a = 5;
6477 return a;
6478 }
6479 inline uint32_t get_a(A a) {
6480 return a.a;
6481 }
6482 struct B {
6483 uint32_t a;
6484 };
6485 inline B give_b() {
6486 B a;
6487 a.a = 8;
6488 return a;
6489 }
6490 inline uint32_t get_b(B a) {
6491 return a.a;
6492 }
6493 "};
6494 let hexathorpe = Token![#](Span::call_site());
6495 let rs = quote! {
6496 use autocxx::prelude::*;
6497 include_cpp! {
6498 #hexathorpe include "input.h"
6499 safety!(unsafe_ffi)
6500 generate!("give_a")
6501 generate!("get_a")
6502 }
6503 include_cpp! {
6504 #hexathorpe include "input.h"
6505 name!(ffi2)
6506 generate!("give_b")
6507 generate!("get_b")
6508 }
6509 fn main() {
6510 let a = ffi::give_a().within_unique_ptr();
6511 assert_eq!(ffi::get_a(a), 5);
6512 let b = unsafe { ffi2::give_b().within_unique_ptr() };
6513 assert_eq!(unsafe { ffi2::get_b(b) }, 8);
6514 }
6515 };
6516 do_run_test_manual("", hdr, rs, None, None).unwrap();
6517}
6518
6519#[test]
6520fn test_manual_bridge() {
6521 let hdr = indoc! {"
6522 #include <cstdint>
6523 inline uint32_t give_int() {
6524 return 5;
6525 }
6526 inline uint32_t give_int2() {
6527 return 5;
6528 }
6529 "};
6530 let hexathorpe = Token![#](Span::call_site());
6531 let rs = quote! {
6532 autocxx::include_cpp! {
6533 #hexathorpe include "input.h"
6534 safety!(unsafe_ffi)
6535 generate!("give_int")
6536 }
6537 #[cxx::bridge]
6538 mod ffi2 {
6539 unsafe extern "C++" {
6540 include!("input.h");
6541 fn give_int2() -> u32;
6542 }
6543 }
6544 fn main() {
6545 assert_eq!(ffi::give_int(), 5);
6546 assert_eq!(ffi2::give_int2(), 5);
6547 }
6548 };
6549 do_run_test_manual("", hdr, rs, None, None).unwrap();
6550}
6551
6552#[test]
6553fn test_manual_bridge_mixed_types() {
6554 let hdr = indoc! {"
6555 #include <memory>
6556 struct A {
6557 int a;
6558 };
6559 inline int take_A(const A& a) {
6560 return a.a;
6561 }
6562 inline std::unique_ptr<A> give_A() {
6563 auto a = std::make_unique<A>();
6564 a->a = 5;
6565 return a;
6566 }
6567 "};
6568 let hexathorpe = Token![#](Span::call_site());
6569 let rs = quote! {
6570 use autocxx::prelude::*;
6571 autocxx::include_cpp! {
6572 #hexathorpe include "input.h"
6573 safety!(unsafe_ffi)
6574 generate!("take_A")
6575 generate!("A")
6576 }
6577 #[cxx::bridge]
6578 mod ffi2 {
6579 unsafe extern "C++" {
6580 include!("input.h");
6581 type A = crate::ffi::A;
6582 fn give_A() -> UniquePtr<A>;
6583 }
6584 }
6585 fn main() {
6586 let a = ffi2::give_A();
6587 assert_eq!(ffi::take_A(&a), autocxx::c_int(5));
6588 }
6589 };
6590 do_run_test_manual("", hdr, rs, None, None).unwrap();
6591}
6592
6593#[test]
6594fn test_extern_cpp_type_cxx_bridge() {
6595 let hdr = indoc! {"
6596 #include <cstdint>
6597 struct A {
6598 A() : a(0) {}
6599 int a;
6600 };
6601 inline void handle_a(const A&) {
6602 }
6603 inline A create_a() {
6604 A a;
6605 return a;
6606 }
6607 "};
6608 let hexathorpe = Token![#](Span::call_site());
6609 let rs = quote! {
6610 use autocxx::prelude::*;
6611 include_cpp! {
6612 #hexathorpe include "input.h"
6613 safety!(unsafe_ffi)
6614 generate!("handle_a")
6615 generate!("create_a")
6616 extern_cpp_opaque_type!("A", crate::ffi2::A)
6617 }
6618 #[cxx::bridge]
6619 pub mod ffi2 {
6620 unsafe extern "C++" {
6621 include!("input.h");
6622 type A;
6623 }
6624 impl UniquePtr<A> {}
6625 }
6626 fn main() {
6627 let a = ffi::create_a();
6628 ffi::handle_a(&a);
6629 }
6630 };
6631 do_run_test_manual("", hdr, rs, None, None).unwrap();
6632}
6633
6634#[test]
6635fn test_extern_cpp_type_two_include_cpp() {
6636 let hdr = indoc! {"
6637 #include <cstdint>
6638 struct A {
6639 A() : a(0) {}
6640 int a;
6641 };
6642 enum B {
6643 VARIANT,
6644 };
6645 inline void handle_a(const A&) {
6646 }
6647 inline A create_a(B) {
6648 A a;
6649 return a;
6650 }
6651 "};
6652 let hexathorpe = Token![#](Span::call_site());
6653 let rs = quote! {
6654 pub mod base {
6655 autocxx::include_cpp! {
6656 #hexathorpe include "input.h"
6657 name!(ffi2)
6658 safety!(unsafe_ffi)
6659 generate!("A")
6660 generate!("B")
6661 }
6662 pub use ffi2::*;
6663 }
6664 pub mod dependent {
6665 autocxx::include_cpp! {
6666 #hexathorpe include "input.h"
6667 safety!(unsafe_ffi)
6668 generate!("handle_a")
6669 generate!("create_a")
6670 extern_cpp_type!("A", crate::base::A)
6671 extern_cpp_type!("B", super::super::base::B)
6672 pod!("B")
6673 }
6674 pub use ffi::*;
6675 }
6676 fn main() {
6677 use autocxx::prelude::*;
6678 let a = dependent::create_a(base::B::VARIANT).within_box();
6679 dependent::handle_a(&a);
6680 }
6681 };
6682 do_run_test_manual("", hdr, rs, None, None).unwrap();
6683}
6684
6685#[test]
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07006686/// Tests extern_cpp_type with a type inside a namespace.
6687fn test_extern_cpp_type_namespace() {
6688 let hdr = indoc! {"
6689 #include <cstdint>
6690 namespace b {
6691 struct B {
6692 B() {}
6693 };
6694 } // namespace b
6695 struct A {
6696 A() {}
6697 b::B make_b() { return b::B(); }
6698 };
6699 "};
6700 let hexathorpe = Token![#](Span::call_site());
6701 let rs = quote! {
6702 pub mod b {
6703 autocxx::include_cpp! {
6704 #hexathorpe include "input.h"
6705 safety!(unsafe_ffi)
6706 name!(ffi_b)
6707 generate_pod!("b::B")
6708 }
6709 pub use ffi_b::b::B;
6710 }
6711 pub mod a {
6712 autocxx::include_cpp! {
6713 #hexathorpe include "input.h"
6714 safety!(unsafe_ffi)
6715 name!(ffi_a)
6716 generate_pod!("A")
6717 extern_cpp_type!("b::B", crate::b::B)
6718 }
6719 pub use ffi_a::A;
6720 }
6721 fn main() {
6722 use autocxx::prelude::*;
6723 let _ = crate::a::A::new().within_unique_ptr().as_mut().unwrap().make_b();
6724 }
6725 };
6726 do_run_test_manual("", hdr, rs, None, None).unwrap();
6727}
6728
6729#[test]
Brian Silverman4e662aa2022-05-11 23:10:19 -07006730#[ignore] // because we currently require UniquePtrTarget which this can't implement
6731fn test_extern_cpp_type_manual() {
6732 let hdr = indoc! {"
6733 #include <cstdint>
6734 struct A {
6735 int a;
6736 };
6737 inline void handle_a(const A& a) {
6738 }
6739 inline A create_a() {
6740 A a;
6741 return a;
6742 }
6743 "};
6744 let hexathorpe = Token![#](Span::call_site());
6745 let rs = quote! {
6746 autocxx::include_cpp! {
6747 #hexathorpe include "input.h"
6748 safety!(unsafe_ffi)
6749 generate!("handle_a")
6750 generate!("create_a")
6751 extern_cpp_type!("A", crate::ffi2::A)
6752 }
6753 pub mod ffi2 {
6754 use autocxx::cxx::{type_id, ExternType};
6755 #[repr(C)]
6756 pub struct A {
6757 a: std::os::raw::c_int
6758 }
6759 unsafe impl ExternType for A {
6760 type Kind = autocxx::cxx::kind::Opaque;
6761 type Id = type_id!("A");
6762 }
6763
6764 }
6765 fn main() {
6766 let a = ffi2::A { a: 3 };
6767 ffi::handle_a(&a);
6768 }
6769 };
6770 do_run_test_manual("", hdr, rs, None, None).unwrap();
6771}
6772
6773#[test]
6774fn test_issue486() {
6775 let hdr = indoc! {"
6776 namespace a {
6777 namespace spanner {
6778 class Key;
6779 }
6780 } // namespace a
6781 namespace spanner {
6782 class Key {
6783 public:
6784 bool b(a::spanner::Key &);
6785 };
6786 } // namespace spanner
6787 "};
6788 let rs = quote! {};
6789 run_test("", hdr, rs, &["spanner::Key"], &[]);
6790}
6791
6792#[test]
6793#[ignore]
6794fn test_issue616() {
6795 let hdr = indoc! {"
6796 namespace N {
6797 template <typename> class B{};
6798 template <typename c> class C {
6799 public:
6800 using U = B<c>;
6801 };
6802 }
6803 class A : N::C<A> {
6804 U u;
6805 };
6806 "};
6807 let rs = quote! {};
6808 run_test("", hdr, rs, &["A"], &[]);
6809}
6810
6811#[test]
6812fn test_shared_ptr() {
6813 let hdr = indoc! {"
6814 #include <memory>
6815 struct A {
6816 int a;
6817 };
6818 inline std::shared_ptr<A> make_shared_int() {
6819 return std::make_shared<A>(A { 3 });
6820 }
6821 inline int take_shared_int(std::shared_ptr<A> a) {
6822 return a->a;
6823 }
6824 inline std::weak_ptr<A> shared_to_weak(std::shared_ptr<A> a) {
6825 return std::weak_ptr<A>(a);
6826 }
6827 "};
6828 let rs = quote! {
6829 let a = ffi::make_shared_int();
6830 assert_eq!(ffi::take_shared_int(a.clone()), autocxx::c_int(3));
6831 ffi::shared_to_weak(a).upgrade();
6832 };
6833 run_test(
6834 "",
6835 hdr,
6836 rs,
6837 &["make_shared_int", "take_shared_int", "shared_to_weak"],
6838 &[],
6839 );
6840}
6841
6842#[test]
6843#[ignore] // https://github.com/google/autocxx/issues/799
6844fn test_shared_ptr_const() {
6845 let hdr = indoc! {"
6846 #include <memory>
6847 inline std::shared_ptr<const int> make_shared_int() {
6848 return std::make_shared<const int>(3);
6849 }
6850 inline int take_shared_int(std::shared_ptr<const int> a) {
6851 return *a;
6852 }
6853 "};
6854 let rs = quote! {
6855 let a = ffi::make_shared_int();
6856 assert_eq!(ffi::take_shared_int(a.clone()), autocxx::c_int(3));
6857 };
6858 run_test("", hdr, rs, &["make_shared_int", "take_shared_int"], &[]);
6859}
6860
6861#[test]
6862fn test_rust_reference() {
6863 let hdr = indoc! {"
6864 #include <cstdint>
6865
6866 struct RustType;
6867 inline uint32_t take_rust_reference(const RustType&) {
6868 return 4;
6869 }
6870 "};
6871 let rs = quote! {
6872 let foo = RustType(3);
6873 assert_eq!(ffi::take_rust_reference(&foo), 4);
6874 };
6875 run_test_ex(
6876 "",
6877 hdr,
6878 rs,
6879 quote! {
6880 generate!("take_rust_reference")
6881 extern_rust_type!(RustType)
6882 },
6883 None,
6884 None,
6885 Some(quote! {
6886 pub struct RustType(i32);
6887 }),
6888 );
6889}
6890
6891#[test]
6892fn test_rust_reference_autodiscover() {
6893 let hdr = indoc! {"
6894 #include <cstdint>
6895
6896 struct RustType;
6897 inline uint32_t take_rust_reference(const RustType&) {
6898 return 4;
6899 }
6900 "};
6901 let rs = quote! {
6902 let foo = RustType(3);
6903 let result = ffi::take_rust_reference(&foo);
6904 assert_eq!(result, 4);
6905 };
6906 run_test_ex(
6907 "",
6908 hdr,
6909 rs,
6910 quote! {},
6911 Some(Box::new(EnableAutodiscover)),
6912 None,
6913 Some(quote! {
6914 #[autocxx::extern_rust::extern_rust_type]
6915 pub struct RustType(i32);
6916 }),
6917 );
6918}
6919
6920#[test]
6921fn test_pass_thru_rust_reference() {
6922 let hdr = indoc! {"
6923 #include <cstdint>
6924
6925 struct RustType;
6926 inline const RustType& pass_rust_reference(const RustType& a) {
6927 return a;
6928 }
6929 "};
6930 let rs = quote! {
6931 let foo = RustType(3);
6932 assert_eq!(ffi::pass_rust_reference(&foo).0, 3);
6933 };
6934 run_test_ex(
6935 "",
6936 hdr,
6937 rs,
6938 quote! {
6939 generate!("pass_rust_reference")
6940 extern_rust_type!(RustType)
6941 },
6942 None,
6943 None,
6944 Some(quote! {
6945 pub struct RustType(i32);
6946 }),
6947 );
6948}
6949
6950#[test]
6951fn test_extern_rust_method() {
6952 let hdr = indoc! {"
6953 #include <cstdint>
6954 struct RustType;
6955 uint32_t examine(const RustType& foo);
6956 "};
6957 let cxx = indoc! {"
6958 uint32_t examine(const RustType& foo) {
6959 return foo.get();
6960 }"};
6961 let rs = quote! {
6962 let a = RustType(74);
6963 assert_eq!(ffi::examine(&a), 74);
6964 };
6965 run_test_ex(
6966 cxx,
6967 hdr,
6968 rs,
6969 directives_from_lists(&["examine"], &[], None),
6970 Some(Box::new(EnableAutodiscover)),
6971 None,
6972 Some(quote! {
6973 #[autocxx::extern_rust::extern_rust_type]
6974 pub struct RustType(i32);
6975 impl RustType {
6976 #[autocxx::extern_rust::extern_rust_function]
6977 pub fn get(&self) -> i32 {
6978 return self.0
6979 }
6980 }
6981 }),
6982 );
6983}
6984
6985#[test]
6986fn test_rust_reference_no_autodiscover() {
6987 let hdr = indoc! {"
6988 #include <cstdint>
6989
6990 struct RustType;
6991 inline uint32_t take_rust_reference(const RustType&) {
6992 return 4;
6993 }
6994 "};
6995 let rs = quote! {
6996 let foo = RustType(3);
6997 let result = ffi::take_rust_reference(&foo);
6998 assert_eq!(result, 4);
6999 };
7000 run_test_ex(
7001 "",
7002 hdr,
7003 rs,
7004 directives_from_lists(&["take_rust_reference"], &[], None),
7005 None,
7006 None,
7007 Some(quote! {
7008 #[autocxx::extern_rust::extern_rust_type]
7009 pub struct RustType(i32);
7010 }),
7011 );
7012}
7013
7014#[test]
7015#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
7016// TODO - replace make_clang_arg_adder with something that knows how to add an MSVC-suitable
7017// directive for the cc build.
7018fn test_cpp17() {
7019 let hdr = indoc! {"
7020 static_assert(__cplusplus >= 201703L, \"This file expects a C++17 compatible compiler.\");
7021 inline void foo() {}
7022 "};
7023 run_test_ex(
7024 "",
7025 hdr,
7026 quote! {
7027 ffi::foo();
7028 },
7029 quote! {
7030 generate!("foo")
7031 },
7032 make_cpp17_adder(),
7033 None,
7034 None,
7035 );
7036}
7037
7038#[test]
7039fn test_box() {
7040 let hdr = indoc! {"
7041 #include <cxx.h>
7042 struct Foo;
7043 inline void take_box(rust::Box<Foo>) {
7044 }
7045 "};
7046 run_test_ex(
7047 "",
7048 hdr,
7049 quote! {
7050 ffi::take_box(Box::new(Foo { a: "Hello".into() }))
7051 },
7052 quote! {
7053 generate!("take_box")
7054 extern_rust_type!(Foo)
7055 },
7056 None,
7057 None,
7058 Some(quote! {
7059 pub struct Foo {
7060 a: String,
7061 }
7062 }),
7063 );
7064}
7065
7066#[test]
7067fn test_box_via_extern_rust() {
7068 let hdr = indoc! {"
7069 #include <cxx.h>
7070 struct Foo;
7071 inline void take_box(rust::Box<Foo>) {
7072 }
7073 "};
7074 run_test_ex(
7075 "",
7076 hdr,
7077 quote! {
7078 ffi::take_box(Box::new(Foo { a: "Hello".into() }))
7079 },
7080 quote! {},
7081 Some(Box::new(EnableAutodiscover)),
7082 None,
7083 Some(quote! {
7084 #[autocxx::extern_rust::extern_rust_type]
7085 pub struct Foo {
7086 a: String,
7087 }
7088 }),
7089 );
7090}
7091
7092#[test]
7093fn test_box_via_extern_rust_in_mod() {
7094 let hdr = indoc! {"
7095 #include <cxx.h>
7096 struct Foo;
7097 inline void take_box(rust::Box<Foo>) {
7098 }
7099 "};
7100 run_test_ex(
7101 "",
7102 hdr,
7103 quote! {
7104 ffi::take_box(Box::new(bar::Foo { a: "Hello".into() }))
7105 },
7106 quote! {},
7107 Some(Box::new(EnableAutodiscover)),
7108 None,
7109 Some(quote! {
7110 mod bar {
7111 #[autocxx::extern_rust::extern_rust_type]
7112 pub struct Foo {
7113 pub a: String,
7114 }
7115 }
7116 }),
7117 );
7118}
7119
7120#[test]
7121fn test_extern_rust_fn_simple() {
7122 let cpp = indoc! {"
7123 void foo() {
7124 my_rust_fun();
7125 }
7126 "};
7127 let hdr = indoc! {"
7128 #include <cxx.h>
7129 inline void do_thing() {}
7130 "};
7131 run_test_ex(
7132 cpp,
7133 hdr,
7134 quote! {
7135 ffi::do_thing();
7136 },
7137 quote! {
7138 generate!("do_thing")
7139 },
7140 Some(Box::new(EnableAutodiscover)),
7141 None,
7142 Some(quote! {
7143 #[autocxx::extern_rust::extern_rust_function]
7144 fn my_rust_fun() {
7145 }
7146 }),
7147 );
7148}
7149
7150#[test]
7151fn test_extern_rust_fn_in_mod() {
7152 let hdr = indoc! {"
7153 #include <cxx.h>
7154 inline void do_thing() {}
7155 "};
7156 run_test_ex(
7157 "",
7158 hdr,
7159 quote! {},
7160 quote! {
7161 generate!("do_thing")
7162 },
7163 Some(Box::new(EnableAutodiscover)),
7164 None,
7165 Some(quote! {
7166 mod bar {
7167 #[autocxx::extern_rust::extern_rust_function]
7168 pub fn my_rust_fun() {
7169
7170 }
7171 }
7172 }),
7173 );
7174}
7175
7176#[test]
7177fn test_issue_956() {
7178 let hdr = indoc! {"
7179 #include <cstdint>
7180 inline void take_int(int&) {}
7181 inline void take_uin16(uint16_t&) {}
7182 inline void take_char16(char16_t &) {}
7183 "};
7184 run_test(
7185 "",
7186 hdr,
7187 quote! {},
7188 &["take_int", "take_uin16", "take_char16"],
7189 &[],
7190 );
7191}
7192
7193#[test]
7194fn test_extern_rust_fn_no_autodiscover() {
7195 let hdr = indoc! {"
7196 #include <cxx.h>
7197 "};
7198 let cpp = indoc! {"
7199 void call_it() {
7200 my_rust_fun();
7201 }
7202 "};
7203 run_test_ex(
7204 cpp,
7205 hdr,
7206 quote! {},
7207 quote! {},
7208 None,
7209 None,
7210 Some(quote! {
7211 mod bar {
7212 #[autocxx::extern_rust::extern_rust_function]
7213 pub fn my_rust_fun() {
7214
7215 }
7216 }
7217 }),
7218 );
7219}
7220
7221#[test]
7222fn test_pv_subclass_mut() {
7223 let hdr = indoc! {"
7224 #include <cstdint>
7225
7226 class Observer {
7227 public:
7228 Observer() {}
7229 virtual void foo() = 0;
7230 virtual ~Observer() {}
7231 };
7232 inline void bar() {}
7233 "};
7234 run_test_ex(
7235 "",
7236 hdr,
7237 quote! {
7238 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7239 },
7240 quote! {
7241 generate!("bar")
7242 subclass!("Observer",MyObserver)
7243 },
7244 None,
7245 None,
7246 Some(quote! {
7247 use autocxx::subclass::CppSubclass;
7248 use ffi::Observer_methods;
7249 #[autocxx::subclass::subclass]
7250 pub struct MyObserver {
7251 a: u32
7252 }
7253 impl Observer_methods for MyObserver {
7254 fn foo(&mut self) {
7255 }
7256 }
7257 }),
7258 );
7259}
7260
7261#[test]
7262fn test_pv_subclass_const() {
7263 let hdr = indoc! {"
7264 #include <cstdint>
7265
7266 class Observer {
7267 public:
7268 Observer() {}
7269 virtual void foo() const = 0;
7270 virtual ~Observer() {}
7271 };
7272 inline void bar() {}
7273 "};
7274 run_test_ex(
7275 "",
7276 hdr,
7277 quote! {
7278 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7279 },
7280 quote! {
7281 generate!("bar")
7282 subclass!("Observer",MyObserver)
7283 },
7284 None,
7285 None,
7286 Some(quote! {
7287 use autocxx::subclass::CppSubclass;
7288 use ffi::Observer_methods;
7289 #[autocxx::subclass::subclass]
7290 pub struct MyObserver {
7291 a: u32
7292 }
7293 impl Observer_methods for MyObserver {
7294 fn foo(&self) {
7295 }
7296 }
7297 }),
7298 );
7299}
7300
7301#[test]
7302fn test_pv_subclass_calls_impossible() {
7303 let hdr = indoc! {"
7304 #include <cstdint>
7305
7306 class Observer {
7307 public:
7308 Observer() {}
7309 virtual void foo() const = 0;
7310 virtual ~Observer() {}
7311 };
7312 inline void bar() {}
7313 "};
7314 run_test_expect_fail_ex(
7315 "",
7316 hdr,
7317 quote! {
7318 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7319 },
7320 quote! {
7321 generate!("bar")
7322 subclass!("Observer",MyObserver)
7323 },
7324 None,
7325 None,
7326 Some(quote! {
7327 use autocxx::subclass::CppSubclass;
7328 use ffi::Observer_methods;
7329 #[autocxx::subclass::subclass]
7330 pub struct MyObserver {
7331 a: u32
7332 }
7333 impl Observer_methods for MyObserver {
7334 fn foo(&self) {
7335 use ffi::Observer_supers;
7336 self.foo_super()
7337 }
7338 }
7339 }),
7340 );
7341}
7342
7343#[test]
7344fn test_pv_subclass_not_pub() {
7345 let hdr = indoc! {"
7346 #include <cstdint>
7347
7348 class Observer {
7349 public:
7350 Observer() {}
7351 virtual void foo() const = 0;
7352 virtual ~Observer() {}
7353 };
7354 inline void bar() {}
7355 "};
7356 run_test_expect_fail_ex(
7357 "",
7358 hdr,
7359 quote! {
7360 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7361 },
7362 quote! {
7363 generate!("bar")
7364 subclass!("Observer",MyObserver)
7365 },
7366 None,
7367 None,
7368 Some(quote! {
7369 use autocxx::subclass::CppSubclass;
7370 use ffi::Observer_methods;
7371 #[autocxx::subclass::subclass]
7372 struct MyObserver {
7373 a: u32
7374 }
7375 impl Observer_methods for MyObserver {
7376 fn foo(&self) {
7377 }
7378 }
7379 }),
7380 );
7381}
7382
7383#[test]
7384fn test_pv_subclass_ptr_param() {
7385 let hdr = indoc! {"
7386 #include <cstdint>
7387 struct A {
7388 uint8_t a;
7389 };
7390
7391 class Observer {
7392 public:
7393 Observer() {}
7394 virtual void foo(const A*) const {};
7395 virtual ~Observer() {}
7396 };
7397 "};
7398 run_test_ex(
7399 "",
7400 hdr,
7401 quote! {
7402 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7403 },
7404 quote! {
7405 generate!("A")
7406 subclass!("Observer",MyObserver)
7407 },
7408 None,
7409 None,
7410 Some(quote! {
7411 use autocxx::subclass::CppSubclass;
7412 use ffi::Observer_methods;
7413 #[autocxx::subclass::subclass]
7414 pub struct MyObserver {
7415 a: u32
7416 }
7417 impl Observer_methods for MyObserver {
7418 unsafe fn foo(&self, a: *const ffi::A) {
7419 use ffi::Observer_supers;
7420 self.foo_super(a)
7421 }
7422 }
7423 }),
7424 );
7425}
7426
7427#[test]
7428fn test_pv_subclass_return() {
7429 let hdr = indoc! {"
7430 #include <cstdint>
7431
7432 class Observer {
7433 public:
7434 Observer() {}
7435 virtual uint32_t foo() const = 0;
7436 virtual ~Observer() {}
7437 };
7438 inline void bar() {}
7439 "};
7440 run_test_ex(
7441 "",
7442 hdr,
7443 quote! {
7444 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7445 },
7446 quote! {
7447 generate!("bar")
7448 subclass!("Observer",MyObserver)
7449 },
7450 None,
7451 None,
7452 Some(quote! {
7453 use autocxx::subclass::CppSubclass;
7454 use ffi::Observer_methods;
7455 #[autocxx::subclass::subclass]
7456 pub struct MyObserver {
7457 a: u32
7458 }
7459 impl Observer_methods for MyObserver {
7460 fn foo(&self) -> u32 {
7461 4
7462 }
7463 }
7464 }),
7465 );
7466}
7467
7468#[test]
7469fn test_pv_subclass_passed_to_fn() {
7470 let hdr = indoc! {"
7471 #include <cstdint>
7472
7473 class Observer {
7474 public:
7475 Observer() {}
7476 virtual uint32_t foo() const = 0;
7477 virtual ~Observer() {}
7478 };
7479 inline void take_observer(const Observer&) {}
7480 "};
7481 run_test_ex(
7482 "",
7483 hdr,
7484 quote! {
7485 let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7486 ffi::take_observer(o.borrow().as_ref());
7487 },
7488 quote! {
7489 generate!("take_observer")
7490 subclass!("Observer",MyObserver)
7491 },
7492 None,
7493 None,
7494 Some(quote! {
7495 use autocxx::subclass::CppSubclass;
7496 use ffi::Observer_methods;
7497 #[autocxx::subclass::subclass]
7498 pub struct MyObserver {
7499 a: u32
7500 }
7501 impl Observer_methods for MyObserver {
7502 fn foo(&self) -> u32 {
7503 4
7504 }
7505 }
7506 }),
7507 );
7508}
7509
7510#[test]
7511fn test_pv_subclass_derive_defaults() {
7512 let hdr = indoc! {"
7513 #include <cstdint>
7514
7515 class Observer {
7516 public:
7517 Observer() {}
7518 virtual uint32_t foo() const = 0;
7519 virtual ~Observer() {}
7520 };
7521 inline void take_observer(const Observer&) {}
7522 "};
7523 run_test_ex(
7524 "",
7525 hdr,
7526 quote! {
7527 use autocxx::subclass::CppSubclassDefault;
7528 let o = MyObserver::default_rust_owned();
7529 ffi::take_observer(o.borrow().as_ref());
7530 },
7531 quote! {
7532 generate!("take_observer")
7533 subclass!("Observer",MyObserver)
7534 },
7535 None,
7536 None,
7537 Some(quote! {
7538 #[autocxx::subclass::subclass]
7539 #[derive(Default)]
7540 pub struct MyObserver {
7541 a: u32
7542 }
7543 impl ffi::Observer_methods for MyObserver {
7544 fn foo(&self) -> u32 {
7545 4
7546 }
7547 }
7548 }),
7549 );
7550}
7551
7552#[test]
7553fn test_non_pv_subclass_simple() {
7554 let hdr = indoc! {"
7555 #include <cstdint>
7556
7557 class Observer {
7558 public:
7559 Observer() {}
7560 virtual void foo() const {}
7561 virtual ~Observer() {}
7562 };
7563 inline void bar() {}
7564 "};
7565 run_test_ex(
7566 "",
7567 hdr,
7568 quote! {
7569 let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7570 obs.borrow().foo();
7571 },
7572 quote! {
7573 generate!("bar")
7574 subclass!("Observer",MyObserver)
7575 },
7576 None,
7577 None,
7578 Some(quote! {
7579 use autocxx::subclass::CppSubclass;
7580 use ffi::Observer_methods;
7581 #[autocxx::subclass::subclass]
7582 pub struct MyObserver {
7583 a: u32
7584 }
7585 impl Observer_methods for MyObserver {
7586 }
7587 }),
7588 );
7589}
7590
7591#[test]
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07007592/// Tests the Rust code generated for subclasses when there's a `std` module in scope representing
7593/// the C++ `std` namespace. This breaks if any of the generated Rust code fails to fully qualify
7594/// its references to the Rust `std`.
7595fn test_subclass_with_std() {
7596 let hdr = indoc! {"
7597 #include <cstdint>
7598 #include <chrono>
7599
7600 class Observer {
7601 public:
7602 Observer() {}
7603 virtual void foo() const {}
7604 virtual ~Observer() {}
7605
7606 void unused(std::chrono::nanoseconds) {}
7607 };
7608 "};
7609 run_test_ex(
7610 "",
7611 hdr,
7612 quote! {
7613 let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7614 obs.borrow().foo();
7615 },
7616 quote! {
7617 subclass!("Observer",MyObserver)
7618 },
7619 None,
7620 None,
7621 Some(quote! {
7622 use autocxx::subclass::CppSubclass;
7623 use ffi::Observer_methods;
7624 #[autocxx::subclass::subclass]
7625 pub struct MyObserver {
7626 a: u32
7627 }
7628 impl Observer_methods for MyObserver {
7629 }
7630 }),
7631 );
7632}
7633
7634#[test]
Brian Silverman4e662aa2022-05-11 23:10:19 -07007635fn test_two_subclasses() {
7636 let hdr = indoc! {"
7637 #include <cstdint>
7638
7639 class Observer {
7640 public:
7641 Observer() {}
7642 virtual void foo() const {}
7643 virtual ~Observer() {}
7644 };
7645 inline void bar() {}
7646 "};
7647 run_test_ex(
7648 "",
7649 hdr,
7650 quote! {
7651 let obs = MyObserverA::new_rust_owned(MyObserverA { a: 3, cpp_peer: Default::default() });
7652 obs.borrow().foo();
7653 let obs = MyObserverB::new_rust_owned(MyObserverB { a: 3, cpp_peer: Default::default() });
7654 obs.borrow().foo();
7655 },
7656 quote! {
7657 generate!("bar")
7658 subclass!("Observer",MyObserverA)
7659 subclass!("Observer",MyObserverB)
7660 },
7661 None,
7662 None,
7663 Some(quote! {
7664 use autocxx::subclass::CppSubclass;
7665 use ffi::Observer_methods;
7666 #[autocxx::subclass::subclass]
7667 pub struct MyObserverA {
7668 a: u32
7669 }
7670 impl Observer_methods for MyObserverA {
7671 }
7672 #[autocxx::subclass::subclass]
7673 pub struct MyObserverB {
7674 a: u32
7675 }
7676 impl Observer_methods for MyObserverB {
7677 }
7678 }),
7679 );
7680}
7681
7682#[test]
7683fn test_two_superclasses_with_same_name_method() {
7684 let hdr = indoc! {"
7685 #include <cstdint>
7686
7687 class ObserverA {
7688 public:
7689 ObserverA() {}
7690 virtual void foo() const {}
7691 virtual ~ObserverA() {}
7692 };
7693
7694 class ObserverB {
7695 public:
7696 ObserverB() {}
7697 virtual void foo() const {}
7698 virtual ~ObserverB() {}
7699 };
7700 inline void bar() {}
7701 "};
7702 run_test_ex(
7703 "",
7704 hdr,
7705 quote! {
7706 let obs = MyObserverA::new_rust_owned(MyObserverA { a: 3, cpp_peer: Default::default() });
7707 obs.borrow().foo();
7708 let obs = MyObserverB::new_rust_owned(MyObserverB { a: 3, cpp_peer: Default::default() });
7709 obs.borrow().foo();
7710 },
7711 quote! {
7712 generate!("bar")
7713 subclass!("ObserverA",MyObserverA)
7714 subclass!("ObserverB",MyObserverB)
7715 },
7716 None,
7717 None,
7718 Some(quote! {
7719 use autocxx::subclass::CppSubclass;
7720 use ffi::ObserverA_methods;
7721 use ffi::ObserverB_methods;
7722 #[autocxx::subclass::subclass]
7723 pub struct MyObserverA {
7724 a: u32
7725 }
7726 impl ObserverA_methods for MyObserverA {
7727 }
7728 #[autocxx::subclass::subclass]
7729 pub struct MyObserverB {
7730 a: u32
7731 }
7732 impl ObserverB_methods for MyObserverB {
7733 }
7734 }),
7735 );
7736}
7737
7738#[test]
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07007739fn test_subclass_no_safety() {
7740 let hdr = indoc! {"
7741 #include <cstdint>
7742
7743 class Observer {
7744 public:
7745 Observer() {}
7746 virtual void foo() = 0;
7747 virtual ~Observer() {}
7748 };
7749 "};
7750 let hexathorpe = Token![#](Span::call_site());
7751 let unexpanded_rust = quote! {
7752 use autocxx::prelude::*;
7753
7754 include_cpp!(
7755 #hexathorpe include "input.h"
7756 subclass!("Observer",MyObserver)
7757 );
7758
7759 use ffi::Observer_methods;
7760 #hexathorpe [autocxx::subclass::subclass]
7761 pub struct MyObserver;
7762 impl Observer_methods for MyObserver {
7763 unsafe fn foo(&mut self) {}
7764 }
7765
7766 use autocxx::subclass::{CppSubclass, CppPeerConstructor, CppSubclassRustPeerHolder};
7767 use cxx::UniquePtr;
7768 impl CppPeerConstructor<ffi::MyObserverCpp> for MyObserver {
7769 fn make_peer(
7770 &mut self,
7771 peer_holder: CppSubclassRustPeerHolder<Self>,
7772 ) -> UniquePtr<ffi::MyObserverCpp> {
7773 UniquePtr::emplace(unsafe { ffi::MyObserverCpp::new(peer_holder) })
7774 }
7775 }
7776
7777 fn main() {
7778 let obs = MyObserver::new_rust_owned(MyObserver { cpp_peer: Default::default() });
7779 unsafe { obs.borrow_mut().foo() };
7780 }
7781 };
7782
7783 do_run_test_manual("", hdr, unexpanded_rust, None, None).unwrap()
7784}
7785
7786#[test]
Brian Silverman4e662aa2022-05-11 23:10:19 -07007787fn test_pv_protected_constructor() {
7788 let hdr = indoc! {"
7789 #include <cstdint>
7790
7791 class Observer {
7792 protected:
7793 Observer() {}
7794 public:
7795 virtual void foo() const {}
7796 virtual ~Observer() {}
7797 };
7798 inline void bar() {}
7799 "};
7800 run_test_ex(
7801 "",
7802 hdr,
7803 quote! {
7804 let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7805 obs.borrow().foo();
7806 },
7807 quote! {
7808 generate!("bar")
7809 subclass!("Observer",MyObserver)
7810 },
7811 None,
7812 None,
7813 Some(quote! {
7814 use autocxx::subclass::CppSubclass;
7815 use ffi::Observer_methods;
7816 #[autocxx::subclass::subclass]
7817 pub struct MyObserver {
7818 a: u32
7819 }
7820 impl Observer_methods for MyObserver {
7821 }
7822 }),
7823 );
7824}
7825
7826#[test]
7827fn test_pv_protected_method() {
7828 let hdr = indoc! {"
7829 #include <cstdint>
7830
7831 class Observer {
7832 public:
7833 Observer() {}
7834 virtual void foo() const {}
7835 virtual ~Observer() {}
7836 protected:
7837 virtual void baz() const {}
7838 };
7839 inline void bar() {}
7840 "};
7841 run_test_ex(
7842 "",
7843 hdr,
7844 quote! {
7845 let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7846 obs.borrow().foo();
7847 },
7848 quote! {
7849 generate!("bar")
7850 subclass!("Observer",MyObserver)
7851 },
7852 None,
7853 None,
7854 Some(quote! {
7855 use autocxx::subclass::CppSubclass;
7856 use ffi::Observer_methods;
7857 #[autocxx::subclass::subclass]
7858 pub struct MyObserver {
7859 a: u32
7860 }
7861 impl Observer_methods for MyObserver {
7862 fn baz(&self) {
7863 }
7864
7865 fn foo(&self) {
7866 use ffi::Observer_supers;
7867 self.baz_super()
7868 }
7869 }
7870 }),
7871 );
7872}
7873
7874#[test]
7875fn test_pv_subclass_allocation_not_self_owned() {
7876 let hdr = indoc! {"
7877 #include <cstdint>
7878 extern \"C\" void mark_freed() noexcept;
7879 extern \"C\" void mark_allocated() noexcept;
7880
7881 class TestObserver {
7882 public:
7883 TestObserver() {
7884 mark_allocated();
7885 }
7886 virtual void a() const = 0;
7887 virtual ~TestObserver() {
7888 mark_freed();
7889 }
7890 };
7891 inline void TriggerTestObserverA(const TestObserver& obs) {
7892 obs.a();
7893 }
7894 "};
7895 run_test_ex(
7896 "",
7897 hdr,
7898 quote! {
7899 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7900 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7901 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7902
7903 // Test when owned by C++
7904 let obs = MyTestObserver::new_cpp_owned(
7905 MyTestObserver::new()
7906 );
7907 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7908 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7909 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7910 let obs_superclass = obs.as_ref().unwrap(); // &subclass
7911 let obs_superclass = unsafe { std::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) };
7912 ffi::TriggerTestObserverA(obs_superclass);
7913 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
7914 std::mem::drop(obs);
7915 Lazy::force(&STATUS).lock().unwrap().a_called = false;
7916 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7917 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7918 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7919
7920 // Test when owned by Rust
7921 let obs = MyTestObserver::new_rust_owned(
7922 MyTestObserver::new()
7923 );
7924 //let cpp_peer_ptr = unsafe { obs.borrow_mut().peer_mut().get_unchecked_mut() as *mut ffi::MyTestObserverCpp };
7925 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7926 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7927 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7928 ffi::TriggerTestObserverA(obs.as_ref().borrow().as_ref());
7929 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
7930 Lazy::force(&STATUS).lock().unwrap().a_called = false;
7931 std::mem::drop(obs);
7932 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7933 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7934 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7935 },
7936 quote! {
7937 generate!("TriggerTestObserverA")
7938 subclass!("TestObserver",MyTestObserver)
7939 },
7940 None,
7941 None,
7942 Some(quote! {
7943 use once_cell::sync::Lazy;
7944 use std::sync::Mutex;
7945
7946 use autocxx::subclass::CppSubclass;
7947 use ffi::TestObserver_methods;
7948 #[autocxx::subclass::subclass]
7949 pub struct MyTestObserver {
7950 data: ExternalEngine,
7951 }
7952 impl TestObserver_methods for MyTestObserver {
7953 fn a(&self) {
7954 self.data.do_something();
7955 }
7956 }
7957 impl MyTestObserver {
7958 fn new() -> Self {
7959 Self {
7960 cpp_peer: Default::default(),
7961 data: ExternalEngine::default(),
7962 }
7963 }
7964 }
7965
7966 #[no_mangle]
7967 pub fn mark_allocated() {
7968 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = true;
7969 }
7970
7971 #[no_mangle]
7972 pub fn mark_freed() {
7973 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = false;
7974 }
7975
7976 #[derive(Default)]
7977 struct Status {
7978 cpp_allocated: bool,
7979 rust_allocated: bool,
7980 a_called: bool,
7981 }
7982
7983 static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
7984
7985 pub struct ExternalEngine;
7986
7987 impl ExternalEngine {
7988 fn do_something(&self) {
7989 Lazy::force(&STATUS).lock().unwrap().a_called = true;
7990 }
7991 }
7992
7993 impl Default for ExternalEngine {
7994 fn default() -> Self {
7995 Lazy::force(&STATUS).lock().unwrap().rust_allocated = true;
7996 ExternalEngine
7997 }
7998 }
7999
8000 impl Drop for ExternalEngine {
8001 fn drop(&mut self) {
8002 Lazy::force(&STATUS).lock().unwrap().rust_allocated = false;
8003 }
8004 }
8005 }),
8006 );
8007}
8008
8009#[test]
8010fn test_pv_subclass_allocation_self_owned() {
8011 let hdr = indoc! {"
8012 #include <cstdint>
8013 extern \"C\" void mark_freed() noexcept;
8014 extern \"C\" void mark_allocated() noexcept;
8015
8016 class TestObserver {
8017 public:
8018 TestObserver() {
8019 mark_allocated();
8020 }
8021 virtual void a() const = 0;
8022 virtual ~TestObserver() {
8023 mark_freed();
8024 }
8025 };
8026 inline void TriggerTestObserverA(const TestObserver& obs) {
8027 const_cast<TestObserver&>(obs).a();
8028 }
8029 "};
8030 run_test_ex(
8031 "",
8032 hdr,
8033 quote! {
8034 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8035 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8036 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
8037
8038 // Test when owned by C++
8039 let obs = MyTestObserver::new_cpp_owned(
8040 MyTestObserver::new(false)
8041 );
8042 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8043 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8044 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
8045 let obs_superclass = obs.as_ref().unwrap(); // &subclass
8046 let obs_superclass = unsafe { std::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) };
8047
8048 ffi::TriggerTestObserverA(obs_superclass);
8049 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
8050 std::mem::drop(obs);
8051 Lazy::force(&STATUS).lock().unwrap().a_called = false;
8052 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8053 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8054 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
8055
8056 // Test when owned by Rust
8057 let obs = MyTestObserver::new_rust_owned(
8058 MyTestObserver::new(false)
8059 );
8060 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8061 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8062 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
8063 ffi::TriggerTestObserverA(obs.as_ref().borrow().as_ref());
8064
8065 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
8066 Lazy::force(&STATUS).lock().unwrap().a_called = false;
8067 std::mem::drop(obs);
8068 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8069 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8070 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
8071
8072 // Test when self-owned
8073 let obs = MyTestObserver::new_self_owned(
8074 MyTestObserver::new(true)
8075 );
8076 let obs_superclass_ptr: *const ffi::TestObserver = obs.as_ref().borrow().as_ref();
8077 // Retain just a pointer on the Rust side, so there is no Rust-side
8078 // ownership.
8079 std::mem::drop(obs);
8080 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8081 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8082 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
8083 ffi::TriggerTestObserverA(unsafe { obs_superclass_ptr.as_ref().unwrap() });
8084
8085 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
8086 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8087 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8088 },
8089 quote! {
8090 generate!("TriggerTestObserverA")
8091 subclass!("TestObserver",MyTestObserver)
8092 },
8093 None,
8094 None,
8095 Some(quote! {
8096 use once_cell::sync::Lazy;
8097 use std::sync::Mutex;
8098
8099 use autocxx::subclass::CppSubclass;
8100 use autocxx::subclass::CppSubclassSelfOwned;
8101 use ffi::TestObserver_methods;
8102 #[autocxx::subclass::subclass(self_owned)]
8103 pub struct MyTestObserver {
8104 data: ExternalEngine,
8105 self_owning: bool,
8106 }
8107 impl TestObserver_methods for MyTestObserver {
8108 fn a(&self) {
8109 self.data.do_something();
8110 if self.self_owning {
8111 self.delete_self();
8112 }
8113 }
8114 }
8115 impl MyTestObserver {
8116 fn new(self_owning: bool) -> Self {
8117 Self {
8118 cpp_peer: Default::default(),
8119 data: ExternalEngine::default(),
8120 self_owning,
8121 }
8122 }
8123 }
8124
8125 #[no_mangle]
8126 pub fn mark_allocated() {
8127 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = true;
8128 }
8129
8130 #[no_mangle]
8131 pub fn mark_freed() {
8132 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = false;
8133 }
8134
8135 #[derive(Default)]
8136 struct Status {
8137 cpp_allocated: bool,
8138 rust_allocated: bool,
8139 a_called: bool,
8140 }
8141
8142 static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
8143
8144 pub struct ExternalEngine;
8145
8146 impl ExternalEngine {
8147 fn do_something(&self) {
8148 Lazy::force(&STATUS).lock().unwrap().a_called = true;
8149 }
8150 }
8151
8152 impl Default for ExternalEngine {
8153 fn default() -> Self {
8154 Lazy::force(&STATUS).lock().unwrap().rust_allocated = true;
8155 ExternalEngine
8156 }
8157 }
8158
8159 impl Drop for ExternalEngine {
8160 fn drop(&mut self) {
8161 Lazy::force(&STATUS).lock().unwrap().rust_allocated = false;
8162 }
8163 }
8164 }),
8165 );
8166}
8167
8168#[test]
8169fn test_pv_subclass_calls() {
8170 let hdr = indoc! {"
8171 #include <cstdint>
8172 extern \"C\" void mark_c_called() noexcept;
8173 extern \"C\" void mark_d_called() noexcept;
8174 extern \"C\" void mark_e_called() noexcept;
8175 extern \"C\" void mark_f_called() noexcept;
8176 extern \"C\" void mark_g_called() noexcept;
8177 extern \"C\" void mark_h_called() noexcept;
8178
8179 class TestObserver {
8180 public:
8181 TestObserver() {}
8182 virtual uint32_t a(uint32_t) const = 0;
8183 virtual uint32_t b(uint32_t) = 0;
8184 virtual uint32_t c(uint32_t) const { mark_c_called(); return 0; };
8185 virtual uint32_t d(uint32_t) { mark_d_called(); return 0; };
8186 virtual uint32_t e(uint32_t) const { mark_e_called(); return 0; };
8187 virtual uint32_t f(uint32_t) { mark_f_called(); return 0; };
8188 virtual uint32_t g(uint32_t) const { mark_g_called(); return 0; };
8189 virtual uint32_t h(uint32_t) { mark_h_called(); return 0; };
8190 virtual ~TestObserver() {}
8191 };
8192
8193 extern TestObserver* obs;
8194
8195 inline void register_observer(TestObserver& a) {
8196 obs = &a;
8197 }
8198 inline uint32_t call_a(uint32_t param) {
8199 return obs->a(param);
8200 }
8201 inline uint32_t call_b(uint32_t param) {
8202 return obs->b(param);
8203 }
8204 inline uint32_t call_c(uint32_t param) {
8205 return obs->c(param);
8206 }
8207 inline uint32_t call_d(uint32_t param) {
8208 return obs->d(param);
8209 }
8210 inline uint32_t call_e(uint32_t param) {
8211 return obs->e(param);
8212 }
8213 inline uint32_t call_f(uint32_t param) {
8214 return obs->f(param);
8215 }
8216 inline uint32_t call_g(uint32_t param) {
8217 return obs->g(param);
8218 }
8219 inline uint32_t call_h(uint32_t param) {
8220 return obs->h(param);
8221 }
8222 "};
8223 run_test_ex(
8224 "TestObserver* obs;",
8225 hdr,
8226 quote! {
8227 let obs = MyTestObserver::new_rust_owned(
8228 MyTestObserver::default()
8229 );
8230 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8231 assert_eq!(ffi::call_a(1), 2);
8232 assert!(Lazy::force(&STATUS).lock().unwrap().sub_a_called);
8233 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8234
8235 assert_eq!(ffi::call_b(1), 3);
8236 assert!(Lazy::force(&STATUS).lock().unwrap().sub_b_called);
8237 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8238
8239 assert_eq!(ffi::call_c(1), 4);
8240 assert!(Lazy::force(&STATUS).lock().unwrap().sub_c_called);
8241 assert!(!Lazy::force(&STATUS).lock().unwrap().super_c_called);
8242 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8243
8244 assert_eq!(ffi::call_d(1), 5);
8245 assert!(Lazy::force(&STATUS).lock().unwrap().sub_d_called);
8246 assert!(!Lazy::force(&STATUS).lock().unwrap().super_d_called);
8247 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8248
8249 assert_eq!(ffi::call_e(1), 0);
8250 assert!(Lazy::force(&STATUS).lock().unwrap().sub_e_called);
8251 assert!(Lazy::force(&STATUS).lock().unwrap().super_e_called);
8252 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8253
8254 assert_eq!(ffi::call_f(1), 0);
8255 assert!(Lazy::force(&STATUS).lock().unwrap().sub_f_called);
8256 assert!(Lazy::force(&STATUS).lock().unwrap().super_f_called);
8257 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8258
8259 assert_eq!(ffi::call_g(1), 0);
8260 assert!(Lazy::force(&STATUS).lock().unwrap().super_g_called);
8261 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8262
8263 assert_eq!(ffi::call_h(1), 0);
8264 assert!(Lazy::force(&STATUS).lock().unwrap().super_h_called);
8265 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8266 },
8267 quote! {
8268 generate!("register_observer")
8269 generate!("call_a")
8270 generate!("call_b")
8271 generate!("call_c")
8272 generate!("call_d")
8273 generate!("call_e")
8274 generate!("call_f")
8275 generate!("call_g")
8276 generate!("call_h")
8277 subclass!("TestObserver",MyTestObserver)
8278 },
8279 None,
8280 None,
8281 Some(quote! {
8282 use once_cell::sync::Lazy;
8283 use std::sync::Mutex;
8284
8285 use autocxx::subclass::CppSubclass;
8286 use ffi::TestObserver_methods;
8287 #[autocxx::subclass::subclass]
8288 #[derive(Default)]
8289 pub struct MyTestObserver {
8290 }
8291 impl TestObserver_methods for MyTestObserver {
8292
8293 // a and b are pure virtual
8294 fn a(&self, param: u32) -> u32 {
8295 Lazy::force(&STATUS).lock().unwrap().sub_a_called = true;
8296 param + 1
8297 }
8298 fn b(&mut self, param: u32) -> u32 {
8299 Lazy::force(&STATUS).lock().unwrap().sub_b_called = true;
8300 param + 2
8301 }
8302
8303 // c and d we override the superclass
8304 fn c(&self, param: u32) -> u32 {
8305 Lazy::force(&STATUS).lock().unwrap().sub_c_called = true;
8306 param + 3
8307 }
8308 fn d(&mut self, param: u32) -> u32 {
8309 Lazy::force(&STATUS).lock().unwrap().sub_d_called = true;
8310 param + 4
8311 }
8312
8313 // e and f we call through to the superclass
8314 fn e(&self, param: u32) -> u32 {
8315 Lazy::force(&STATUS).lock().unwrap().sub_e_called = true;
8316 self.peer().e_super(param)
8317 }
8318 fn f(&mut self, param: u32) -> u32 {
8319 Lazy::force(&STATUS).lock().unwrap().sub_f_called = true;
8320 self.peer_mut().f_super(param)
8321 }
8322
8323 // g and h we do not do anything, so calls should only call
8324 // the superclass
8325 }
8326
8327 #[no_mangle]
8328 pub fn mark_c_called() {
8329 Lazy::force(&STATUS).lock().unwrap().super_c_called = true;
8330 }
8331 #[no_mangle]
8332 pub fn mark_d_called() {
8333 Lazy::force(&STATUS).lock().unwrap().super_d_called = true;
8334 }
8335 #[no_mangle]
8336 pub fn mark_e_called() {
8337 Lazy::force(&STATUS).lock().unwrap().super_e_called = true;
8338 }
8339 #[no_mangle]
8340 pub fn mark_f_called() {
8341 Lazy::force(&STATUS).lock().unwrap().super_f_called = true;
8342 }
8343 #[no_mangle]
8344 pub fn mark_g_called() {
8345 Lazy::force(&STATUS).lock().unwrap().super_g_called = true;
8346 }
8347 #[no_mangle]
8348 pub fn mark_h_called() {
8349 Lazy::force(&STATUS).lock().unwrap().super_h_called = true;
8350 }
8351
8352 #[derive(Default)]
8353 struct Status {
8354 super_c_called: bool,
8355 super_d_called: bool,
8356 super_e_called: bool,
8357 super_f_called: bool,
8358 super_g_called: bool,
8359 super_h_called: bool,
8360 sub_a_called: bool,
8361 sub_b_called: bool,
8362 sub_c_called: bool,
8363 sub_d_called: bool,
8364 sub_e_called: bool,
8365 sub_f_called: bool,
8366 }
8367
8368 static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
8369 }),
8370 );
8371}
8372
8373#[test]
Brian Silvermanf3ec38b2022-07-06 20:43:36 -07008374fn test_pv_subclass_as_superclass() {
8375 let hdr = indoc! {"
8376 #include <cstdint>
8377 #include <memory>
8378
8379 class TestObserver {
8380 public:
8381 TestObserver() {}
8382 virtual void a() const = 0;
8383 virtual ~TestObserver() {}
8384 };
8385
8386 inline void call_observer(std::unique_ptr<TestObserver> obs) { obs->a(); }
8387 "};
8388 run_test_ex(
8389 "",
8390 hdr,
8391 quote! {
8392 use autocxx::subclass::CppSubclass;
8393 let obs = MyTestObserver::new_cpp_owned(
8394 MyTestObserver::default()
8395 );
8396 let obs = MyTestObserver::as_TestObserver_unique_ptr(obs);
8397 assert!(!Lazy::force(&STATUS).lock().unwrap().dropped);
8398 ffi::call_observer(obs);
8399 assert!(Lazy::force(&STATUS).lock().unwrap().sub_a_called);
8400 assert!(Lazy::force(&STATUS).lock().unwrap().dropped);
8401 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8402 },
8403 quote! {
8404 generate!("call_observer")
8405 subclass!("TestObserver",MyTestObserver)
8406 },
8407 None,
8408 None,
8409 Some(quote! {
8410 use once_cell::sync::Lazy;
8411 use std::sync::Mutex;
8412
8413 use ffi::TestObserver_methods;
8414 #[autocxx::subclass::subclass]
8415 #[derive(Default)]
8416 pub struct MyTestObserver {
8417 }
8418 impl TestObserver_methods for MyTestObserver {
8419 fn a(&self) {
8420 assert!(!Lazy::force(&STATUS).lock().unwrap().dropped);
8421 Lazy::force(&STATUS).lock().unwrap().sub_a_called = true;
8422 }
8423 }
8424 impl Drop for MyTestObserver {
8425 fn drop(&mut self) {
8426 Lazy::force(&STATUS).lock().unwrap().dropped = true;
8427 }
8428 }
8429
8430 #[derive(Default)]
8431 struct Status {
8432 sub_a_called: bool,
8433 dropped: bool,
8434 }
8435
8436 static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
8437 }),
8438 );
8439}
8440
8441#[test]
Brian Silverman4e662aa2022-05-11 23:10:19 -07008442fn test_cycle_nonpod_simple() {
8443 let hdr = indoc! {"
8444 #include <string>
8445 struct NonPod {
8446 std::string a;
8447 };
8448 inline NonPod make_non_pod(std::string a) {
8449 NonPod p;
8450 p.a = a;
8451 return p;
8452 }
8453 inline NonPod call_n(NonPod param) {
8454 return param;
8455 }
8456 "};
8457 let rs = quote! {
8458 let nonpod = ffi::make_non_pod("hello").within_unique_ptr();
8459 ffi::call_n(nonpod).within_unique_ptr();
8460 };
8461 run_test("", hdr, rs, &["NonPod", "make_non_pod", "call_n"], &[])
8462}
8463
8464#[test]
8465fn test_pv_subclass_types() {
8466 let hdr = indoc! {"
8467 #include <cstdint>
8468 #include <string>
8469 #include <vector>
8470
8471 struct Fwd;
8472 struct Pod {
8473 uint32_t a;
8474 };
8475 struct NonPod {
8476 std::string a;
8477 };
8478 class TestObserver {
8479 public:
8480 TestObserver() {}
8481 virtual std::string s(std::string p) const { return p; }
8482 virtual Pod p(Pod p) const { return p; }
8483 virtual NonPod n(NonPod p) const { return p; }
8484 virtual void f(const Fwd&) const { }
8485 virtual std::vector<NonPod> v(std::vector<NonPod> v) const { return v; }
8486 virtual const std::vector<NonPod>& vr(const std::vector<NonPod>& vr) const { return vr; }
8487 virtual const std::vector<Fwd>& vfr(const std::vector<Fwd>& vfr) const { return vfr; }
8488 virtual ~TestObserver() {}
8489 };
8490
8491 extern TestObserver* obs;
8492
8493 inline void register_observer(TestObserver& a) {
8494 obs = &a;
8495 }
8496 inline std::string call_s(std::string param) {
8497 return obs->s(param);
8498 }
8499 inline Pod call_p(Pod param) {
8500 return obs->p(param);
8501 }
8502 inline NonPod call_n(NonPod param) {
8503 return obs->n(param);
8504 }
8505 inline NonPod make_non_pod(std::string a) {
8506 NonPod p;
8507 p.a = a;
8508 return p;
8509 }
8510 "};
8511 run_test_ex(
8512 "TestObserver* obs;",
8513 hdr,
8514 quote! {
8515 let obs = MyTestObserver::new_rust_owned(
8516 MyTestObserver::default()
8517 );
8518 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8519 ffi::call_p(ffi::Pod { a: 3 });
8520 ffi::call_s("hello");
8521 ffi::call_n(ffi::make_non_pod("goodbye").within_unique_ptr());
8522 },
8523 quote! {
8524 generate!("register_observer")
8525 generate!("call_s")
8526 generate!("call_n")
8527 generate!("call_p")
8528 generate!("NonPod")
8529 generate!("make_non_pod")
8530 generate_pod!("Pod")
8531 subclass!("TestObserver",MyTestObserver)
8532 },
8533 None,
8534 None,
8535 Some(quote! {
8536 use autocxx::subclass::CppSubclass;
8537 use ffi::TestObserver_methods;
8538 #[autocxx::subclass::subclass]
8539 #[derive(Default)]
8540 pub struct MyTestObserver {
8541 }
8542 impl TestObserver_methods for MyTestObserver {
8543 fn s(&self, p: cxx::UniquePtr<cxx::CxxString>) -> cxx::UniquePtr<cxx::CxxString> {
8544 self.peer().s_super(p)
8545 }
8546
8547 fn p(&self, p: ffi::Pod) -> ffi::Pod {
8548 self.peer().p_super(p)
8549 }
8550
8551 fn n(&self, p: cxx::UniquePtr<ffi::NonPod>) -> cxx::UniquePtr<ffi::NonPod> {
8552 self.peer().n_super(p)
8553 }
8554 }
8555 }),
8556 );
8557}
8558
8559#[test]
8560fn test_pv_subclass_constructors() {
8561 // Also tests a Rust-side subclass type which is an empty struct
8562 let hdr = indoc! {"
8563 #include <cstdint>
8564 #include <string>
8565
8566 class TestObserver {
8567 public:
8568 TestObserver() {}
8569 TestObserver(uint8_t) {}
8570 TestObserver(std::string) {}
8571 virtual void call() const { }
8572 virtual ~TestObserver() {}
8573 };
8574
8575 extern TestObserver* obs;
8576
8577 inline void register_observer(TestObserver& a) {
8578 obs = &a;
8579 }
8580 inline void do_a_thing() {
8581 return obs->call();
8582 }
8583 "};
8584 run_test_ex(
8585 "TestObserver* obs;",
8586 hdr,
8587 quote! {
8588 let obs = MyTestObserver::new_rust_owned(
8589 MyTestObserver::default()
8590 );
8591 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8592 ffi::do_a_thing();
8593 },
8594 quote! {
8595 generate!("register_observer")
8596 generate!("do_a_thing")
8597 subclass!("TestObserver",MyTestObserver)
8598 },
8599 None,
8600 None,
8601 Some(quote! {
8602 use autocxx::subclass::prelude::*;
8603 #[subclass]
8604 #[derive(Default)]
8605 pub struct MyTestObserver;
8606 impl ffi::TestObserver_methods for MyTestObserver {
8607 fn call(&self) {
8608 self.peer().call_super()
8609 }
8610 }
8611 impl CppPeerConstructor<ffi::MyTestObserverCpp> for MyTestObserver {
8612 fn make_peer(&mut self, peer_holder: CppSubclassRustPeerHolder<Self>) -> cxx::UniquePtr<ffi::MyTestObserverCpp> {
8613 ffi::MyTestObserverCpp::new1(peer_holder, 3u8).within_unique_ptr()
8614 }
8615 }
8616 }),
8617 );
8618}
8619
8620#[test]
8621fn test_pv_subclass_fancy_constructor() {
8622 let hdr = indoc! {"
8623 #include <cstdint>
8624
8625 class Observer {
8626 public:
8627 Observer(uint8_t) {}
8628 virtual uint32_t foo() const = 0;
8629 virtual ~Observer() {}
8630 };
8631 inline void take_observer(const Observer&) {}
8632 "};
8633 run_test_expect_fail_ex(
8634 "",
8635 hdr,
8636 quote! {
8637 let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() }, ffi::MyObserverCpp::make_unique);
8638 ffi::take_observer(o.borrow().as_ref());
8639 },
8640 quote! {
8641 generate!("take_observer")
8642 subclass!("Observer",MyObserver)
8643 },
8644 None,
8645 None,
8646 Some(quote! {
8647 use autocxx::subclass::CppSubclass;
8648 use ffi::Observer_methods;
8649 #[autocxx::subclass::subclass]
8650 pub struct MyObserver {
8651 a: u32
8652 }
8653 impl Observer_methods for MyObserver {
8654 fn foo(&self) -> u32 {
8655 4
8656 }
8657 }
8658 }),
8659 );
8660}
8661
8662#[test]
8663fn test_non_pv_subclass_overloads() {
8664 let hdr = indoc! {"
8665 #include <cstdint>
8666 #include <string>
8667
8668 class TestObserver {
8669 public:
8670 TestObserver() {}
8671 virtual void call(uint8_t) const {}
8672 virtual void call(std::string) const {}
8673 virtual ~TestObserver() {}
8674 };
8675
8676 extern TestObserver* obs;
8677
8678 inline void register_observer(TestObserver& a) {
8679 obs = &a;
8680 }
8681 inline void do_a_thing() {
8682 return obs->call(8);
8683 }
8684 "};
8685 run_test_ex(
8686 "TestObserver* obs;",
8687 hdr,
8688 quote! {
8689 let obs = MyTestObserver::new_rust_owned(
8690 MyTestObserver::default()
8691 );
8692 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8693 ffi::do_a_thing();
8694 },
8695 quote! {
8696 generate!("register_observer")
8697 generate!("do_a_thing")
8698 subclass!("TestObserver",MyTestObserver)
8699 },
8700 None,
8701 None,
8702 Some(quote! {
8703 use autocxx::subclass::prelude::*;
8704 #[subclass]
8705 #[derive(Default)]
8706 pub struct MyTestObserver;
8707 impl ffi::TestObserver_methods for MyTestObserver {
8708 fn call(&self, a: u8) {
8709 self.peer().call_super(a)
8710 }
8711 fn call1(&self, a: cxx::UniquePtr<cxx::CxxString>) {
8712 self.peer().call1_super(a)
8713 }
8714 }
8715 }),
8716 );
8717}
8718
8719#[test]
8720fn test_pv_subclass_overrides() {
8721 let hdr = indoc! {"
8722 #include <cstdint>
8723 #include <string>
8724
8725 class TestObserver {
8726 public:
8727 TestObserver() {}
8728 virtual void call(uint8_t) const = 0;
8729 virtual void call(std::string) const = 0;
8730 virtual ~TestObserver() {}
8731 };
8732
8733 extern TestObserver* obs;
8734
8735 inline void register_observer(TestObserver& a) {
8736 obs = &a;
8737 }
8738 inline void do_a_thing() {
8739 return obs->call(8);
8740 }
8741 "};
8742 run_test_ex(
8743 "TestObserver* obs;",
8744 hdr,
8745 quote! {
8746 let obs = MyTestObserver::new_rust_owned(
8747 MyTestObserver::default()
8748 );
8749 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8750 ffi::do_a_thing();
8751 },
8752 quote! {
8753 generate!("register_observer")
8754 generate!("do_a_thing")
8755 subclass!("TestObserver",MyTestObserver)
8756 },
8757 None,
8758 None,
8759 Some(quote! {
8760 use autocxx::subclass::prelude::*;
8761 #[subclass]
8762 #[derive(Default)]
8763 pub struct MyTestObserver;
8764 impl ffi::TestObserver_methods for MyTestObserver {
8765 fn call(&self, _a: u8) {
8766 }
8767 fn call1(&self, _a: cxx::UniquePtr<cxx::CxxString>) {
8768 }
8769 }
8770 }),
8771 );
8772}
8773
8774#[test]
8775fn test_pv_subclass_namespaced_superclass() {
8776 let hdr = indoc! {"
8777 #include <cstdint>
8778
8779 namespace a {
8780 class Observer {
8781 public:
8782 Observer() {}
8783 virtual uint32_t foo() const = 0;
8784 virtual ~Observer() {}
8785 };
8786 }
8787 inline void take_observer(const a::Observer&) {}
8788 "};
8789 run_test_ex(
8790 "",
8791 hdr,
8792 quote! {
8793 let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
8794 ffi::take_observer(o.borrow().as_ref());
8795 },
8796 quote! {
8797 generate!("take_observer")
8798 subclass!("a::Observer",MyObserver)
8799 },
8800 None,
8801 None,
8802 Some(quote! {
8803 use autocxx::subclass::CppSubclass;
8804 #[autocxx::subclass::subclass]
8805 pub struct MyObserver {
8806 a: u32
8807 }
8808 impl ffi::a::Observer_methods for MyObserver {
8809 fn foo(&self) -> u32 {
8810 4
8811 }
8812 }
8813 }),
8814 );
8815}
8816
8817#[test]
8818fn test_no_constructor_make_unique() {
8819 let hdr = indoc! {"
8820 #include <stdint.h>
8821 struct A {
8822 uint32_t a;
8823 };
8824 "};
8825 let rs = quote! {
8826 ffi::A::new().within_unique_ptr();
8827 };
8828 run_test("", hdr, rs, &["A"], &[]);
8829}
8830
8831#[test]
8832fn test_constructor_moveit() {
8833 let hdr = indoc! {"
8834 #include <stdint.h>
8835 #include <string>
8836 struct A {
8837 A() {}
8838 void set(uint32_t val) { a = val; }
8839 uint32_t get() const { return a; }
8840 uint32_t a;
8841 std::string so_we_are_non_trivial;
8842 };
8843 "};
8844 let rs = quote! {
8845 moveit! {
8846 let mut stack_obj = ffi::A::new();
8847 }
8848 stack_obj.as_mut().set(42);
8849 assert_eq!(stack_obj.get(), 42);
8850 };
8851 run_test("", hdr, rs, &["A"], &[]);
8852}
8853
8854#[test]
8855fn test_move_out_of_uniqueptr() {
8856 let hdr = indoc! {"
8857 #include <stdint.h>
8858 #include <string>
8859 struct A {
8860 A() {}
8861 std::string so_we_are_non_trivial;
8862 };
8863 inline A get_a() {
8864 A a;
8865 return a;
8866 }
8867 "};
8868 let rs = quote! {
8869 let a = ffi::get_a().within_unique_ptr();
8870 moveit! {
8871 let _stack_obj = autocxx::moveit::new::mov(a);
8872 }
8873 };
8874 run_test("", hdr, rs, &["A", "get_a"], &[]);
8875}
8876
8877#[test]
8878fn test_implicit_constructor_with_typedef_field() {
8879 let hdr = indoc! {"
8880 #include <stdint.h>
8881 #include <string>
8882 struct B {
8883 uint32_t b;
8884 };
8885 typedef struct B C;
8886 struct A {
8887 B field;
8888 uint32_t a;
8889 std::string so_we_are_non_trivial;
8890 };
8891 "};
8892 let rs = quote! {
8893 moveit! {
8894 let mut stack_obj = ffi::A::new();
8895 }
8896 };
8897 run_test("", hdr, rs, &["A"], &[]);
8898}
8899
8900#[test]
8901fn test_implicit_constructor_with_array_field() {
8902 let hdr = indoc! {"
8903 #include <stdint.h>
8904 #include <string>
8905 struct A {
8906 uint32_t a[3];
8907 std::string so_we_are_non_trivial;
8908 };
8909 "};
8910 let rs = quote! {
8911 moveit! {
8912 let mut _stack_obj = ffi::A::new();
8913 }
8914 };
8915 run_test("", hdr, rs, &["A"], &[]);
8916}
8917
8918#[test]
8919fn test_implicit_constructor_moveit() {
8920 let hdr = indoc! {"
8921 #include <stdint.h>
8922 #include <string>
8923 struct A {
8924 void set(uint32_t val) { a = val; }
8925 uint32_t get() const { return a; }
8926 uint32_t a;
8927 std::string so_we_are_non_trivial;
8928 };
8929 "};
8930 let rs = quote! {
8931 moveit! {
8932 let mut stack_obj = ffi::A::new();
8933 }
8934 stack_obj.as_mut().set(42);
8935 assert_eq!(stack_obj.get(), 42);
8936 };
8937 run_test("", hdr, rs, &["A"], &[]);
8938}
8939
8940#[test]
8941fn test_pass_by_value_moveit() {
8942 let hdr = indoc! {"
8943 #include <stdint.h>
8944 #include <string>
8945 struct A {
8946 void set(uint32_t val) { a = val; }
8947 uint32_t a;
8948 std::string so_we_are_non_trivial;
8949 };
8950 inline void take_a(A) {}
8951 struct B {
8952 B() {}
8953 B(const B&) {}
8954 B(B&&) {}
8955 std::string so_we_are_non_trivial;
8956 };
8957 inline void take_b(B) {}
8958 "};
8959 let rs = quote! {
8960 moveit! {
8961 let mut stack_obj = ffi::A::new();
8962 }
8963 stack_obj.as_mut().set(42);
8964 ffi::take_a(&*stack_obj);
8965 ffi::take_a(as_copy(stack_obj.as_ref()));
8966 ffi::take_a(as_copy(stack_obj.as_ref()));
8967 // A has no move constructor so we can't consume it.
8968
8969 let heap_obj = ffi::A::new().within_unique_ptr();
8970 ffi::take_a(heap_obj.as_ref().unwrap());
8971 ffi::take_a(&heap_obj);
8972 ffi::take_a(autocxx::as_copy(heap_obj.as_ref().unwrap()));
8973 ffi::take_a(heap_obj); // consume
8974
8975 let heap_obj2 = ffi::A::new().within_box();
8976 ffi::take_a(heap_obj2.as_ref().get_ref());
8977 ffi::take_a(&heap_obj2);
8978 ffi::take_a(autocxx::as_copy(heap_obj2.as_ref().get_ref()));
8979 ffi::take_a(heap_obj2); // consume
8980
8981 moveit! {
8982 let mut stack_obj = ffi::B::new();
8983 }
8984 ffi::take_b(&*stack_obj);
8985 ffi::take_b(as_copy(stack_obj.as_ref()));
8986 ffi::take_b(as_copy(stack_obj.as_ref()));
8987 ffi::take_b(as_mov(stack_obj)); // due to move constructor
8988
8989 // Test direct-from-New-to-param.
8990 ffi::take_b(as_new(ffi::B::new()));
8991 };
8992 run_test("", hdr, rs, &["A", "take_a", "B", "take_b"], &[]);
8993}
8994
8995#[test]
8996fn test_nonconst_reference_parameter() {
8997 let hdr = indoc! {"
8998 #include <stdint.h>
8999 #include <string>
9000
9001 // Force generating a wrapper for the second `take_a`.
9002 struct NOP { void take_a() {}; };
9003
9004 struct A {
9005 std::string so_we_are_non_trivial;
9006 };
9007 inline void take_a(A&) {}
9008 "};
9009 let rs = quote! {
9010 let mut heap_obj = ffi::A::new().within_unique_ptr();
9011 ffi::take_a(heap_obj.pin_mut());
9012 };
9013 run_test("", hdr, rs, &["NOP", "A", "take_a"], &[]);
9014}
9015
9016#[test]
9017fn test_nonconst_reference_method_parameter() {
9018 let hdr = indoc! {"
9019 #include <stdint.h>
9020 #include <string>
9021
9022 // Force generating a wrapper for the second `take_a`.
9023 struct NOP { void take_a() {}; };
9024
9025 struct A {
9026 std::string so_we_are_non_trivial;
9027 };
9028 struct B {
9029 inline void take_a(A&) const {}
9030 };
9031 "};
9032 let rs = quote! {
9033 let mut a = ffi::A::new().within_unique_ptr();
9034 let b = ffi::B::new().within_unique_ptr();
9035 b.take_a(a.pin_mut());
9036 };
9037 run_test("", hdr, rs, &["NOP", "A", "B"], &[]);
9038}
9039
9040fn destruction_test(ident: proc_macro2::Ident, extra_bit: Option<TokenStream>) {
9041 let hdr = indoc! {"
9042 #include <stdint.h>
9043 #include <string>
9044 extern bool gConstructed;
9045 struct A {
9046 A() { gConstructed = true; }
9047 virtual ~A() { gConstructed = false; }
9048 void set(uint32_t val) { a = val; }
9049 uint32_t get() const { return a; }
9050 uint32_t a;
9051 std::string so_we_are_non_trivial;
9052 };
9053 inline bool is_constructed() { return gConstructed; }
9054 struct B: public A {
9055 uint32_t b;
9056 };
9057 "};
9058 let cpp = indoc! {"
9059 bool gConstructed = false;
9060 "};
9061 let rs = quote! {
9062 assert!(!ffi::is_constructed());
9063 {
9064 moveit! {
9065 let mut _stack_obj = ffi::#ident::new();
9066 }
9067 assert!(ffi::is_constructed());
9068 #extra_bit
9069 }
9070 assert!(!ffi::is_constructed());
9071 };
9072 run_test(cpp, hdr, rs, &[&ident.to_string(), "is_constructed"], &[]);
9073}
9074
9075#[test]
9076fn test_destructor_moveit() {
9077 destruction_test(
9078 parse_quote! { A },
9079 Some(quote! {
9080 _stack_obj.as_mut().set(42);
9081 assert_eq!(_stack_obj.get(), 42);
9082 }),
9083 );
9084}
9085
9086#[test]
9087fn test_destructor_derived_moveit() {
9088 destruction_test(parse_quote! { B }, None);
9089}
9090
9091#[test]
9092fn test_copy_and_move_constructor_moveit() {
9093 let hdr = indoc! {"
9094 #include <stdint.h>
9095 #include <string>
9096 struct A {
9097 A() {}
9098 A(const A& other) : a(other.a+1) {}
9099 A(A&& other) : a(other.a+2) { other.a = 666; }
9100 void set(uint32_t val) { a = val; }
9101 uint32_t get() const { return a; }
9102 uint32_t a;
9103 std::string so_we_are_non_trivial;
9104 };
9105 "};
9106 let rs = quote! {
9107 moveit! {
9108 let mut stack_obj = ffi::A::new();
9109 }
9110 stack_obj.as_mut().set(42);
9111 moveit! {
9112 let stack_obj2 = autocxx::moveit::new::copy(stack_obj.as_ref());
9113 }
9114 assert_eq!(stack_obj2.get(), 43);
9115 assert_eq!(stack_obj.get(), 42);
9116 moveit! {
9117 let stack_obj3 = autocxx::moveit::new::mov(stack_obj);
9118 }
9119 assert_eq!(stack_obj3.get(), 44);
9120 // Following line prevented by moveit, even though it would
9121 // be possible in C++.
9122 // assert_eq!(stack_obj.get(), 666);
9123 };
9124 run_test("", hdr, rs, &["A"], &[]);
9125}
9126
9127// This test fails on Windows gnu but not on Windows msvc
9128#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
9129#[test]
9130fn test_uniqueptr_moveit() {
9131 let hdr = indoc! {"
9132 #include <stdint.h>
9133 #include <string>
9134 struct A {
9135 A() {}
9136 void set(uint32_t val) { a = val; }
9137 uint32_t get() const { return a; }
9138 uint32_t a;
9139 std::string so_we_are_non_trivial;
9140 };
9141 "};
9142 let rs = quote! {
9143 use autocxx::moveit::EmplaceUnpinned;
9144 let mut up_obj = cxx::UniquePtr::emplace(ffi::A::new());
9145 up_obj.as_mut().unwrap().set(42);
9146 assert_eq!(up_obj.get(), 42);
9147 };
9148 run_test("", hdr, rs, &["A"], &[]);
9149}
9150
9151// This test fails on Windows gnu but not on Windows msvc
9152#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
9153#[test]
9154fn test_various_emplacement() {
9155 let hdr = indoc! {"
9156 #include <stdint.h>
9157 #include <string>
9158 struct A {
9159 A() {}
9160 void set(uint32_t val) { a = val; }
9161 uint32_t get() const { return a; }
9162 uint32_t a;
9163 std::string so_we_are_non_trivial;
9164 };
9165 "};
9166 let rs = quote! {
9167 use autocxx::moveit::EmplaceUnpinned;
9168 use autocxx::moveit::Emplace;
9169 let mut up_obj = cxx::UniquePtr::emplace(ffi::A::new());
9170 up_obj.pin_mut().set(666);
9171 // Can't current move out of a UniquePtr
9172 let mut box_obj = Box::emplace(ffi::A::new());
9173 box_obj.as_mut().set(667);
9174 let box_obj2 = Box::emplace(autocxx::moveit::new::mov(box_obj));
9175 moveit! { let back_on_stack = autocxx::moveit::new::mov(box_obj2); }
9176 assert_eq!(back_on_stack.get(), 667);
9177 };
9178 run_test("", hdr, rs, &["A"], &[]);
9179}
9180
9181#[test]
9182fn test_emplace_uses_overridden_new_and_delete() {
9183 let hdr = indoc! {"
9184 #include <stdint.h>
9185 #include <string>
9186 struct A {
9187 A() {}
9188 void* operator new(size_t count);
9189 void operator delete(void* ptr) noexcept;
9190 void* operator new(size_t count, void* ptr);
9191 std::string so_we_are_non_trivial;
9192 };
9193 void reset_flags();
9194 bool was_new_called();
9195 bool was_delete_called();
9196 "};
9197 let cxx = indoc! {"
9198 bool new_called;
9199 bool delete_called;
9200 void reset_flags() {
9201 new_called = false;
9202 delete_called = false;
9203 }
9204 void* A::operator new(size_t count) {
9205 new_called = true;
9206 return ::operator new(count);
9207 }
9208 void* A::operator new(size_t count, void* ptr) {
9209 return ::operator new(count, ptr);
9210 }
9211 void A::operator delete(void* ptr) noexcept {
9212 delete_called = true;
9213 ::operator delete(ptr);
9214 }
9215 bool was_new_called() {
9216 return new_called;
9217 }
9218 bool was_delete_called() {
9219 return delete_called;
9220 }
9221 "};
9222 let rs = quote! {
9223 ffi::reset_flags();
9224 {
9225 let _ = ffi::A::new().within_unique_ptr();
9226 assert!(ffi::was_new_called());
9227 }
9228 assert!(ffi::was_delete_called());
9229 ffi::reset_flags();
9230 {
9231 use autocxx::moveit::EmplaceUnpinned;
9232 let _ = cxx::UniquePtr::emplace(ffi::A::new());
9233 }
9234 assert!(ffi::was_delete_called());
9235 };
9236 run_test(
9237 cxx,
9238 hdr,
9239 rs,
9240 &["A", "reset_flags", "was_new_called", "was_delete_called"],
9241 &[],
9242 );
9243}
9244
9245#[test]
9246fn test_pass_by_reference_to_value_param() {
9247 let hdr = indoc! {"
9248 #include <stdint.h>
9249 #include <string>
9250 struct A {
9251 A() : count(0) {}
9252 std::string so_we_are_non_trivial;
9253 uint32_t count;
9254 };
9255 void take_a(A a) {
9256 a.count++;
9257 }
9258 uint32_t report_on_a(const A& a) {
9259 return a.count;
9260 }
9261 "};
9262 let rs = quote! {
9263 let a = ffi::A::new().within_unique_ptr();
9264 ffi::take_a(a.as_ref().unwrap());
9265 ffi::take_a(&a); // syntactic sugar
9266 assert_eq!(ffi::report_on_a(&a), 0); // should have acted upon copies
9267 };
9268 run_test("", hdr, rs, &["A", "take_a", "report_on_a"], &[]);
9269}
9270
9271#[test]
9272fn test_explicit_everything() {
9273 let hdr = indoc! {"
9274 #include <stdint.h>
9275 #include <string>
9276 struct A {
9277 A() {} // default constructor
9278 A(A&&) {} // move constructor
9279 A(const A&) {} // copy constructor
9280 A& operator=(const A&) { return *this; } // copy assignment operator
9281 A& operator=(A&&) { return *this; } // move assignment operator
9282 ~A() {} // destructor
9283 void set(uint32_t val) { a = val; }
9284 uint32_t get() const { return a; }
9285 uint32_t a;
9286 std::string so_we_are_non_trivial;
9287 };
9288 "};
9289 let rs = quote! {};
9290 run_test("", hdr, rs, &["A"], &[]);
9291}
9292
9293#[test]
9294fn test_generate_ns() {
9295 let hdr = indoc! {"
9296 namespace A {
9297 inline void foo() {}
9298 inline void bar() {}
9299 }
9300 namespace B {
9301 inline void baz() {}
9302 }
9303 "};
9304 let rs = quote! {
9305 ffi::A::foo();
9306 };
9307 run_test_ex(
9308 "",
9309 hdr,
9310 rs,
9311 quote! {
9312 generate_ns!("A")
9313 safety!(unsafe_ffi)
9314 },
9315 None,
9316 None,
9317 None,
9318 );
9319}
9320
9321#[test]
9322fn test_no_constructor_make_unique_ns() {
9323 let hdr = indoc! {"
9324 #include <stdint.h>
9325 namespace B {
9326 struct A {
9327 uint32_t a;
9328 };
9329 }
9330 "};
9331 let rs = quote! {
9332 ffi::B::A::new().within_unique_ptr();
9333 };
9334 run_test("", hdr, rs, &["B::A"], &[]);
9335}
9336
9337#[test]
9338fn test_no_constructor_pod_make_unique() {
9339 let hdr = indoc! {"
9340 #include <stdint.h>
9341 struct A {
9342 uint32_t a;
9343 };
9344 "};
9345 let rs = quote! {
9346 ffi::A::new().within_unique_ptr();
9347 };
9348 run_test("", hdr, rs, &[], &["A"]);
9349}
9350
9351#[test]
9352fn test_no_constructor_pv() {
9353 let hdr = indoc! {"
9354 #include <stdint.h>
9355 class A {
9356 public:
9357 virtual ~A() {}
9358 virtual void foo() = 0;
9359 };
9360 "};
9361 let rs = quote! {};
9362 run_test("", hdr, rs, &["A"], &[]);
9363}
9364
9365#[test]
9366fn test_suppress_system_includes() {
9367 let hdr = indoc! {"
9368 #include <stdint.h>
9369 #include <string>
9370 inline void a() {};
9371 "};
9372 let rs = quote! {};
9373 run_test_ex(
9374 "",
9375 hdr,
9376 rs,
9377 quote! { generate("a")},
9378 Some(Box::new(SetSuppressSystemHeaders)),
9379 Some(Box::new(NoSystemHeadersChecker)),
9380 None,
9381 );
9382}
9383
9384#[test]
9385fn test_no_rvo_move() {
9386 let hdr = indoc! {"
9387 #include <memory>
9388 class A {
9389 public:
9390 static std::unique_ptr<A> create() { return std::make_unique<A>(); }
9391 };
9392 "};
9393 let rs = quote! {
9394 ffi::A::create();
9395 };
9396 run_test_ex(
9397 "",
9398 hdr,
9399 rs,
9400 quote! { generate!("A") },
9401 None,
9402 Some(Box::new(CppMatcher::new(
9403 &["return A::create();"],
9404 &["return std::move(A::create());"],
9405 ))),
9406 None,
9407 );
9408}
9409
9410#[test]
9411fn test_abstract_up() {
9412 let hdr = indoc! {"
9413 #include <memory>
9414 class A {
9415 public:
9416 virtual void foo() const = 0;
9417 virtual ~A() {}
9418 };
9419 class B : public A {
9420 public:
9421 void foo() const {}
9422 };
9423 inline std::unique_ptr<A> get_a() { return std::make_unique<B>(); }
9424 "};
9425 let rs = quote! {
9426 let a = ffi::get_a();
9427 a.foo();
9428 };
9429 run_test("", hdr, rs, &["A", "get_a"], &[]);
9430}
9431
9432#[test]
9433fn test_abstract_private() {
9434 let hdr = indoc! {"
9435 #include <memory>
9436 class A {
9437 virtual void foo() const = 0;
9438 public:
9439 virtual ~A() {}
9440 };
9441 "};
9442 let rs = quote! {};
9443 run_test("", hdr, rs, &["A"], &[]);
9444}
9445
9446#[test]
9447fn test_abstract_issue_979() {
9448 let hdr = indoc! {"
9449 class Test {
9450 virtual ~Test() {}
9451 virtual void TestBody() = 0;
9452 };
9453 "};
9454 let rs = quote! {};
9455 run_test("", hdr, rs, &["Test"], &[]);
9456}
9457
9458#[test]
9459fn test_class_having_protected_method() {
9460 let hdr = indoc! {"
9461 #include <cstdint>
9462 class A {
9463 protected:
9464 inline uint32_t protected_method() { return 0; }
9465 };
9466 "};
9467 let rs = quote! {};
9468 run_test("", hdr, rs, &[], &["A"]);
9469}
9470
9471#[test]
9472fn test_protected_inner_class() {
9473 let hdr = indoc! {"
9474 #include <cstdint>
9475 inline uint32_t DoMath(uint32_t a) {
9476 return a * 3;
9477 }
9478
9479 class A {
9480 protected:
9481 inline uint32_t protected_method() { return 0; }
9482
9483 struct B {
9484 int x;
9485 };
9486
9487 inline B protected_method_2() {
9488 return { 0 };
9489 }
9490 };
9491 "};
9492 let rs = quote! {};
9493 run_test("", hdr, rs, &["A"], &[]);
9494}
9495
9496#[test]
9497fn test_private_inner_class() {
9498 let hdr = indoc! {"
9499 #include <cstdint>
9500 inline uint32_t DoMath(uint32_t a) {
9501 return a * 3;
9502 }
9503
9504 class A {
9505 protected:
9506 inline uint32_t protected_method() { return 0; }
9507
9508 private:
9509 struct B {
9510 int x;
9511 };
9512
9513 inline B private_method_2() {
9514 return { 0 };
9515 }
9516 };
9517 "};
9518 let rs = quote! {};
9519 run_test("", hdr, rs, &["A"], &[]);
9520}
9521
9522#[test]
9523fn test_class_having_private_method() {
9524 let hdr = indoc! {"
9525 #include <cstdint>
9526 class A {
9527 private:
9528 inline uint32_t private_method() { return 0; }
9529 };
9530 "};
9531 let rs = quote! {};
9532 run_test("", hdr, rs, &[], &["A"]);
9533}
9534
9535#[test]
9536#[ignore] // https://github.com/google/autocxx/issues/787
9537fn test_chrono_problem() {
9538 let hdr = indoc! {"
9539 #include <chrono>
9540 struct Clock {
9541 typedef std::chrono::nanoseconds duration;
9542 };
9543 struct Class {
9544 int a() { return 42; }
9545 std::chrono::time_point<Clock> b();
9546 };
9547 "};
9548 let rs = quote! {};
9549 run_test("", hdr, rs, &[], &["Class"]);
9550}
9551
9552fn size_and_alignment_test(pod: bool) {
9553 static TYPES: [(&str, &str); 6] = [
9554 ("A", "struct A { uint8_t a; };"),
9555 ("B", "struct B { uint32_t a; };"),
9556 ("C", "struct C { uint64_t a; };"),
9557 ("D", "enum D { Z, X };"),
9558 ("E", "struct E { uint8_t a; uint32_t b; };"),
9559 ("F", "struct F { uint32_t a; uint8_t b; };"),
9560 ];
9561 let type_definitions = TYPES.iter().map(|(_, def)| *def).join("\n");
9562 let function_definitions = TYPES.iter().map(|(name, _)| format!("inline size_t get_sizeof_{}() {{ return sizeof({}); }}\ninline size_t get_alignof_{}() {{ return alignof({}); }}\n",
9563 name, name, name, name)).join("\n");
9564 let hdr = format!(
9565 indoc! {"
9566 #include <cstdint>
9567 #include <cstddef>
9568 {}
9569 {}
9570 "},
9571 type_definitions, function_definitions
9572 );
9573 #[allow(clippy::unnecessary_to_owned)] // wrongly triggers on into_iter() below
9574 let allowlist_fns: Vec<String> = TYPES
9575 .iter()
9576 .flat_map(|(name, _)| {
9577 [
9578 format!("get_sizeof_{}", name),
9579 format!("get_alignof_{}", name),
9580 ]
9581 .to_vec()
9582 .into_iter()
9583 })
9584 .collect_vec();
9585 let allowlist_types: Vec<String> = TYPES.iter().map(|(name, _)| name.to_string()).collect_vec();
9586 let allowlist_both = allowlist_types
9587 .iter()
9588 .cloned()
9589 .chain(allowlist_fns.iter().cloned())
9590 .collect_vec();
9591 let allowlist_types: Vec<&str> = allowlist_types.iter().map(AsRef::as_ref).collect_vec();
9592 let allowlist_fns: Vec<&str> = allowlist_fns.iter().map(AsRef::as_ref).collect_vec();
9593 let allowlist_both: Vec<&str> = allowlist_both.iter().map(AsRef::as_ref).collect_vec();
9594 let rs = TYPES.iter().fold(quote! {}, |mut accumulator, (name, _)| {
9595 let get_align_symbol =
9596 proc_macro2::Ident::new(&format!("get_alignof_{}", name), Span::call_site());
9597 let get_size_symbol =
9598 proc_macro2::Ident::new(&format!("get_sizeof_{}", name), Span::call_site());
9599 let type_symbol = proc_macro2::Ident::new(name, Span::call_site());
9600 accumulator.extend(quote! {
9601 let c_size = ffi::#get_size_symbol();
9602 let c_align = ffi::#get_align_symbol();
9603 assert_eq!(std::mem::size_of::<ffi::#type_symbol>(), c_size);
9604 assert_eq!(std::mem::align_of::<ffi::#type_symbol>(), c_align);
9605 });
9606 accumulator
9607 });
9608 if pod {
9609 run_test("", &hdr, rs, &allowlist_fns, &allowlist_types);
9610 } else {
9611 run_test("", &hdr, rs, &allowlist_both, &[]);
9612 }
9613}
9614
9615#[test]
9616fn test_sizes_and_alignment_nonpod() {
9617 size_and_alignment_test(false)
9618}
9619
9620#[test]
9621fn test_sizes_and_alignment_pod() {
9622 size_and_alignment_test(true)
9623}
9624
9625#[test]
9626fn test_nested_class_methods() {
9627 let hdr = indoc! {"
9628 #include <cstdint>
9629 class A {
9630 public:
9631 virtual ~A() {}
9632 struct B {
9633 virtual void b() const {}
9634 };
9635 virtual void a() const {}
9636 struct C {
9637 virtual void b() const {}
9638 };
9639 virtual void c() const {}
9640 struct D {
9641 virtual void b() const {}
9642 };
9643 };
9644 "};
9645 let rs = quote! {
9646 let a = ffi::A::new().within_unique_ptr();
9647 a.a();
9648 a.c();
9649 };
9650 run_test("", hdr, rs, &["A"], &[]);
9651}
9652
9653#[test]
9654fn test_call_superclass() {
9655 let hdr = indoc! {"
9656 #include <memory>
9657 class A {
9658 public:
9659 virtual void foo() const {};
9660 virtual ~A() {}
9661 };
9662 class B : public A {
9663 public:
9664 void bar() const {}
9665 };
9666 inline std::unique_ptr<B> get_b() { return std::make_unique<B>(); }
9667 "};
9668 let rs = quote! {
9669 let b = ffi::get_b();
9670 b.as_ref().unwrap().as_ref().foo();
9671 };
9672 run_test("", hdr, rs, &["A", "B", "get_b"], &[]);
9673}
9674
9675#[test]
9676fn test_pass_superclass() {
9677 let hdr = indoc! {"
9678 #include <memory>
9679 class A {
9680 public:
9681 virtual void foo() const {};
9682 virtual ~A() {}
9683 };
9684 class B : public A {
9685 public:
9686 void bar() const {}
9687 };
9688 inline std::unique_ptr<B> get_b() { return std::make_unique<B>(); }
9689 inline void take_a(const A&) {}
9690 "};
9691 let rs = quote! {
9692 let b = ffi::get_b();
9693 ffi::take_a(b.as_ref().unwrap().as_ref());
9694 };
9695 run_test("", hdr, rs, &["A", "B", "get_b", "take_a"], &[]);
9696}
9697
9698#[test]
9699fn test_issue486_multi_types() {
9700 let hdr = indoc! {"
9701 namespace a {
9702 namespace spanner {
9703 struct Key {};
9704 }
9705 } // namespace a
9706 namespace b {
9707 namespace spanner {
9708 typedef int Key;
9709 }
9710 } // namespace b
9711 namespace c {
9712 namespace spanner {
9713 enum Key { A, B };
9714 }
9715 } // namespace c
9716 namespace spanner {
9717 class Key {
9718 public:
9719 bool a(a::spanner::Key &);
9720 bool b(b::spanner::Key &);
9721 bool c(c::spanner::Key &);
9722 };
9723 } // namespace spanner
9724 "};
9725 let rs = quote! {};
9726 run_test(
9727 "",
9728 hdr,
9729 rs,
9730 &["spanner::Key", "a::spanner::Key", "b::spanner::Key"],
9731 &[],
9732 );
9733}
9734
9735#[test]
9736/// Tests types with various forms of copy, move, and default constructors. Calls the things which
9737/// should be generated, and will produce C++ compile failures if other wrappers are generated.
9738///
9739/// Specifically, we can have the cross product of any of these:
9740/// * Explicitly deleted
9741/// * Implicitly defaulted
9742/// * User declared
9743/// * Explicitly defaulted
9744/// Not handled yet: https://github.com/google/autocxx/issues/815.
9745/// Once this is handled, add equivalents of all the implicitly defaulted cases, at all
9746/// visibility levels.
9747/// applied to each of these:
9748/// * Default constructor
9749/// * Copy constructor
9750/// * Move constructor
9751/// in any of these:
9752/// * The class itself
9753/// * A base class
9754/// * A field of the class
9755/// * A field of a base class
9756/// with any of these access modifiers:
9757/// * private (impossible for implicitly defaulted)
9758/// * protected (impossible for implicitly defaulted)
9759/// * public
9760///
9761/// Various combinations of these lead to the default versions being deleted. The move and copy
9762/// ones also interact with each other in various ways.
9763///
9764/// TODO: Remove all the `int x` members after https://github.com/google/autocxx/issues/832 is
9765/// fixed.
9766fn test_implicit_constructor_rules() {
9767 let cxx = "";
9768 let hdr = indoc! {"
9769 struct AllImplicitlyDefaulted {
9770 void a() const {}
9771 };
9772
9773 struct PublicDeleted {
9774 PublicDeleted() = delete;
9775 PublicDeleted(const PublicDeleted&) = delete;
9776 PublicDeleted(PublicDeleted&&) = delete;
9777
9778 void a() const {}
9779
9780 int x;
9781 };
9782 struct PublicDeletedDefault {
9783 PublicDeletedDefault() = delete;
9784
9785 void a() const {}
9786
9787 int x;
9788 };
9789 struct PublicDeletedCopy {
9790 PublicDeletedCopy() = default;
9791 PublicDeletedCopy(const PublicDeletedCopy&) = delete;
9792
9793 void a() const {}
9794
9795 int x;
9796 };
9797 struct PublicDeletedCopyNoDefault {
9798 PublicDeletedCopyNoDefault(const PublicDeletedCopyNoDefault&) = delete;
9799
9800 void a() const {}
9801
9802 int x;
9803 };
9804 struct PublicMoveDeletedCopy {
9805 PublicMoveDeletedCopy() = default;
9806 PublicMoveDeletedCopy(const PublicMoveDeletedCopy&) = delete;
9807 PublicMoveDeletedCopy(PublicMoveDeletedCopy&&) = default;
9808
9809 void a() const {}
9810
9811 int x;
9812 };
9813 struct PublicDeletedMove {
9814 PublicDeletedMove() = default;
9815 PublicDeletedMove(PublicDeletedMove&&) = delete;
9816
9817 void a() const {}
9818
9819 int x;
9820 };
9821 struct PublicDeletedDestructor {
9822 PublicDeletedDestructor() = default;
9823 ~PublicDeletedDestructor() = delete;
9824
9825 void a() const {}
9826
9827 int x;
9828 };
9829 struct PublicDestructor {
9830 PublicDestructor() = default;
9831 ~PublicDestructor() = default;
9832
9833 void a() const {}
9834
9835 int x;
9836 };
9837
9838 struct ProtectedDeleted {
9839 void a() const {}
9840
9841 int x;
9842
9843 protected:
9844 ProtectedDeleted() = delete;
9845 ProtectedDeleted(const ProtectedDeleted&) = delete;
9846 ProtectedDeleted(ProtectedDeleted&&) = delete;
9847 };
9848 struct ProtectedDeletedDefault {
9849 void a() const {}
9850
9851 int x;
9852
9853 protected:
9854 ProtectedDeletedDefault() = delete;
9855 };
9856 struct ProtectedDeletedCopy {
9857 ProtectedDeletedCopy() = default;
9858
9859 void a() const {}
9860
9861 int x;
9862
9863 protected:
9864 ProtectedDeletedCopy(const ProtectedDeletedCopy&) = delete;
9865 };
9866 struct ProtectedDeletedCopyNoDefault {
9867 void a() const {}
9868
9869 int x;
9870
9871 protected:
9872 ProtectedDeletedCopyNoDefault(const ProtectedDeletedCopyNoDefault&) = delete;
9873 };
9874 struct ProtectedMoveDeletedCopy {
9875 ProtectedMoveDeletedCopy() = default;
9876
9877 void a() const {}
9878
9879 int x;
9880
9881 protected:
9882 ProtectedMoveDeletedCopy(const ProtectedMoveDeletedCopy&) = delete;
9883 ProtectedMoveDeletedCopy(ProtectedMoveDeletedCopy&&) = default;
9884 };
9885 struct ProtectedDeletedMove {
9886 ProtectedDeletedMove() = default;
9887
9888 void a() const {}
9889
9890 int x;
9891
9892 protected:
9893 ProtectedDeletedMove(ProtectedDeletedMove&&) = delete;
9894 };
9895 struct ProtectedDeletedDestructor {
9896 ProtectedDeletedDestructor() = default;
9897
9898 void a() const {}
9899
9900 int x;
9901
9902 protected:
9903 ~ProtectedDeletedDestructor() = delete;
9904 };
9905 struct ProtectedDestructor {
9906 ProtectedDestructor() = default;
9907
9908 void a() const {}
9909
9910 int x;
9911
9912 protected:
9913 ~ProtectedDestructor() = default;
9914 };
9915
9916 struct PrivateDeleted {
9917 void a() const {}
9918
9919 int x;
9920
9921 private:
9922 PrivateDeleted() = delete;
9923 PrivateDeleted(const PrivateDeleted&) = delete;
9924 PrivateDeleted(PrivateDeleted&&) = delete;
9925 };
9926 struct PrivateDeletedDefault {
9927 void a() const {}
9928
9929 int x;
9930
9931 private:
9932 PrivateDeletedDefault() = delete;
9933 };
9934 struct PrivateDeletedCopy {
9935 PrivateDeletedCopy() = default;
9936
9937 void a() const {}
9938
9939 int x;
9940
9941 private:
9942 PrivateDeletedCopy(const PrivateDeletedCopy&) = delete;
9943 };
9944 struct PrivateDeletedCopyNoDefault {
9945 void a() const {}
9946
9947 int x;
9948
9949 private:
9950 PrivateDeletedCopyNoDefault(const PrivateDeletedCopyNoDefault&) = delete;
9951 };
9952 struct PrivateMoveDeletedCopy {
9953 PrivateMoveDeletedCopy() = default;
9954
9955 void a() const {}
9956
9957 int x;
9958
9959 private:
9960 PrivateMoveDeletedCopy(const PrivateMoveDeletedCopy&) = delete;
9961 PrivateMoveDeletedCopy(PrivateMoveDeletedCopy&&) = default;
9962 };
9963 struct PrivateDeletedMove {
9964 PrivateDeletedMove() = default;
9965
9966 void a() const {}
9967
9968 int x;
9969
9970 private:
9971 PrivateDeletedMove(PrivateDeletedMove&&) = delete;
9972 };
9973 struct PrivateDeletedDestructor {
9974 PrivateDeletedDestructor() = default;
9975
9976 void a() const {}
9977
9978 int x;
9979
9980 private:
9981 ~PrivateDeletedDestructor() = delete;
9982 };
9983 struct PrivateDestructor {
9984 PrivateDestructor() = default;
9985
9986 void a() const {}
9987
9988 int x;
9989
9990 private:
9991 ~PrivateDestructor() = default;
9992 };
9993
9994 struct NonConstCopy {
9995 NonConstCopy() = default;
9996
9997 NonConstCopy(NonConstCopy&) {}
9998 NonConstCopy(NonConstCopy&&) = default;
9999
10000 void a() const {}
10001 };
10002 struct TwoCopy {
10003 TwoCopy() = default;
10004
10005 TwoCopy(TwoCopy&) {}
10006 TwoCopy(const TwoCopy&) {}
10007 TwoCopy(TwoCopy&&) = default;
10008
10009 void a() const {}
10010 };
10011
10012 struct MemberPointerDeleted {
10013 PublicDeleted *x;
10014
10015 void a() const {}
10016 };
10017
10018 struct MemberConstPointerDeleted {
10019 PublicDeleted *const x;
10020
10021 void a() const {}
10022 };
10023
10024 struct MemberConst {
10025 const int x;
10026
10027 void a() const {}
10028 };
10029
10030 struct MemberReferenceDeleted {
10031 PublicDeleted &x;
10032
10033 void a() const {}
10034 };
10035
10036 struct MemberConstReferenceDeleted {
10037 const PublicDeleted &x;
10038
10039 void a() const {}
10040 };
10041
10042 struct MemberReference {
10043 int &x;
10044
10045 void a() const {}
10046 };
10047
10048 struct MemberConstReference {
10049 const int &x;
10050
10051 void a() const {}
10052 };
10053
10054 struct MemberRvalueReferenceDeleted {
10055 PublicDeleted &&x;
10056
10057 void a() const {}
10058 };
10059
10060 struct MemberRvalueReference {
10061 int &&x;
10062
10063 void a() const {}
10064 };
10065
10066 struct BasePublicDeleted : public PublicDeleted {};
10067 struct BasePublicDeletedDefault : public PublicDeletedDefault {};
10068 struct BasePublicDeletedCopy : public PublicDeletedCopy {};
10069 struct BasePublicDeletedCopyNoDefault : public PublicDeletedCopyNoDefault { };
10070 struct BasePublicMoveDeletedCopy : public PublicMoveDeletedCopy {};
10071 struct BasePublicDeletedMove : public PublicDeletedMove {};
10072 struct BasePublicDeletedDestructor : public PublicDeletedDestructor {};
10073 struct BasePublicDestructor : public PublicDestructor {};
10074
10075 struct MemberPublicDeleted {
10076 void a() const {}
10077
10078 PublicDeleted member;
10079 };
10080 struct MemberPublicDeletedDefault {
10081 void a() const {}
10082
10083 PublicDeletedDefault member;
10084 };
10085 struct MemberPublicDeletedCopy {
10086 void a() const {}
10087
10088 PublicDeletedCopy member;
10089 };
10090 struct MemberPublicDeletedCopyNoDefault {
10091 void a() const {}
10092
10093 PublicDeletedCopyNoDefault member;
10094 };
10095 struct MemberPublicMoveDeletedCopy {
10096 void a() const {}
10097
10098 PublicMoveDeletedCopy member;
10099 };
10100 struct MemberPublicDeletedMove {
10101 void a() const {}
10102
10103 PublicDeletedMove member;
10104 };
10105 struct MemberPublicDeletedDestructor {
10106 void a() const {}
10107
10108 PublicDeletedDestructor member;
10109 };
10110 struct MemberPublicDestructor {
10111 void a() const {}
10112
10113 PublicDestructor member;
10114 };
10115
10116 struct BaseMemberPublicDeleted : public MemberPublicDeleted {};
10117 struct BaseMemberPublicDeletedDefault : public MemberPublicDeletedDefault {};
10118 struct BaseMemberPublicDeletedCopy : public MemberPublicDeletedCopy {};
10119 struct BaseMemberPublicDeletedCopyNoDefault : public MemberPublicDeletedCopyNoDefault {};
10120 struct BaseMemberPublicMoveDeletedCopy : public MemberPublicMoveDeletedCopy {};
10121 struct BaseMemberPublicDeletedMove : public MemberPublicDeletedMove {};
10122 struct BaseMemberPublicDeletedDestructor : public MemberPublicDeletedDestructor {};
10123 struct BaseMemberPublicDestructor : public MemberPublicDestructor {};
10124
10125 struct BaseProtectedDeleted : public ProtectedDeleted {};
10126 struct BaseProtectedDeletedDefault : public ProtectedDeletedDefault {};
10127 struct BaseProtectedDeletedCopy : public ProtectedDeletedCopy {};
10128 struct BaseProtectedDeletedCopyNoDefault : public ProtectedDeletedCopyNoDefault {};
10129 struct BaseProtectedMoveDeletedCopy : public ProtectedMoveDeletedCopy {};
10130 struct BaseProtectedDeletedMove : public ProtectedDeletedMove {};
10131 struct BaseProtectedDeletedDestructor : public ProtectedDeletedDestructor {};
10132 struct BaseProtectedDestructor : public ProtectedDestructor {};
10133
10134 struct MemberProtectedDeleted {
10135 void a() const {}
10136
10137 ProtectedDeleted member;
10138 };
10139 struct MemberProtectedDeletedDefault {
10140 void a() const {}
10141
10142 ProtectedDeletedDefault member;
10143 };
10144 struct MemberProtectedDeletedCopy {
10145 void a() const {}
10146
10147 ProtectedDeletedCopy member;
10148 };
10149 struct MemberProtectedDeletedCopyNoDefault {
10150 void a() const {}
10151
10152 ProtectedDeletedCopyNoDefault member;
10153 };
10154 struct MemberProtectedMoveDeletedCopy {
10155 void a() const {}
10156
10157 ProtectedMoveDeletedCopy member;
10158 };
10159 struct MemberProtectedDeletedMove {
10160 void a() const {}
10161
10162 ProtectedDeletedMove member;
10163 };
10164 struct MemberProtectedDeletedDestructor {
10165 void a() const {}
10166
10167 ProtectedDeletedDestructor member;
10168 };
10169 struct MemberProtectedDestructor {
10170 void a() const {}
10171
10172 ProtectedDestructor member;
10173 };
10174
10175 struct BaseMemberProtectedDeleted : public MemberProtectedDeleted {};
10176 struct BaseMemberProtectedDeletedDefault : public MemberProtectedDeletedDefault {};
10177 struct BaseMemberProtectedDeletedCopy : public MemberProtectedDeletedCopy {};
10178 struct BaseMemberProtectedDeletedCopyNoDefault : public MemberProtectedDeletedCopyNoDefault {};
10179 struct BaseMemberProtectedMoveDeletedCopy : public MemberProtectedMoveDeletedCopy {};
10180 struct BaseMemberProtectedDeletedMove : public MemberProtectedDeletedMove {};
10181 struct BaseMemberProtectedDeletedDestructor : public MemberProtectedDeletedDestructor {};
10182 struct BaseMemberProtectedDestructor : public MemberProtectedDestructor {};
10183
10184 struct BasePrivateDeleted : public PrivateDeleted {};
10185 struct BasePrivateDeletedDefault : public PrivateDeletedDefault {};
10186 struct BasePrivateDeletedCopy : public PrivateDeletedCopy {};
10187 struct BasePrivateDeletedCopyNoDefault : public PrivateDeletedCopyNoDefault {};
10188 struct BasePrivateMoveDeletedCopy : public PrivateMoveDeletedCopy {};
10189 struct BasePrivateDeletedMove : public PrivateDeletedMove {};
10190 struct BasePrivateDeletedDestructor : public PrivateDeletedDestructor {};
10191 struct BasePrivateDestructor : public PrivateDestructor {};
10192
10193 struct MemberPrivateDeleted {
10194 void a() const {}
10195
10196 PrivateDeleted member;
10197 };
10198 struct MemberPrivateDeletedDefault {
10199 void a() const {}
10200
10201 PrivateDeletedDefault member;
10202 };
10203 struct MemberPrivateDeletedCopy {
10204 void a() const {}
10205
10206 PrivateDeletedCopy member;
10207 };
10208 struct MemberPrivateDeletedCopyNoDefault {
10209 void a() const {}
10210
10211 PrivateDeletedCopyNoDefault member;
10212 };
10213 struct MemberPrivateMoveDeletedCopy {
10214 void a() const {}
10215
10216 PrivateMoveDeletedCopy member;
10217 };
10218 struct MemberPrivateDeletedMove {
10219 void a() const {}
10220
10221 PrivateDeletedMove member;
10222 };
10223 struct MemberPrivateDeletedDestructor {
10224 void a() const {}
10225
10226 PrivateDeletedDestructor member;
10227 };
10228 struct MemberPrivateDestructor {
10229 void a() const {}
10230
10231 PrivateDestructor member;
10232 };
10233
10234 struct BaseMemberPrivateDeleted : public MemberPrivateDeleted {};
10235 struct BaseMemberPrivateDeletedDefault : public MemberPrivateDeletedDefault {};
10236 struct BaseMemberPrivateDeletedCopy : public MemberPrivateDeletedCopy {};
10237 struct BaseMemberPrivateDeletedCopyNoDefault : public MemberPrivateDeletedCopyNoDefault {};
10238 struct BaseMemberPrivateMoveDeletedCopy : public MemberPrivateMoveDeletedCopy {};
10239 struct BaseMemberPrivateDeletedMove : public MemberPrivateDeletedMove {};
10240 struct BaseMemberPrivateDeletedDestructor : public MemberPrivateDeletedDestructor {};
10241 struct BaseMemberPrivateDestructor : public MemberPrivateDestructor {};
10242 "};
10243 let rs = quote! {
10244 // Some macros to test various operations on our types. Note that some of them define
10245 // functions which take arguments that the APIs defined in this test have no way to
10246 // produce, because we have C++ types which can't be constructed (for example). In a real
10247 // program, there might be other C++ APIs which can instantiate these types.
10248
10249 // TODO: https://github.com/google/autocxx/issues/829: Should this be merged with
10250 // `test_make_unique`? Currently types where the Rust wrappers permit this but not that
10251 // aren't running C++ destructors.
10252 macro_rules! test_constructible {
10253 [$t:ty] => {
10254 moveit! {
10255 let _moveit_t = <$t>::new();
10256 }
10257 }
10258 }
10259 macro_rules! test_make_unique {
10260 [$t:ty] => {
10261 let _unique_t = <$t>::new().within_unique_ptr();
10262 }
10263 }
10264 macro_rules! test_copyable {
10265 [$t:ty] => {
10266 {
10267 fn test_copyable(moveit_t: impl autocxx::moveit::new::New<Output = $t>) {
10268 moveit! {
10269 let moveit_t = moveit_t;
10270 let _copied_t = autocxx::moveit::new::copy(moveit_t);
10271 }
10272 }
10273 }
10274 }
10275 }
10276 macro_rules! test_movable {
10277 [$t:ty] => {
10278 {
10279 fn test_movable(moveit_t: impl autocxx::moveit::new::New<Output = $t>) {
10280 moveit! {
10281 let moveit_t = moveit_t;
10282 let _moved_t = autocxx::moveit::new::mov(moveit_t);
10283 }
10284 }
10285 }
10286 }
10287 }
10288 macro_rules! test_call_a {
10289 [$t:ty] => {
10290 {
10291 fn test_call_a(t: &$t) {
10292 t.a();
10293 }
10294 }
10295 }
10296 }
10297 macro_rules! test_call_a_as {
10298 [$t:ty, $parent:ty] => {
10299 {
10300 fn test_call_a(t: &$t) {
10301 let t: &$parent = t.as_ref();
10302 t.a();
10303 }
10304 }
10305 }
10306 }
10307
10308 test_constructible![ffi::AllImplicitlyDefaulted];
10309 test_make_unique![ffi::AllImplicitlyDefaulted];
10310 test_copyable![ffi::AllImplicitlyDefaulted];
10311 test_movable![ffi::AllImplicitlyDefaulted];
10312 test_call_a![ffi::AllImplicitlyDefaulted];
10313
10314 test_call_a![ffi::PublicDeleted];
10315
10316 test_copyable![ffi::PublicDeletedDefault];
10317 test_movable![ffi::PublicDeletedDefault];
10318 test_call_a![ffi::PublicDeletedDefault];
10319
10320 test_constructible![ffi::PublicDeletedCopy];
10321 test_make_unique![ffi::PublicDeletedCopy];
10322 test_call_a![ffi::PublicDeletedCopy];
10323
10324 test_call_a![ffi::PublicDeletedCopyNoDefault];
10325
10326 test_constructible![ffi::PublicMoveDeletedCopy];
10327 test_make_unique![ffi::PublicMoveDeletedCopy];
10328 test_movable![ffi::PublicMoveDeletedCopy];
10329 test_call_a![ffi::PublicMoveDeletedCopy];
10330
10331 test_constructible![ffi::PublicDeletedMove];
10332 test_make_unique![ffi::PublicDeletedMove];
10333 test_call_a![ffi::PublicDeletedMove];
10334
10335 test_constructible![ffi::PublicDeletedDestructor];
10336 test_copyable![ffi::PublicDeletedDestructor];
10337 test_call_a![ffi::PublicDeletedDestructor];
10338
10339 test_constructible![ffi::PublicDestructor];
10340 test_make_unique![ffi::PublicDestructor];
10341 test_copyable![ffi::PublicDestructor];
10342 test_call_a![ffi::PublicDestructor];
10343
10344 test_call_a![ffi::ProtectedDeleted];
10345
10346 test_copyable![ffi::ProtectedDeletedDefault];
10347 test_movable![ffi::ProtectedDeletedDefault];
10348 test_call_a![ffi::ProtectedDeletedDefault];
10349
10350 test_constructible![ffi::ProtectedDeletedCopy];
10351 test_make_unique![ffi::ProtectedDeletedCopy];
10352 test_call_a![ffi::ProtectedDeletedCopy];
10353
10354 test_call_a![ffi::ProtectedDeletedCopyNoDefault];
10355
10356 test_constructible![ffi::ProtectedMoveDeletedCopy];
10357 test_make_unique![ffi::ProtectedMoveDeletedCopy];
10358 test_call_a![ffi::ProtectedMoveDeletedCopy];
10359
10360 test_constructible![ffi::ProtectedDeletedMove];
10361 test_make_unique![ffi::ProtectedDeletedMove];
10362 test_call_a![ffi::ProtectedDeletedMove];
10363
10364 test_constructible![ffi::ProtectedDeletedDestructor];
10365 test_copyable![ffi::ProtectedDeletedDestructor];
10366 test_call_a![ffi::ProtectedDeletedDestructor];
10367
10368 test_constructible![ffi::ProtectedDestructor];
10369 test_copyable![ffi::ProtectedDestructor];
10370 test_call_a![ffi::ProtectedDestructor];
10371
10372 test_call_a![ffi::PrivateDeleted];
10373
10374 test_copyable![ffi::PrivateDeletedDefault];
10375 test_movable![ffi::PrivateDeletedDefault];
10376 test_call_a![ffi::PrivateDeletedDefault];
10377
10378 test_constructible![ffi::PrivateDeletedCopy];
10379 test_make_unique![ffi::PrivateDeletedCopy];
10380 test_call_a![ffi::PrivateDeletedCopy];
10381
10382 test_call_a![ffi::PrivateDeletedCopyNoDefault];
10383
10384 test_constructible![ffi::PrivateMoveDeletedCopy];
10385 test_make_unique![ffi::PrivateMoveDeletedCopy];
10386 test_call_a![ffi::PrivateMoveDeletedCopy];
10387
10388 test_constructible![ffi::PrivateDeletedMove];
10389 test_make_unique![ffi::PrivateDeletedMove];
10390 test_call_a![ffi::PrivateDeletedMove];
10391
10392 test_constructible![ffi::PrivateDeletedDestructor];
10393 test_copyable![ffi::PrivateDeletedDestructor];
10394 test_call_a![ffi::PrivateDeletedDestructor];
10395
10396 test_constructible![ffi::PrivateDestructor];
10397 test_copyable![ffi::PrivateDestructor];
10398 test_call_a![ffi::PrivateDestructor];
10399
10400 test_constructible![ffi::NonConstCopy];
10401 test_make_unique![ffi::NonConstCopy];
10402 test_movable![ffi::NonConstCopy];
10403 test_call_a![ffi::NonConstCopy];
10404
10405 test_constructible![ffi::TwoCopy];
10406 test_make_unique![ffi::TwoCopy];
10407 test_copyable![ffi::TwoCopy];
10408 test_movable![ffi::TwoCopy];
10409 test_call_a![ffi::TwoCopy];
10410
10411 // TODO: https://github.com/google/autocxx/issues/865
10412 // Treat pointers and references differently so this has a default constructor.
10413 //test_constructible![ffi::MemberPointerDeleted];
10414 //test_make_unique![ffi::MemberPointerDeleted];
10415 test_copyable![ffi::MemberPointerDeleted];
10416 test_movable![ffi::MemberPointerDeleted];
10417 test_call_a![ffi::MemberPointerDeleted];
10418
10419 test_copyable![ffi::MemberConstPointerDeleted];
10420 test_movable![ffi::MemberConstPointerDeleted];
10421 test_call_a![ffi::MemberConstPointerDeleted];
10422
10423 //test_copyable![ffi::MemberConst];
10424 //test_movable![ffi::MemberConst];
10425 //test_call_a![ffi::MemberConst];
10426
10427 test_copyable![ffi::MemberReferenceDeleted];
10428 test_movable![ffi::MemberReferenceDeleted];
10429 test_call_a![ffi::MemberReferenceDeleted];
10430
10431 test_copyable![ffi::MemberConstReferenceDeleted];
10432 test_movable![ffi::MemberConstReferenceDeleted];
10433 test_call_a![ffi::MemberConstReferenceDeleted];
10434
10435 test_copyable![ffi::MemberReference];
10436 test_movable![ffi::MemberReference];
10437 test_call_a![ffi::MemberReference];
10438
10439 test_copyable![ffi::MemberConstReference];
10440 test_movable![ffi::MemberConstReference];
10441 test_call_a![ffi::MemberConstReference];
10442
10443 test_movable![ffi::MemberRvalueReferenceDeleted];
10444 test_call_a![ffi::MemberRvalueReferenceDeleted];
10445
10446 test_movable![ffi::MemberRvalueReference];
10447 test_call_a![ffi::MemberRvalueReference];
10448
10449 test_call_a_as![ffi::BasePublicDeleted, ffi::PublicDeleted];
10450
10451 test_copyable![ffi::BasePublicDeletedDefault];
10452 test_movable![ffi::BasePublicDeletedDefault];
10453 test_call_a_as![ffi::BasePublicDeletedDefault, ffi::PublicDeletedDefault];
10454
10455 test_constructible![ffi::BasePublicDeletedCopy];
10456 test_make_unique![ffi::BasePublicDeletedCopy];
10457 test_call_a_as![ffi::BasePublicDeletedCopy, ffi::PublicDeletedCopy];
10458
10459 test_call_a_as![ffi::BasePublicDeletedCopyNoDefault, ffi::PublicDeletedCopyNoDefault];
10460
10461 test_constructible![ffi::BasePublicMoveDeletedCopy];
10462 test_make_unique![ffi::BasePublicMoveDeletedCopy];
10463 test_movable![ffi::BasePublicMoveDeletedCopy];
10464 test_call_a_as![ffi::BasePublicMoveDeletedCopy, ffi::PublicMoveDeletedCopy];
10465
10466 test_constructible![ffi::BasePublicDeletedMove];
10467 test_make_unique![ffi::BasePublicDeletedMove];
10468 test_call_a_as![ffi::BasePublicDeletedMove, ffi::PublicDeletedMove];
10469
10470 test_call_a_as![ffi::BasePublicDeletedDestructor, ffi::PublicDeletedDestructor];
10471
10472 test_constructible![ffi::BasePublicDestructor];
10473 test_make_unique![ffi::BasePublicDestructor];
10474 test_copyable![ffi::BasePublicDestructor];
10475 test_call_a_as![ffi::BasePublicDestructor, ffi::PublicDestructor];
10476
10477 test_call_a![ffi::MemberPublicDeleted];
10478
10479 test_copyable![ffi::MemberPublicDeletedDefault];
10480 test_movable![ffi::MemberPublicDeletedDefault];
10481 test_call_a![ffi::MemberPublicDeletedDefault];
10482
10483 test_constructible![ffi::MemberPublicDeletedCopy];
10484 test_make_unique![ffi::MemberPublicDeletedCopy];
10485 test_call_a![ffi::MemberPublicDeletedCopy];
10486
10487 test_call_a![ffi::MemberPublicDeletedCopyNoDefault];
10488
10489 test_constructible![ffi::MemberPublicMoveDeletedCopy];
10490 test_make_unique![ffi::MemberPublicMoveDeletedCopy];
10491 test_movable![ffi::MemberPublicMoveDeletedCopy];
10492 test_call_a![ffi::MemberPublicMoveDeletedCopy];
10493
10494 test_constructible![ffi::MemberPublicDeletedMove];
10495 test_make_unique![ffi::MemberPublicDeletedMove];
10496 test_call_a![ffi::MemberPublicDeletedMove];
10497
10498 test_call_a![ffi::MemberPublicDeletedDestructor];
10499
10500 test_constructible![ffi::MemberPublicDestructor];
10501 test_make_unique![ffi::MemberPublicDestructor];
10502 test_copyable![ffi::MemberPublicDestructor];
10503 test_call_a![ffi::MemberPublicDestructor];
10504
10505 test_call_a_as![ffi::BaseMemberPublicDeleted, ffi::MemberPublicDeleted];
10506
10507 test_copyable![ffi::BaseMemberPublicDeletedDefault];
10508 test_movable![ffi::BaseMemberPublicDeletedDefault];
10509 test_call_a_as![ffi::BaseMemberPublicDeletedDefault, ffi::MemberPublicDeletedDefault];
10510
10511 test_constructible![ffi::BaseMemberPublicDeletedCopy];
10512 test_make_unique![ffi::BaseMemberPublicDeletedCopy];
10513 test_call_a_as![ffi::BaseMemberPublicDeletedCopy, ffi::MemberPublicDeletedCopy];
10514
10515 test_call_a_as![ffi::BaseMemberPublicDeletedCopyNoDefault, ffi::MemberPublicDeletedCopyNoDefault];
10516
10517 test_constructible![ffi::BaseMemberPublicMoveDeletedCopy];
10518 test_make_unique![ffi::BaseMemberPublicMoveDeletedCopy];
10519 test_movable![ffi::BaseMemberPublicMoveDeletedCopy];
10520 test_call_a_as![ffi::BaseMemberPublicMoveDeletedCopy, ffi::MemberPublicMoveDeletedCopy];
10521
10522 test_constructible![ffi::BaseMemberPublicDeletedMove];
10523 test_make_unique![ffi::BaseMemberPublicDeletedMove];
10524 test_call_a_as![ffi::BaseMemberPublicDeletedMove, ffi::MemberPublicDeletedMove];
10525
10526 test_call_a_as![ffi::BaseMemberPublicDeletedDestructor, ffi::MemberPublicDeletedDestructor];
10527
10528 test_constructible![ffi::BaseMemberPublicDestructor];
10529 test_make_unique![ffi::BaseMemberPublicDestructor];
10530 test_copyable![ffi::BaseMemberPublicDestructor];
10531 test_call_a_as![ffi::BaseMemberPublicDestructor, ffi::MemberPublicDestructor];
10532
10533 test_call_a_as![ffi::BaseProtectedDeleted, ffi::ProtectedDeleted];
10534
10535 test_copyable![ffi::BaseProtectedDeletedDefault];
10536 test_movable![ffi::BaseProtectedDeletedDefault];
10537 test_call_a_as![ffi::BaseProtectedDeletedDefault, ffi::ProtectedDeletedDefault];
10538
10539 test_constructible![ffi::BaseProtectedDeletedCopy];
10540 test_make_unique![ffi::BaseProtectedDeletedCopy];
10541 test_call_a_as![ffi::BaseProtectedDeletedCopy, ffi::ProtectedDeletedCopy];
10542
10543 test_call_a_as![ffi::BaseProtectedDeletedCopyNoDefault, ffi::ProtectedDeletedCopyNoDefault];
10544
10545 test_constructible![ffi::BaseProtectedMoveDeletedCopy];
10546 test_make_unique![ffi::BaseProtectedMoveDeletedCopy];
10547 test_movable![ffi::BaseProtectedMoveDeletedCopy];
10548 test_call_a_as![ffi::BaseProtectedMoveDeletedCopy, ffi::ProtectedMoveDeletedCopy];
10549
10550 test_constructible![ffi::BaseProtectedDeletedMove];
10551 test_make_unique![ffi::BaseProtectedDeletedMove];
10552 test_call_a_as![ffi::BaseProtectedDeletedMove, ffi::ProtectedDeletedMove];
10553
10554 test_call_a_as![ffi::BaseProtectedDeletedDestructor, ffi::ProtectedDeletedDestructor];
10555
10556 test_constructible![ffi::BaseProtectedDestructor];
10557 test_make_unique![ffi::BaseProtectedDestructor];
10558 test_copyable![ffi::BaseProtectedDestructor];
10559 test_call_a_as![ffi::BaseProtectedDestructor, ffi::ProtectedDestructor];
10560
10561 test_call_a![ffi::MemberProtectedDeleted];
10562
10563 test_copyable![ffi::MemberProtectedDeletedDefault];
10564 test_movable![ffi::MemberProtectedDeletedDefault];
10565 test_call_a![ffi::MemberProtectedDeletedDefault];
10566
10567 test_constructible![ffi::MemberProtectedDeletedCopy];
10568 test_make_unique![ffi::MemberProtectedDeletedCopy];
10569 test_call_a![ffi::MemberProtectedDeletedCopy];
10570
10571 test_call_a![ffi::MemberProtectedDeletedCopyNoDefault];
10572
10573 test_constructible![ffi::MemberProtectedMoveDeletedCopy];
10574 test_make_unique![ffi::MemberProtectedMoveDeletedCopy];
10575 test_call_a![ffi::MemberProtectedMoveDeletedCopy];
10576
10577 test_constructible![ffi::MemberProtectedDeletedMove];
10578 test_make_unique![ffi::MemberProtectedDeletedMove];
10579 test_call_a![ffi::MemberProtectedDeletedMove];
10580
10581 test_call_a![ffi::MemberProtectedDeletedDestructor];
10582
10583 test_call_a![ffi::MemberProtectedDestructor];
10584
10585 test_call_a_as![ffi::BaseMemberProtectedDeleted, ffi::MemberProtectedDeleted];
10586
10587 test_copyable![ffi::BaseMemberProtectedDeletedDefault];
10588 test_movable![ffi::BaseMemberProtectedDeletedDefault];
10589 test_call_a_as![ffi::BaseMemberProtectedDeletedDefault, ffi::MemberProtectedDeletedDefault];
10590
10591 test_constructible![ffi::BaseMemberProtectedDeletedCopy];
10592 test_make_unique![ffi::BaseMemberProtectedDeletedCopy];
10593 test_call_a_as![ffi::BaseMemberProtectedDeletedCopy, ffi::MemberProtectedDeletedCopy];
10594
10595 test_call_a_as![ffi::BaseMemberProtectedDeletedCopyNoDefault, ffi::MemberProtectedDeletedCopyNoDefault];
10596
10597 test_constructible![ffi::BaseMemberProtectedMoveDeletedCopy];
10598 test_make_unique![ffi::BaseMemberProtectedMoveDeletedCopy];
10599 test_call_a_as![ffi::BaseMemberProtectedMoveDeletedCopy, ffi::MemberProtectedMoveDeletedCopy];
10600
10601 test_constructible![ffi::BaseMemberProtectedDeletedMove];
10602 test_make_unique![ffi::BaseMemberProtectedDeletedMove];
10603 test_call_a_as![ffi::BaseMemberProtectedDeletedMove, ffi::MemberProtectedDeletedMove];
10604
10605 test_call_a_as![ffi::BaseMemberProtectedDeletedDestructor, ffi::MemberProtectedDeletedDestructor];
10606
10607 test_call_a_as![ffi::BaseMemberProtectedDestructor, ffi::MemberProtectedDestructor];
10608
10609 test_call_a_as![ffi::BasePrivateDeleted, ffi::PrivateDeleted];
10610
10611 test_copyable![ffi::BasePrivateDeletedDefault];
10612 test_movable![ffi::BasePrivateDeletedDefault];
10613 test_call_a_as![ffi::BasePrivateDeletedDefault, ffi::PrivateDeletedDefault];
10614
10615 test_constructible![ffi::BasePrivateDeletedCopy];
10616 test_make_unique![ffi::BasePrivateDeletedCopy];
10617 test_call_a_as![ffi::BasePrivateDeletedCopy, ffi::PrivateDeletedCopy];
10618
10619 test_call_a_as![ffi::BasePrivateDeletedCopyNoDefault, ffi::PrivateDeletedCopyNoDefault];
10620
10621 test_constructible![ffi::BasePrivateMoveDeletedCopy];
10622 test_make_unique![ffi::BasePrivateMoveDeletedCopy];
10623 test_call_a_as![ffi::BasePrivateMoveDeletedCopy, ffi::PrivateMoveDeletedCopy];
10624
10625 test_constructible![ffi::BasePrivateDeletedMove];
10626 test_make_unique![ffi::BasePrivateDeletedMove];
10627 test_call_a_as![ffi::BasePrivateDeletedMove, ffi::PrivateDeletedMove];
10628
10629 test_call_a_as![ffi::BasePrivateDeletedDestructor, ffi::PrivateDeletedDestructor];
10630
10631 test_call_a_as![ffi::BasePrivateDestructor, ffi::PrivateDestructor];
10632
10633 test_call_a![ffi::MemberPrivateDeleted];
10634
10635 test_copyable![ffi::MemberPrivateDeletedDefault];
10636 test_movable![ffi::MemberPrivateDeletedDefault];
10637 test_call_a![ffi::MemberPrivateDeletedDefault];
10638
10639 test_constructible![ffi::MemberPrivateDeletedCopy];
10640 test_make_unique![ffi::MemberPrivateDeletedCopy];
10641 test_call_a![ffi::MemberPrivateDeletedCopy];
10642
10643 test_call_a![ffi::MemberPrivateDeletedCopyNoDefault];
10644
10645 test_constructible![ffi::MemberPrivateMoveDeletedCopy];
10646 test_make_unique![ffi::MemberPrivateMoveDeletedCopy];
10647 test_call_a![ffi::MemberPrivateMoveDeletedCopy];
10648
10649 test_constructible![ffi::MemberPrivateDeletedMove];
10650 test_make_unique![ffi::MemberPrivateDeletedMove];
10651 test_call_a![ffi::MemberPrivateDeletedMove];
10652
10653 test_call_a![ffi::MemberPrivateDeletedDestructor];
10654
10655 test_call_a![ffi::MemberPrivateDestructor];
10656
10657 test_call_a_as![ffi::BaseMemberPrivateDeleted, ffi::MemberPrivateDeleted];
10658
10659 test_copyable![ffi::BaseMemberPrivateDeletedDefault];
10660 test_movable![ffi::BaseMemberPrivateDeletedDefault];
10661 test_call_a_as![ffi::BaseMemberPrivateDeletedDefault, ffi::MemberPrivateDeletedDefault];
10662
10663 test_constructible![ffi::BaseMemberPrivateDeletedCopy];
10664 test_make_unique![ffi::BaseMemberPrivateDeletedCopy];
10665 test_call_a_as![ffi::BaseMemberPrivateDeletedCopy, ffi::MemberPrivateDeletedCopy];
10666
10667 test_call_a_as![ffi::BaseMemberPrivateDeletedCopyNoDefault, ffi::MemberPrivateDeletedCopyNoDefault];
10668
10669 test_constructible![ffi::BaseMemberPrivateMoveDeletedCopy];
10670 test_make_unique![ffi::BaseMemberPrivateMoveDeletedCopy];
10671 test_call_a_as![ffi::BaseMemberPrivateMoveDeletedCopy, ffi::MemberPrivateMoveDeletedCopy];
10672
10673 test_constructible![ffi::BaseMemberPrivateDeletedMove];
10674 test_make_unique![ffi::BaseMemberPrivateDeletedMove];
10675 test_call_a_as![ffi::BaseMemberPrivateDeletedMove, ffi::MemberPrivateDeletedMove];
10676
10677 test_call_a_as![ffi::BaseMemberPrivateDeletedDestructor, ffi::MemberPrivateDeletedDestructor];
10678
10679 test_call_a_as![ffi::BaseMemberPrivateDestructor, ffi::MemberPrivateDestructor];
10680 };
10681 run_test(
10682 cxx,
10683 hdr,
10684 rs,
10685 &[
10686 "AllImplicitlyDefaulted",
10687 "PublicDeleted",
10688 "PublicDeletedDefault",
10689 "PublicDeletedCopy",
10690 "PublicDeletedCopyNoDefault",
10691 "PublicMoveDeletedCopy",
10692 "PublicDeletedMove",
10693 "PublicDeletedDestructor",
10694 "PublicDestructor",
10695 "ProtectedDeleted",
10696 "ProtectedDeletedDefault",
10697 "ProtectedDeletedCopy",
10698 "ProtectedDeletedCopyNoDefault",
10699 "ProtectedMoveDeletedCopy",
10700 "ProtectedDeletedMove",
10701 "ProtectedDeletedDestructor",
10702 "ProtectedDestructor",
10703 "PrivateDeleted",
10704 "PrivateDeletedDefault",
10705 "PrivateDeletedCopy",
10706 "PrivateDeletedCopyNoDefault",
10707 "PrivateMoveDeletedCopy",
10708 "PrivateDeletedMove",
10709 "PrivateDeletedDestructor",
10710 "PrivateDestructor",
10711 "NonConstCopy",
10712 "TwoCopy",
10713 "MemberPointerDeleted",
10714 "MemberConstPointerDeleted",
10715 // TODO: Handle top-level const on C++ members correctly.
10716 //"MemberConst",
10717 "MemberReferenceDeleted",
10718 "MemberConstReferenceDeleted",
10719 "MemberReference",
10720 "MemberConstReference",
10721 "MemberRvalueReferenceDeleted",
10722 "MemberRvalueReference",
10723 "BasePublicDeleted",
10724 "BasePublicDeletedDefault",
10725 "BasePublicDeletedCopy",
10726 "BasePublicDeletedCopyNoDefault",
10727 "BasePublicMoveDeletedCopy",
10728 "BasePublicDeletedMove",
10729 "BasePublicDeletedDestructor",
10730 "BasePublicDestructor",
10731 "MemberPublicDeleted",
10732 "MemberPublicDeletedDefault",
10733 "MemberPublicDeletedCopy",
10734 "MemberPublicDeletedCopyNoDefault",
10735 "MemberPublicMoveDeletedCopy",
10736 "MemberPublicDeletedMove",
10737 "MemberPublicDeletedDestructor",
10738 "MemberPublicDestructor",
10739 "BaseMemberPublicDeleted",
10740 "BaseMemberPublicDeletedDefault",
10741 "BaseMemberPublicDeletedCopy",
10742 "BaseMemberPublicDeletedCopyNoDefault",
10743 "BaseMemberPublicMoveDeletedCopy",
10744 "BaseMemberPublicDeletedMove",
10745 "BaseMemberPublicDeletedDestructor",
10746 "BaseMemberPublicDestructor",
10747 "BaseProtectedDeleted",
10748 "BaseProtectedDeletedDefault",
10749 "BaseProtectedDeletedCopy",
10750 "BaseProtectedDeletedCopyNoDefault",
10751 "BaseProtectedMoveDeletedCopy",
10752 "BaseProtectedDeletedMove",
10753 "BaseProtectedDeletedDestructor",
10754 "BaseProtectedDestructor",
10755 "MemberProtectedDeleted",
10756 "MemberProtectedDeletedDefault",
10757 "MemberProtectedDeletedCopy",
10758 "MemberProtectedDeletedCopyNoDefault",
10759 "MemberProtectedMoveDeletedCopy",
10760 "MemberProtectedDeletedMove",
10761 "MemberProtectedDeletedDestructor",
10762 "MemberProtectedDestructor",
10763 "BaseMemberProtectedDeleted",
10764 "BaseMemberProtectedDeletedDefault",
10765 "BaseMemberProtectedDeletedCopy",
10766 "BaseMemberProtectedDeletedCopyNoDefault",
10767 "BaseMemberProtectedMoveDeletedCopy",
10768 "BaseMemberProtectedDeletedMove",
10769 "BaseMemberProtectedDeletedDestructor",
10770 "BaseMemberProtectedDestructor",
10771 "BasePrivateDeleted",
10772 "BasePrivateDeletedDefault",
10773 "BasePrivateDeletedCopy",
10774 "BasePrivateDeletedCopyNoDefault",
10775 "BasePrivateMoveDeletedCopy",
10776 "BasePrivateDeletedMove",
10777 "BasePrivateDeletedDestructor",
10778 "BasePrivateDestructor",
10779 "MemberPrivateDeleted",
10780 "MemberPrivateDeletedDefault",
10781 "MemberPrivateDeletedCopy",
10782 "MemberPrivateDeletedCopyNoDefault",
10783 "MemberPrivateMoveDeletedCopy",
10784 "MemberPrivateDeletedMove",
10785 "MemberPrivateDeletedDestructor",
10786 "MemberPrivateDestructor",
10787 "BaseMemberPrivateDeleted",
10788 "BaseMemberPrivateDeletedDefault",
10789 "BaseMemberPrivateDeletedCopy",
10790 "BaseMemberPrivateDeletedCopyNoDefault",
10791 "BaseMemberPrivateMoveDeletedCopy",
10792 "BaseMemberPrivateDeletedMove",
10793 "BaseMemberPrivateDeletedDestructor",
10794 "BaseMemberPrivateDestructor",
10795 ],
10796 &[],
10797 );
10798}
10799
10800#[test]
10801/// Test that destructors hidden in various places are correctly called.
10802///
10803/// Some types are excluded because we know they behave poorly due to
10804/// https://github.com/google/autocxx/issues/829.
10805fn test_tricky_destructors() {
10806 let cxx = "";
10807 let hdr = indoc! {"
10808 #include <stdio.h>
10809 #include <stdlib.h>
10810 // A simple type to let Rust verify the destructor is run.
10811 struct DestructorFlag {
10812 DestructorFlag() = default;
10813 DestructorFlag(const DestructorFlag&) = default;
10814 DestructorFlag(DestructorFlag&&) = default;
10815
10816 ~DestructorFlag() {
10817 if (!flag) return;
10818 if (*flag) {
10819 fprintf(stderr, \"DestructorFlag is already set\\n\");
10820 abort();
10821 }
10822 *flag = true;
10823 // Note we deliberately do NOT clear the value of `flag`, to catch Rust calling
10824 // this destructor twice.
10825 }
10826
10827 bool *flag = nullptr;
10828 };
10829
10830 struct ImplicitlyDefaulted {
10831 DestructorFlag flag;
10832
10833 void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
10834 };
10835 struct ExplicitlyDefaulted {
10836 ExplicitlyDefaulted() = default;
10837 ~ExplicitlyDefaulted() = default;
10838
10839 DestructorFlag flag;
10840
10841 void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
10842 };
10843 struct Explicit {
10844 Explicit() = default;
10845 ~Explicit() {}
10846
10847 DestructorFlag flag;
10848
10849 void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
10850 };
10851
10852 struct BaseImplicitlyDefaulted : public ImplicitlyDefaulted {
10853 void set_flag(bool *flag_pointer) { ImplicitlyDefaulted::set_flag(flag_pointer); }
10854 };
10855 struct BaseExplicitlyDefaulted : public ExplicitlyDefaulted {
10856 void set_flag(bool *flag_pointer) { ExplicitlyDefaulted::set_flag(flag_pointer); }
10857 };
10858 struct BaseExplicit : public Explicit {
10859 void set_flag(bool *flag_pointer) { Explicit::set_flag(flag_pointer); }
10860 };
10861
10862 struct MemberImplicitlyDefaulted {
10863 ImplicitlyDefaulted member;
10864
10865 void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
10866 };
10867 struct MemberExplicitlyDefaulted {
10868 ExplicitlyDefaulted member;
10869
10870 void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
10871 };
10872 struct MemberExplicit {
10873 Explicit member;
10874
10875 void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
10876 };
10877
10878 struct BaseMemberImplicitlyDefaulted : public MemberImplicitlyDefaulted {
10879 void set_flag(bool *flag_pointer) { MemberImplicitlyDefaulted::set_flag(flag_pointer); }
10880 };
10881 struct BaseMemberExplicitlyDefaulted : public MemberExplicitlyDefaulted {
10882 void set_flag(bool *flag_pointer) { MemberExplicitlyDefaulted::set_flag(flag_pointer); }
10883 };
10884 struct BaseMemberExplicit : public MemberExplicit {
10885 void set_flag(bool *flag_pointer) { MemberExplicit::set_flag(flag_pointer); }
10886 };
10887 "};
10888 let rs = quote! {
10889 macro_rules! test_type {
10890 [$t:ty] => {
10891 let mut unique_t = <$t>::new().within_unique_ptr();
10892 let mut destructor_flag = false;
10893 unsafe {
10894 unique_t.pin_mut().set_flag(&mut destructor_flag);
10895 }
10896 std::mem::drop(unique_t);
10897 assert!(destructor_flag, "Destructor did not run with make_unique for {}", quote::quote!{$t});
10898
10899 moveit! {
10900 let mut moveit_t = <$t>::new();
10901 }
10902 let mut destructor_flag = false;
10903 unsafe {
10904 moveit_t.as_mut().set_flag(&mut destructor_flag);
10905 }
10906 std::mem::drop(moveit_t);
10907 assert!(destructor_flag, "Destructor did not run with moveit for {}", quote::quote!{$t});
10908 }
10909 }
10910
10911 test_type![ffi::ImplicitlyDefaulted];
10912 test_type![ffi::ExplicitlyDefaulted];
10913 test_type![ffi::Explicit];
10914 test_type![ffi::BaseImplicitlyDefaulted];
10915 test_type![ffi::BaseExplicitlyDefaulted];
10916 test_type![ffi::BaseExplicit];
10917 test_type![ffi::MemberImplicitlyDefaulted];
10918 test_type![ffi::MemberExplicitlyDefaulted];
10919 test_type![ffi::MemberExplicit];
10920 test_type![ffi::BaseMemberImplicitlyDefaulted];
10921 test_type![ffi::BaseMemberExplicitlyDefaulted];
10922 test_type![ffi::BaseMemberExplicit];
10923 };
10924 run_test(
10925 cxx,
10926 hdr,
10927 rs,
10928 &[
10929 "DestructorFlag",
10930 "ImplicitlyDefaulted",
10931 "ExplicitlyDefaulted",
10932 "Explicit",
10933 "BaseImplicitlyDefaulted",
10934 "BaseExplicitlyDefaulted",
10935 "BaseExplicit",
10936 "MemberImplicitlyDefaulted",
10937 "MemberExplicitlyDefaulted",
10938 "MemberExplicit",
10939 "BaseMemberImplicitlyDefaulted",
10940 "BaseMemberExplicitlyDefaulted",
10941 "BaseMemberExplicit",
10942 ],
10943 &[],
10944 );
10945}
10946
10947#[test]
10948fn test_concretize() {
10949 let hdr = indoc! {"
10950 #include <string>
10951 template<typename CONTENTS>
10952 class Container {
10953 private:
10954 CONTENTS* contents;
10955 };
10956 struct B {
10957 std::string a;
10958 };
10959 "};
10960 run_test_ex(
10961 "",
10962 hdr,
10963 quote! {},
10964 quote! {
10965 concrete!("Container<B>", ContainerOfB)
10966 generate!("B")
10967 },
10968 None,
10969 None,
10970 Some(quote! {
10971 struct HasAField {
10972 contents: ffi::ContainerOfB
10973 }
10974 }),
10975 );
10976}
10977
10978#[test]
10979fn test_doc_comments_survive() {
10980 let hdr = indoc! {"
10981 #include <cstdint>
10982 /// Struct line A
10983 /// Struct line B
10984 struct A { int b; };
10985
10986 /// POD struct line A
10987 /// POD struct line B
10988 struct B {
10989 /// Field line A
10990 /// Field line B
10991 uint32_t b;
10992
10993 /// Method line A
10994 /// Method line B
10995 void foo() {}
10996 };
10997
10998 /// Enum line A
10999 /// Enum line B
11000 enum C {
11001 /// Variant line A
11002 /// Variant line B
11003 VARIANT,
11004 };
11005
11006 /// Function line A
11007 /// Function line B
11008 inline void D() {}
11009 "};
11010
11011 let expected_messages = [
11012 "Struct",
11013 "POD struct",
11014 "Field",
11015 "Method",
11016 "Enum",
11017 "Variant",
11018 "Function",
11019 ]
11020 .into_iter()
11021 .flat_map(|l| [format!("{} line A", l), format!("{} line B", l)])
11022 .collect_vec();
11023
11024 run_test_ex(
11025 "",
11026 hdr,
11027 quote! {},
11028 directives_from_lists(&["A", "C", "D"], &["B"], None),
11029 None,
11030 Some(make_string_finder(expected_messages)),
11031 None,
11032 );
11033}
11034
11035#[test]
11036fn optional_param_in_copy_constructor() {
11037 let hdr = indoc! {"
11038 struct A {
11039 A(const A &other, bool optional_arg = false);
11040 };
11041 "};
11042 run_test("", hdr, quote! {}, &["A"], &[]);
11043}
11044
11045#[test]
11046fn param_in_copy_constructor() {
11047 let hdr = indoc! {"
11048 struct A {
11049 A(const A &other, bool arg);
11050 };
11051 "};
11052 run_test("", hdr, quote! {}, &["A"], &[]);
11053}
11054
11055#[test]
11056fn test_variadic() {
11057 let hdr = indoc! {"
11058 class SomeClass{
11059 public:
11060 inline void foo(int, ... ) {}
11061 };
11062 "};
11063 run_test("", hdr, quote! {}, &["SomeClass"], &[]);
11064}
11065
11066#[test]
11067fn test_typedef_to_enum() {
11068 let hdr = indoc! {"
11069 enum b {};
11070 class c {
11071 public:
11072 typedef b d;
11073 d e();
11074 };
11075 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011076 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -070011077}
11078
11079#[test]
11080fn test_typedef_to_ns_enum() {
11081 let hdr = indoc! {"
11082 namespace a {
11083 enum b {};
11084 class c {
11085 public:
11086 typedef b d;
11087 d e();
11088 };
11089 } // namespace
11090 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011091 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -070011092}
11093
11094#[test]
11095fn test_typedef_unsupported_type_pub() {
11096 let hdr = indoc! {"
11097 #include <set>
11098 namespace NS{
11099 class cls{
11100 public:
11101 typedef std::set<int> InnerType;
11102 };
11103 }
11104 "};
11105
11106 run_test_ex(
11107 "",
11108 hdr,
11109 quote! {},
11110 quote! { generate_ns!("NS") },
11111 None,
11112 None,
11113 None,
11114 );
11115}
11116
11117#[test]
11118fn test_typedef_unsupported_type_pri() {
11119 let hdr = indoc! {"
11120 #include <set>
11121 namespace NS{
11122 class cls{
11123 private:
11124 typedef std::set<int> InnerType;
11125 };
11126 }
11127 "};
11128
11129 run_test_ex(
11130 "",
11131 hdr,
11132 quote! {},
11133 quote! { generate_ns!("NS") },
11134 None,
11135 None,
11136 None,
11137 );
11138}
11139
11140#[test]
11141fn test_array_trouble1() {
11142 let hdr = indoc! {"
11143 namespace a {
11144 template <typename b> struct array {
11145 typedef b c;
11146 typedef c d;
11147 };
11148 } // namespace a
11149 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011150 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -070011151}
11152
11153#[test]
11154fn test_array_trouble2() {
11155 let hdr = indoc! {"
11156 template <typename b> struct array {
11157 typedef b c;
11158 typedef c d;
11159 };
11160 "};
11161 run_test("", hdr, quote! {}, &["array_d"], &[]);
11162}
11163
11164#[test]
11165fn test_issue_1087a() {
11166 let hdr = indoc! {"
11167 template <typename _CharT> class a {
11168 _CharT b;
11169 };
11170 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011171 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -070011172}
11173
11174#[test]
11175fn test_issue_1087b() {
11176 let hdr = indoc! {"
11177 template <typename _CharT> class a {
11178 typedef _CharT b;
11179 b c;
11180 };
11181 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011182 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -070011183}
11184
11185#[test]
11186fn test_issue_1087c() {
11187 let hdr = indoc! {"
11188 namespace {
11189 namespace {
11190 template <typename _CharT> class a {
11191 typedef _CharT b;
11192 b c;
11193 };
11194 }
11195 }
11196 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011197 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -070011198}
11199
11200#[test]
11201fn test_issue_1089() {
11202 let hdr = indoc! {"
11203 namespace a {
11204 template <typename c, c> struct d;
11205 template <bool, typename, typename> struct ab;
11206 inline namespace {
11207 namespace ac {
11208 template <typename, template <typename> class, typename> struct bh;
11209 template <template <typename> class ad, typename... bi>
11210 using bj = bh<void, ad, bi...>;
11211 template <typename ad> using bk = typename ad::b;
11212 template <typename> struct bm;
11213 } // namespace ac
11214 template <typename ad>
11215 struct b : ab<ac::bj<ac::bk, ad>::e, ac::bm<ad>, d<bool, ad ::e>>::bg {};
11216 } // namespace
11217 } // namespace a
11218 "};
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011219 run_generate_all_test(hdr);
11220}
11221
11222/// The problem here is that 'g' doesn't get annotated with
11223/// the unused_template semantic attribute.
11224/// This seems to be because both g and f have template
11225/// parameters, so they're all "used", but effectively cancel
11226/// out and thus bindgen generates
11227/// pub type g = root::b::f;
11228/// So, what we should do here is spot any typedef depending
11229/// on a template which takes template args, and reject that too.
11230/// Probably.
11231#[test]
11232#[ignore] // https://github.com/google/autocxx/pull/1094
11233fn test_issue_1094() {
11234 let hdr = indoc! {"
11235 namespace {
11236 typedef int a;
11237 }
11238 namespace b {
11239 template <typename> struct c;
11240 template <typename d, d e> using f = __make_integer_seq<c, d, e>;
11241 template <a e> using g = f<a, e>;
11242 } // namespace b
11243 "};
11244 run_generate_all_test(hdr);
11245}
11246
11247#[test]
11248fn test_issue_1096a() {
11249 let hdr = indoc! {"
11250 namespace a {
11251 class b {
11252 class c;
11253 };
11254 } // namespace a
11255 "};
11256 run_generate_all_test(hdr);
11257}
11258
11259#[test]
11260fn test_issue_1096b() {
11261 let hdr = indoc! {"
11262 namespace a {
11263 class b {
11264 public:
11265 class c;
11266 };
11267 } // namespace a
11268 "};
11269 run_generate_all_test(hdr);
11270}
11271
11272#[test]
11273fn test_issue_1096c() {
11274 let hdr = indoc! {"
11275 namespace a {
11276 class b {
11277 public:
11278 class c {
11279 public:
11280 int d;
11281 };
11282 };
11283 } // namespace a
11284 "};
11285 run_generate_all_test(hdr);
11286}
11287
11288#[test]
11289fn test_issue_1096d() {
11290 let hdr = indoc! {"
11291 namespace a {
11292 class b {
11293 private:
11294 class c {
11295 public:
11296 int d;
11297 };
11298 };
11299 } // namespace a
11300 "};
11301 run_generate_all_test(hdr);
11302}
11303
11304#[test]
11305fn test_issue_1096e() {
11306 let hdr = indoc! {"
11307 namespace a {
11308 class b {
11309 private:
11310 enum c {
11311 D,
11312 };
11313 };
11314 } // namespace a
11315 "};
11316 run_generate_all_test(hdr);
11317}
11318
11319/// Unclear why minimization resulted in this particular test case.
11320#[test]
11321#[ignore] // https://github.com/google/autocxx/pull/1097
11322fn test_issue_1097() {
11323 let hdr = indoc! {"
11324 namespace rust {
11325 inline namespace a {
11326 class Str {
11327 public:
11328 ~Str();
11329 };
11330 } // namespace a
11331 } // namespace rust
11332 "};
11333 run_generate_all_test(hdr);
11334}
11335
11336#[test]
11337fn test_issue_1098a() {
11338 let hdr = indoc! {"
11339 namespace {
11340 namespace {
11341 template <typename _CharT> class a {
11342 typedef _CharT b;
11343 b c;
11344 };
11345 template <typename _CharT> class d : a<_CharT> {};
11346 } // namespace
11347 } // namespace
11348 "};
11349 run_generate_all_test(hdr);
11350}
11351
11352/// Need to spot structs like this:
11353/// pub struct d<_CharT> {
11354/// _base: root::a<_CharT>,
11355/// }
11356/// and not create concrete types where the inner type is something from
11357/// the outer context.
11358#[test]
11359fn test_issue_1098b() {
11360 let hdr = indoc! {"
11361 template <typename _CharT> class a {
11362 typedef _CharT b;
11363 b c;
11364 };
11365 template <typename _CharT> class d : a<_CharT> {};
11366 "};
11367 run_generate_all_test(hdr);
11368}
11369
11370#[test]
11371fn test_issue_1098c() {
11372 let hdr = indoc! {"
11373 namespace {
11374 namespace {
11375 struct A {
11376 int a;
11377 };
11378 typedef A B;
11379 } // namespace
11380 } // namespace
11381 inline void take_b(const B&) {}
11382 "};
11383 run_generate_all_test(hdr);
Brian Silverman4e662aa2022-05-11 23:10:19 -070011384}
11385
11386#[test]
11387fn test_pass_rust_str_and_return_struct() {
11388 let cxx = indoc! {"
11389 A take_str_return_struct(rust::Str) {
11390 A a;
11391 return a;
11392 }
11393 "};
11394 let hdr = indoc! {"
11395 #include <cxx.h>
11396 struct A {};
11397 A take_str_return_struct(rust::Str);
11398 "};
11399 let rs = quote! {
11400 ffi::take_str_return_struct("hi");
11401 };
11402 run_test(cxx, hdr, rs, &["take_str_return_struct"], &[]);
11403}
11404
11405#[test]
11406fn test_issue_1065a() {
11407 let hdr = indoc! {"
11408 #include <memory>
11409 #include <vector>
11410
11411 template <typename at> class au {
11412 std::unique_ptr<at> aw;
11413 };
11414 class bb;
11415 using bc = au<bb>;
11416 class RenderFrameHost {
11417 public:
11418 virtual std::vector<bc> &bd() = 0;
11419 virtual ~RenderFrameHost() {}
11420 };
11421 "};
11422 let rs = quote! {};
11423 run_test("", hdr, rs, &["RenderFrameHost"], &[]);
11424}
11425
11426#[test]
11427fn test_issue_1065b() {
11428 let hdr = indoc! {"
11429 #include <memory>
11430 #include <vector>
11431
11432 class bb;
11433 using bc = std::unique_ptr<bb>;
11434 class RenderFrameHost {
11435 public:
11436 virtual std::vector<bc> &bd() = 0;
11437 virtual ~RenderFrameHost() {}
11438 };
11439 "};
11440 let rs = quote! {};
11441 run_test("", hdr, rs, &["RenderFrameHost"], &[]);
11442}
11443
Brian Silvermanf3ec38b2022-07-06 20:43:36 -070011444#[test]
11445fn test_issue_1081() {
11446 let hdr = indoc! {"
11447 namespace libtorrent {
11448 char version;
11449 }
11450 namespace libtorrent {
11451 struct session;
11452 }
11453 "};
11454 let rs = quote! {};
11455 run_test("", hdr, rs, &["libtorrent::session"], &[]);
11456}
11457
11458#[test]
11459#[ignore] // This test passes under all normal builds. However
11460 // it triggers a stack use-after-return in older versions of
11461 // libclang which is only detected under ASAN (obviously it
11462 // sometimes causes crashes the rest of the time).
11463 // This UaR does not occur when the same code is processed
11464 // with a HEAD version of clang itself as of June 2022. This
11465 // may mean that the UaR has been fixed in later versions of
11466 // the clang code, or that it only occurs when the code is used
11467 // in a libclang context (not a plain clang compilation context).
11468 // If the problem recurs, we should work out which of these is
11469 // the case.
11470fn test_issue_1125() {
11471 let hdr = indoc! {"
11472 namespace {
11473 namespace {
11474 template <class a> class b {
11475 typedef a c;
11476 struct {
11477 c : sizeof(c);
11478 };
11479 };
11480 } // namespace
11481 } // namespace
11482 "};
11483 run_test_ex(
11484 "",
11485 hdr,
11486 quote! {},
11487 quote! {
11488 generate_all!()
11489 },
11490 make_cpp17_adder(),
11491 None,
11492 None,
11493 );
11494}
11495
Brian Silverman4e662aa2022-05-11 23:10:19 -070011496// Yet to test:
11497// - Ifdef
11498// - Out param pointers
11499// - ExcludeUtilities
11500// - Struct fields which are typedefs
11501// Negative tests:
11502// - Private methods
11503// - Private fields