blob: 2a3340a006923b70eb2457a5c46f192b23634fd2 [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::{
19 directives_from_lists, do_run_test, do_run_test_manual, run_test, run_test_ex,
20 run_test_expect_fail, run_test_expect_fail_ex, TestError,
21};
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 "};
3544
3545 let rs = quote! {};
3546
3547 run_test_ex(
3548 "",
3549 hdr,
3550 rs,
3551 quote! {
3552 generate_all!()
3553 },
3554 None,
3555 None,
3556 None,
3557 );
3558}
3559
3560#[test]
3561fn test_foreign_ns_func_arg_pod() {
3562 let hdr = indoc! {"
3563 #include <cstdint>
3564 #include <memory>
3565 namespace A {
3566 struct Bob {
3567 uint32_t a;
3568 };
3569 }
3570 namespace B {
3571 inline uint32_t daft(A::Bob a) { return a.a; }
3572 }
3573 "};
3574 let rs = quote! {
3575 let a = ffi::A::Bob { a: 12 };
3576 assert_eq!(ffi::B::daft(a), 12);
3577 };
3578 run_test("", hdr, rs, &["B::daft"], &["A::Bob"]);
3579}
3580
3581#[test]
3582fn test_foreign_ns_func_arg_nonpod() {
3583 let hdr = indoc! {"
3584 #include <cstdint>
3585 #include <memory>
3586 namespace A {
3587 struct Bob {
3588 uint32_t a;
3589 Bob(uint32_t _a) :a(_a) {}
3590 };
3591 }
3592 namespace B {
3593 inline uint32_t daft(A::Bob a) { return a.a; }
3594 }
3595 "};
3596 let rs = quote! {
3597 let a = ffi::A::Bob::new(12).within_unique_ptr();
3598 assert_eq!(ffi::B::daft(a), 12);
3599 };
3600 run_test("", hdr, rs, &["B::daft", "A::Bob"], &[]);
3601}
3602
3603#[test]
3604fn test_foreign_ns_meth_arg_pod() {
3605 let hdr = indoc! {"
3606 #include <cstdint>
3607 #include <memory>
3608 namespace A {
3609 struct Bob {
3610 uint32_t a;
3611 };
3612 }
3613 namespace B {
3614 struct C {
3615 uint32_t a;
3616 uint32_t daft(A::Bob a) const { return a.a; }
3617 };
3618 }
3619 "};
3620 let rs = quote! {
3621 let a = ffi::A::Bob { a: 12 };
3622 let b = ffi::B::C { a: 12 };
3623 assert_eq!(b.daft(a), 12);
3624 };
3625 run_test("", hdr, rs, &[], &["A::Bob", "B::C"]);
3626}
3627
3628#[test]
3629fn test_foreign_ns_meth_arg_nonpod() {
3630 let hdr = indoc! {"
3631 #include <cstdint>
3632 #include <memory>
3633 namespace A {
3634 struct Bob {
3635 uint32_t a;
3636 Bob(uint32_t _a) :a(_a) {}
3637 };
3638 }
3639 namespace B {
3640 struct C {
3641 uint32_t a;
3642 uint32_t daft(A::Bob a) const { return a.a; }
3643 };
3644 }
3645 "};
3646 let rs = quote! {
3647 let a = ffi::A::Bob::new(12).within_unique_ptr();
3648 let b = ffi::B::C { a: 12 };
3649 assert_eq!(b.daft(a), 12);
3650 };
3651 run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
3652}
3653
3654#[test]
3655fn test_foreign_ns_cons_arg_pod() {
3656 let hdr = indoc! {"
3657 #include <cstdint>
3658 #include <memory>
3659 namespace A {
3660 struct Bob {
3661 uint32_t a;
3662 };
3663 }
3664 namespace B {
3665 struct C {
3666 uint32_t a;
3667 C(const A::Bob& input) : a(input.a) {}
3668 };
3669 }
3670 "};
3671 let rs = quote! {
3672 let a = ffi::A::Bob { a: 12 };
3673 let b = ffi::B::C::new(&a).within_unique_ptr();
3674 assert_eq!(b.as_ref().unwrap().a, 12);
3675 };
3676 run_test("", hdr, rs, &[], &["B::C", "A::Bob"]);
3677}
3678
3679#[test]
3680fn test_foreign_ns_cons_arg_nonpod() {
3681 let hdr = indoc! {"
3682 #include <cstdint>
3683 #include <memory>
3684 namespace A {
3685 struct Bob {
3686 Bob(uint32_t _a) :a(_a) {}
3687 uint32_t a;
3688 };
3689 }
3690 namespace B {
3691 struct C {
3692 uint32_t a;
3693 C(const A::Bob& input) : a(input.a) {}
3694 };
3695 }
3696 "};
3697 let rs = quote! {
3698 let a = ffi::A::Bob::new(12).within_unique_ptr();
3699 let b = ffi::B::C::new(&a).within_unique_ptr();
3700 assert_eq!(b.as_ref().unwrap().a, 12);
3701 };
3702 run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
3703}
3704
3705#[test]
3706fn test_foreign_ns_func_ret_pod() {
3707 let hdr = indoc! {"
3708 #include <cstdint>
3709 #include <memory>
3710 namespace A {
3711 struct Bob {
3712 uint32_t a;
3713 };
3714 }
3715 namespace B {
3716 inline A::Bob daft() { A::Bob bob; bob.a = 12; return bob; }
3717 }
3718 "};
3719 let rs = quote! {
3720 assert_eq!(ffi::B::daft().a, 12);
3721 };
3722 run_test("", hdr, rs, &["B::daft"], &["A::Bob"]);
3723}
3724
3725#[test]
3726fn test_foreign_ns_func_ret_nonpod() {
3727 let hdr = indoc! {"
3728 #include <cstdint>
3729 #include <memory>
3730 namespace A {
3731 struct Bob {
3732 uint32_t a;
3733 };
3734 }
3735 namespace B {
3736 inline A::Bob daft() { A::Bob bob; bob.a = 12; return bob; }
3737 }
3738 "};
3739 let rs = quote! {
3740 ffi::B::daft().within_box().as_ref();
3741 };
3742 run_test("", hdr, rs, &["B::daft", "A::Bob"], &[]);
3743}
3744
3745#[test]
3746fn test_foreign_ns_meth_ret_pod() {
3747 let hdr = indoc! {"
3748 #include <cstdint>
3749 #include <memory>
3750 namespace A {
3751 struct Bob {
3752 uint32_t a;
3753 };
3754 }
3755 namespace B {
3756 struct C {
3757 uint32_t a;
3758 A::Bob daft() const { A::Bob bob; bob.a = 12; return bob; }
3759 };
3760 }
3761 "};
3762 let rs = quote! {
3763 let b = ffi::B::C { a: 12 };
3764 assert_eq!(b.daft().a, 12);
3765 };
3766 run_test("", hdr, rs, &[], &["A::Bob", "B::C"]);
3767}
3768
3769#[test]
3770fn test_foreign_ns_meth_ret_nonpod() {
3771 let hdr = indoc! {"
3772 #include <cstdint>
3773 #include <memory>
3774 namespace A {
3775 struct Bob {
3776 uint32_t a;
3777 };
3778 }
3779 namespace B {
3780 struct C {
3781 uint32_t a;
3782 A::Bob daft() const { A::Bob bob; bob.a = 12; return bob; }
3783 };
3784 }
3785 "};
3786 let rs = quote! {
3787 let b = ffi::B::C { a: 14 };
3788 b.daft().within_unique_ptr().as_ref().unwrap();
3789 };
3790 run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
3791}
3792
3793#[test]
3794fn test_root_ns_func_arg_pod() {
3795 let hdr = indoc! {"
3796 #include <cstdint>
3797 #include <memory>
3798 struct Bob {
3799 uint32_t a;
3800 };
3801 namespace B {
3802 inline uint32_t daft(Bob a) { return a.a; }
3803 }
3804 "};
3805 let rs = quote! {
3806 let a = ffi::Bob { a: 12 };
3807 assert_eq!(ffi::B::daft(a), 12);
3808 };
3809 run_test("", hdr, rs, &["B::daft"], &["Bob"]);
3810}
3811
3812#[test]
3813fn test_root_ns_func_arg_nonpod() {
3814 let hdr = indoc! {"
3815 #include <cstdint>
3816 #include <memory>
3817 struct Bob {
3818 uint32_t a;
3819 Bob(uint32_t _a) :a(_a) {}
3820 };
3821 namespace B {
3822 inline uint32_t daft(Bob a) { return a.a; }
3823 }
3824 "};
3825 let rs = quote! {
3826 let a = ffi::Bob::new(12).within_unique_ptr();
3827 assert_eq!(ffi::B::daft(a), 12);
3828 };
3829 run_test("", hdr, rs, &["B::daft", "Bob"], &[]);
3830}
3831
3832#[test]
3833fn test_root_ns_meth_arg_pod() {
3834 let hdr = indoc! {"
3835 #include <cstdint>
3836 #include <memory>
3837 struct Bob {
3838 uint32_t a;
3839 };
3840 namespace B {
3841 struct C {
3842 uint32_t a;
3843 uint32_t daft(Bob a) const { return a.a; }
3844 };
3845 }
3846 "};
3847 let rs = quote! {
3848 let a = ffi::Bob { a: 12 };
3849 let b = ffi::B::C { a: 12 };
3850 assert_eq!(b.daft(a), 12);
3851 };
3852 run_test("", hdr, rs, &[], &["Bob", "B::C"]);
3853}
3854
3855#[test]
3856fn test_root_ns_meth_arg_nonpod() {
3857 let hdr = indoc! {"
3858 #include <cstdint>
3859 #include <memory>
3860 struct Bob {
3861 uint32_t a;
3862 Bob(uint32_t _a) :a(_a) {}
3863 };
3864 namespace B {
3865 struct C {
3866 uint32_t a;
3867 uint32_t daft(Bob a) const { return a.a; }
3868 };
3869 }
3870 "};
3871 let rs = quote! {
3872 let a = ffi::Bob::new(12).within_unique_ptr();
3873 let b = ffi::B::C { a: 12 };
3874 assert_eq!(b.daft(a), 12);
3875 };
3876 run_test("", hdr, rs, &["Bob"], &["B::C"]);
3877}
3878
3879#[test]
3880fn test_root_ns_cons_arg_pod() {
3881 let hdr = indoc! {"
3882 #include <cstdint>
3883 #include <memory>
3884 struct Bob {
3885 uint32_t a;
3886 };
3887 namespace B {
3888 struct C {
3889 uint32_t a;
3890 C(const Bob& input) : a(input.a) {}
3891 };
3892 }
3893 "};
3894 let rs = quote! {
3895 let a = ffi::Bob { a: 12 };
3896 let b = ffi::B::C::new(&a).within_unique_ptr();
3897 assert_eq!(b.as_ref().unwrap().a, 12);
3898 };
3899 run_test("", hdr, rs, &[], &["B::C", "Bob"]);
3900}
3901
3902#[test]
3903fn test_root_ns_cons_arg_nonpod() {
3904 let hdr = indoc! {"
3905 #include <cstdint>
3906 #include <memory>
3907 struct Bob {
3908 Bob(uint32_t _a) :a(_a) {}
3909 uint32_t a;
3910 };
3911 namespace B {
3912 struct C {
3913 uint32_t a;
3914 C(const Bob& input) : a(input.a) {}
3915 };
3916 }
3917 "};
3918 let rs = quote! {
3919 let a = ffi::Bob::new(12).within_unique_ptr();
3920 let b = ffi::B::C::new(&a).within_unique_ptr();
3921 assert_eq!(b.as_ref().unwrap().a, 12);
3922 };
3923 run_test("", hdr, rs, &["Bob"], &["B::C"]);
3924}
3925
3926#[test]
3927fn test_root_ns_func_ret_pod() {
3928 let hdr = indoc! {"
3929 #include <cstdint>
3930 #include <memory>
3931 struct Bob {
3932 uint32_t a;
3933 };
3934 namespace B {
3935 inline Bob daft() { Bob bob; bob.a = 12; return bob; }
3936 }
3937 "};
3938 let rs = quote! {
3939 assert_eq!(ffi::B::daft().a, 12);
3940 };
3941 run_test("", hdr, rs, &["B::daft"], &["Bob"]);
3942}
3943
3944#[test]
3945fn test_root_ns_func_ret_nonpod() {
3946 let hdr = indoc! {"
3947 #include <cstdint>
3948 #include <memory>
3949 struct Bob {
3950 uint32_t a;
3951 };
3952 namespace B {
3953 inline Bob daft() { Bob bob; bob.a = 12; return bob; }
3954 }
3955 "};
3956 let rs = quote! {
3957 ffi::B::daft().within_unique_ptr().as_ref().unwrap();
3958 };
3959 run_test("", hdr, rs, &["B::daft", "Bob"], &[]);
3960}
3961
3962#[test]
3963fn test_root_ns_meth_ret_pod() {
3964 let hdr = indoc! {"
3965 #include <cstdint>
3966 #include <memory>
3967 struct Bob {
3968 uint32_t a;
3969 };
3970 namespace B {
3971 struct C {
3972 uint32_t a;
3973 Bob daft() const { Bob bob; bob.a = 12; return bob; }
3974 };
3975 }
3976 "};
3977 let rs = quote! {
3978 let b = ffi::B::C { a: 12 };
3979 assert_eq!(b.daft().a, 12);
3980 };
3981 run_test("", hdr, rs, &[], &["Bob", "B::C"]);
3982}
3983
3984#[test]
3985fn test_root_ns_meth_ret_nonpod() {
3986 let hdr = indoc! {"
3987 #include <cstdint>
3988 #include <memory>
3989 struct Bob {
3990 uint32_t a;
3991 };
3992 namespace B {
3993 struct C {
3994 uint32_t a;
3995 Bob daft() const { Bob bob; bob.a = 12; return bob; }
3996 };
3997 }
3998 "};
3999 let rs = quote! {
4000 let b = ffi::B::C { a: 12 };
4001 b.daft().within_unique_ptr().as_ref().unwrap();
4002 };
4003 run_test("", hdr, rs, &["Bob"], &["B::C"]);
4004}
4005
4006#[test]
4007fn test_forward_declaration() {
4008 let hdr = indoc! {"
4009 #include <cstdint>
4010 #include <memory>
4011 struct A;
4012 struct B {
4013 B() : a(0) {}
4014 uint32_t a;
4015 void daft(const A&) const {}
4016 static B daft3(const A&) { B b; return b; }
4017 A daft4();
4018 std::unique_ptr<A> daft5();
4019 const std::unique_ptr<A>& daft6();
4020 };
4021 A* get_a();
4022 void delete_a(A*);
4023 "};
4024 let cpp = indoc! {"
4025 struct A {
4026 A() : a(0) {}
4027 uint32_t a;
4028 };
4029 A* get_a() {
4030 return new A();
4031 }
4032 void delete_a(A* a) {
4033 delete a;
4034 }
4035 A B::daft4() {
4036 A a;
4037 return a;
4038 }
4039 std::unique_ptr<A> B::daft5() {
4040 return std::make_unique<A>();
4041 }
4042 std::unique_ptr<A> fixed;
4043 const std::unique_ptr<A>& B::daft6() {
4044 return fixed;
4045 }
4046 "};
4047 let rs = quote! {
4048 let b = ffi::B::new().within_unique_ptr();
4049 let a = ffi::get_a();
4050 b.daft(unsafe { a.as_ref().unwrap() });
4051 unsafe { ffi::delete_a(a) };
4052 };
4053 run_test(cpp, hdr, rs, &["B", "get_a", "delete_a"], &[]);
4054}
4055
4056#[test]
4057fn test_ulong() {
4058 let hdr = indoc! {"
4059 inline unsigned long daft(unsigned long a) { return a; }
4060 "};
4061 let rs = quote! {
4062 assert_eq!(ffi::daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
4063 };
4064 run_test("", hdr, rs, &["daft"], &[]);
4065}
4066
4067#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4068#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
4069#[test]
4070fn test_typedef_to_ulong() {
4071 let hdr = indoc! {"
4072 typedef unsigned long fiddly;
4073 inline fiddly daft(fiddly a) { return a; }
4074 "};
4075 let rs = quote! {
4076 assert_eq!(ffi::daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
4077 };
4078 run_test("", hdr, rs, &["daft"], &[]);
4079}
4080
4081#[test]
4082fn test_generate_typedef_to_ulong() {
4083 let hdr = indoc! {"
4084 #include <cstdint>
4085 typedef uint32_t fish_t;
4086 "};
4087 let rs = quote! {
4088 let _: ffi::fish_t;
4089 };
4090 run_test("", hdr, rs, &[], &["fish_t"]);
4091}
4092
4093#[test]
4094fn test_ulong_method() {
4095 let hdr = indoc! {"
4096 class A {
4097 public:
4098 A() {};
4099 unsigned long daft(unsigned long a) const { return a; }
4100 };
4101 "};
4102 let rs = quote! {
4103 let a = ffi::A::new().within_unique_ptr();
4104 assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
4105 };
4106 run_test("", hdr, rs, &["A"], &[]);
4107}
4108
4109#[test]
4110fn test_ulong_wrapped_method() {
4111 let hdr = indoc! {"
4112 #include <cstdint>
4113 struct B {
4114 B() {};
4115 uint32_t a;
4116 };
4117 class A {
4118 public:
4119 A() {};
4120 unsigned long daft(unsigned long a, B) const { return a; }
4121 };
4122 "};
4123 let rs = quote! {
4124 let b = ffi::B::new().within_unique_ptr();
4125 let a = ffi::A::new().within_unique_ptr();
4126 assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34), b), autocxx::c_ulong(34));
4127 };
4128 run_test("", hdr, rs, &["A", "B"], &[]);
4129}
4130
4131#[test]
4132fn test_reserved_name() {
4133 let hdr = indoc! {"
4134 #include <cstdint>
4135 inline uint32_t async(uint32_t a) { return a; }
4136 "};
4137 let rs = quote! {
4138 assert_eq!(ffi::async_(34), 34);
4139 };
4140 run_test("", hdr, rs, &["async_"], &[]);
4141}
4142
4143#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4144#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
4145#[test]
4146fn test_nested_type() {
4147 // Test that we can import APIs that use nested types.
4148 // As a regression test, we also test that the nested type `A::B` doesn't conflict with the
4149 // top-level type `B`. This used to cause compile errors.
4150 let hdr = indoc! {"
4151 struct A {
4152 A() {}
4153 struct B {
4154 B() {}
4155 };
4156 enum C {};
4157 using D = int;
4158 };
4159 struct B {
4160 B() {}
4161 void method_on_top_level_type() const {}
4162 };
4163 void take_A_B(A::B);
4164 void take_A_C(A::C);
4165 void take_A_D(A::D);
4166 "};
4167 let rs = quote! {
4168 let _ = ffi::A::new().within_unique_ptr();
4169 let b = ffi::B::new().within_unique_ptr();
4170 b.as_ref().unwrap().method_on_top_level_type();
4171 };
4172 run_test("", hdr, rs, &["A", "B", "take_A_B", "take_A_C"], &[]);
4173}
4174
4175#[test]
4176fn test_nested_type_in_namespace() {
4177 // Test that we can import APIs that use nested types in a namespace.
4178 // We can't make this part of the previous test as autocxx drops the
4179 // namespace, so `A::B` and `N::A::B` would be imported as the same
4180 // type.
4181 let hdr = indoc! {"
4182 namespace N {
4183 struct A {
4184 A() {}
4185 struct B {
4186 B() {}
4187 };
4188 };
4189 };
4190 void take_A_B(N::A::B);
4191 "};
4192 let rs = quote! {};
4193 run_test("", hdr, rs, &["take_A_B"], &[]);
4194}
4195
4196#[test]
4197fn test_nested_enum_in_namespace() {
4198 let hdr = indoc! {"
4199 namespace N {
4200 struct A {
4201 A() {}
4202 enum B {
4203 C,
4204 D,
4205 };
4206 };
4207 };
4208 void take_A_B(N::A::B);
4209 "};
4210 let rs = quote! {};
4211 run_test("", hdr, rs, &["take_A_B"], &[]);
4212}
4213
4214#[test]
4215fn test_abstract_nested_type() {
4216 let hdr = indoc! {"
4217 namespace N {
4218 class A {
4219 public:
4220 A() {}
4221 class B {
4222 private:
4223 B() {}
4224 public:
4225 virtual ~B() {}
4226 virtual void Foo() = 0;
4227 };
4228 };
4229 };
4230 void take_A_B(const N::A::B&);
4231 "};
4232 let rs = quote! {};
4233 run_test("", hdr, rs, &["take_A_B", "N::A_B"], &[]);
4234}
4235
4236#[test]
4237fn test_nested_type_constructor() {
4238 let hdr = indoc! {"
4239 #include <string>
4240 class A {
4241 public:
4242 class B {
4243 public:
4244 B(const std::string&) {}
4245 int b;
4246 };
4247 int a;
4248 };
4249 "};
4250 let rs = quote! {
4251 ffi::A_B::new(&ffi::make_string("Hello")).within_unique_ptr();
4252 };
4253 run_test("", hdr, rs, &["A_B"], &[]);
4254}
4255
4256#[test]
4257fn test_generic_type() {
4258 let hdr = indoc! {"
4259 #include <cstdint>
4260 #include <string>
4261 template<typename TY>
4262 struct Container {
4263 Container(TY a_) : a(a_) {}
4264 TY a;
4265 };
4266 struct Secondary {
4267 Secondary() {}
4268 void take_a(const Container<char>) const {}
4269 void take_b(const Container<uint16_t>) const {}
4270 uint16_t take_c(std::string a) const { return 10 + a.size(); }
4271 };
4272 "};
4273 let rs = quote! {
4274 use ffi::ToCppString;
4275 let item = ffi::Secondary::new().within_unique_ptr();
4276 assert_eq!(item.take_c("hello".into_cpp()), 15)
4277 };
4278 run_test("", hdr, rs, &["Secondary"], &[]);
4279}
4280
4281#[test]
4282fn test_cycle_generic_type() {
4283 let hdr = indoc! {"
4284 #include <cstdint>
4285 template<typename TY>
4286 struct Container {
4287 Container(TY a_) : a(a_) {}
4288 TY a;
4289 };
4290 inline Container<char> make_thingy() {
4291 Container<char> a('a');
4292 return a;
4293 }
4294 typedef Container<char> Concrete;
4295 inline uint32_t take_thingy(Concrete a) {
4296 return a.a;
4297 }
4298 "};
4299 let rs = quote! {
4300 assert_eq!(ffi::take_thingy(ffi::make_thingy()), 'a' as u32)
4301 };
4302 run_test("", hdr, rs, &["take_thingy", "make_thingy"], &[]);
4303}
4304
4305#[test]
4306fn test_virtual_fns() {
4307 let hdr = indoc! {"
4308 #include <cstdint>
4309 class A {
4310 public:
4311 A(uint32_t num) : b(num) {}
4312 virtual uint32_t foo(uint32_t a) { return a+1; };
4313 virtual ~A() {}
4314 uint32_t b;
4315 };
4316 class B: public A {
4317 public:
4318 B() : A(3), c(4) {}
4319 virtual uint32_t foo(uint32_t a) { return a+2; };
4320 uint32_t c;
4321 };
4322 "};
4323 let rs = quote! {
4324 let mut a = ffi::A::new(12).within_unique_ptr();
4325 assert_eq!(a.pin_mut().foo(2), 3);
4326 let mut b = ffi::B::new().within_unique_ptr();
4327 assert_eq!(b.pin_mut().foo(2), 4);
4328 };
4329 run_test("", hdr, rs, &["A", "B"], &[]);
4330}
4331
4332#[test]
4333fn test_const_virtual_fns() {
4334 let hdr = indoc! {"
4335 #include <cstdint>
4336 class A {
4337 public:
4338 A(uint32_t num) : b(num) {}
4339 virtual uint32_t foo(uint32_t a) const { return a+1; };
4340 virtual ~A() {}
4341 uint32_t b;
4342 };
4343 class B: public A {
4344 public:
4345 B() : A(3), c(4) {}
4346 virtual uint32_t foo(uint32_t a) const { return a+2; };
4347 uint32_t c;
4348 };
4349 "};
4350 let rs = quote! {
4351 let a = ffi::A::new(12).within_unique_ptr();
4352 assert_eq!(a.foo(2), 3);
4353 let b = ffi::B::new().within_unique_ptr();
4354 assert_eq!(b.foo(2), 4);
4355 };
4356 run_test("", hdr, rs, &["A", "B"], &[]);
4357}
4358
4359#[test]
4360#[ignore] // https://github.com/google/autocxx/issues/197
4361fn test_virtual_fns_inheritance() {
4362 let hdr = indoc! {"
4363 #include <cstdint>
4364 class A {
4365 public:
4366 A(uint32_t num) : b(num) {}
4367 virtual uint32_t foo(uint32_t a) { return a+1; };
4368 virtual ~A() {}
4369 uint32_t b;
4370 };
4371 class B: public A {
4372 public:
4373 B() : A(3), c(4) {}
4374 uint32_t c;
4375 };
4376 "};
4377 let rs = quote! {
4378 let mut b = ffi::B::new().within_unique_ptr();
4379 assert_eq!(b.pin_mut().foo(2), 3);
4380 };
4381 run_test("", hdr, rs, &["B"], &[]);
4382}
4383
4384#[test]
4385fn test_vector_cycle_up() {
4386 let hdr = indoc! {"
4387 #include <cstdint>
4388 #include <vector>
4389 #include <memory>
4390 struct A {
4391 uint32_t a;
4392 };
4393 inline uint32_t take_vec(std::unique_ptr<std::vector<A>> many_as) {
4394 return many_as->size();
4395 }
4396 inline std::unique_ptr<std::vector<A>> get_vec() {
4397 auto items = std::make_unique<std::vector<A>>();
4398 items->push_back(A { 3 });
4399 items->push_back(A { 4 });
4400 return items;
4401 }
4402 "};
4403 let rs = quote! {
4404 let v = ffi::get_vec();
4405 assert_eq!(v.as_ref().unwrap().is_empty(), false);
4406 assert_eq!(ffi::take_vec(v), 2);
4407 };
4408 run_test("", hdr, rs, &["take_vec", "get_vec"], &[]);
4409}
4410
4411#[test]
4412fn test_vector_cycle_bare() {
4413 let hdr = indoc! {"
4414 #include <cstdint>
4415 #include <vector>
4416 struct A {
4417 uint32_t a;
4418 };
4419 inline uint32_t take_vec(std::vector<A> many_as) {
4420 return many_as.size();
4421 }
4422 inline std::vector<A> get_vec() {
4423 std::vector<A> items;
4424 items.push_back(A { 3 });
4425 items.push_back(A { 4 });
4426 return items;
4427 }
4428 "};
4429 let rs = quote! {
4430 assert_eq!(ffi::take_vec(ffi::get_vec()), 2);
4431 };
4432 run_test("", hdr, rs, &["take_vec", "get_vec"], &[]);
4433}
4434
4435#[test]
4436fn test_typedef_to_std() {
4437 let hdr = indoc! {"
4438 #include <string>
4439 typedef std::string my_string;
4440 inline uint32_t take_str(my_string a) {
4441 return a.size();
4442 }
4443 "};
4444 let rs = quote! {
4445 use ffi::ToCppString;
4446 assert_eq!(ffi::take_str("hello".into_cpp()), 5);
4447 };
4448 run_test("", hdr, rs, &["take_str"], &[]);
4449}
4450
4451#[test]
4452fn test_typedef_to_up_in_fn_call() {
4453 let hdr = indoc! {"
4454 #include <string>
4455 #include <memory>
4456 typedef std::unique_ptr<std::string> my_string;
4457 inline uint32_t take_str(my_string a) {
4458 return a->size();
4459 }
4460 "};
4461 let rs = quote! {
4462 use ffi::ToCppString;
4463 assert_eq!(ffi::take_str("hello".into_cpp()), 5);
4464 };
4465 run_test("", hdr, rs, &["take_str"], &[]);
4466}
4467
4468#[test]
4469fn test_typedef_in_pod_struct() {
4470 let hdr = indoc! {"
4471 #include <string>
4472 typedef uint32_t my_int;
4473 struct A {
4474 my_int a;
4475 };
4476 inline uint32_t take_a(A a) {
4477 return a.a;
4478 }
4479 "};
4480 let rs = quote! {
4481 let a = ffi::A {
4482 a: 32,
4483 };
4484 assert_eq!(ffi::take_a(a), 32);
4485 };
4486 run_test("", hdr, rs, &["take_a"], &["A"]);
4487}
4488
4489#[test]
4490fn test_cint_in_pod_struct() {
4491 let hdr = indoc! {"
4492 #include <string>
4493 struct A {
4494 int a;
4495 };
4496 inline uint32_t take_a(A a) {
4497 return a.a;
4498 }
4499 "};
4500 let rs = quote! {
4501 let a = ffi::A {
4502 a: 32,
4503 };
4504 assert_eq!(ffi::take_a(a), 32);
4505 };
4506 run_test("", hdr, rs, &["take_a"], &["A"]);
4507}
4508
4509#[test]
4510fn test_string_in_struct() {
4511 let hdr = indoc! {"
4512 #include <string>
4513 #include <memory>
4514 struct A {
4515 std::string a;
4516 };
4517 inline A make_a(std::string b) {
4518 A bob;
4519 bob.a = b;
4520 return bob;
4521 }
4522 inline uint32_t take_a(A a) {
4523 return a.a.size();
4524 }
4525 "};
4526 let rs = quote! {
4527 use ffi::ToCppString;
4528 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4529 };
4530 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4531}
4532
4533#[test]
4534#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4535fn test_up_in_struct() {
4536 let hdr = indoc! {"
4537 #include <string>
4538 #include <memory>
4539 struct A {
4540 std::unique_ptr<std::string> a;
4541 };
4542 inline A make_a(std::string b) {
4543 A bob;
4544 bob.a = std::make_unique<std::string>(b);
4545 return bob;
4546 }
4547 inline uint32_t take_a(A a) {
4548 return a.a->size();
4549 }
4550 "};
4551 let rs = quote! {
4552 use ffi::ToCppString;
4553 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4554 };
4555 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4556}
4557
4558#[test]
4559fn test_typedef_to_std_in_struct() {
4560 let hdr = indoc! {"
4561 #include <string>
4562 typedef std::string my_string;
4563 struct A {
4564 my_string a;
4565 };
4566 inline A make_a(std::string b) {
4567 A bob;
4568 bob.a = b;
4569 return bob;
4570 }
4571 inline uint32_t take_a(A a) {
4572 return a.a.size();
4573 }
4574 "};
4575 let rs = quote! {
4576 use ffi::ToCppString;
4577 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4578 };
4579 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4580}
4581
4582#[test]
4583#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
4584fn test_typedef_to_up_in_struct() {
4585 let hdr = indoc! {"
4586 #include <string>
4587 #include <memory>
4588 typedef std::unique_ptr<std::string> my_string;
4589 struct A {
4590 my_string a;
4591 };
4592 inline A make_a(std::string b) {
4593 A bob;
4594 bob.a = std::make_unique<std::string>(b);
4595 return bob;
4596 }
4597 inline uint32_t take_a(A a) {
4598 return a.a->size();
4599 }
4600 "};
4601 let rs = quote! {
4602 use ffi::ToCppString;
4603 assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
4604 };
4605 run_test("", hdr, rs, &["make_a", "take_a"], &[]);
4606}
4607
4608#[test]
4609fn test_float() {
4610 let hdr = indoc! {"
4611 inline float daft(float a) { return a; }
4612 "};
4613 let rs = quote! {
4614 assert_eq!(ffi::daft(34.0f32), 34.0f32);
4615 };
4616 run_test("", hdr, rs, &["daft"], &[]);
4617}
4618
4619#[test]
4620fn test_double() {
4621 let hdr = indoc! {"
4622 inline double daft(double a) { return a; }
4623 "};
4624 let rs = quote! {
4625 assert_eq!(ffi::daft(34.0f64), 34.0f64);
4626 };
4627 run_test("", hdr, rs, &["daft"], &[]);
4628}
4629
4630#[test]
4631fn test_issues_217_222() {
4632 let hdr = indoc! {"
4633 #include <string>
4634 #include <cstdint>
4635 #include <cstddef>
4636
4637 template <typename STRING_TYPE> class BasicStringPiece {
4638 public:
4639 typedef size_t size_type;
4640 typedef typename STRING_TYPE::traits_type traits_type;
4641 typedef typename STRING_TYPE::value_type value_type;
4642 typedef const value_type* pointer;
4643 typedef const value_type& reference;
4644 typedef const value_type& const_reference;
4645 typedef ptrdiff_t difference_type;
4646 typedef const value_type* const_iterator;
4647 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
4648 static const size_type npos;
4649 };
4650
4651 template<typename CHAR>
4652 class Replacements {
4653 public:
4654 Replacements() {
4655 }
4656 void SetScheme(const CHAR*) {
4657 }
4658 uint16_t a;
4659 };
4660
4661 struct Component {
4662 uint16_t a;
4663 };
4664
4665 template <typename STR>
4666 class StringPieceReplacements : public Replacements<typename STR::value_type> {
4667 private:
4668 using CharT = typename STR::value_type;
4669 using StringPieceT = BasicStringPiece<STR>;
4670 using ParentT = Replacements<CharT>;
4671 using SetterFun = void (ParentT::*)(const CharT*, const Component&);
4672 void SetImpl(SetterFun, StringPieceT) {
4673 }
4674 public:
4675 void SetSchemeStr(const CharT* str) { SetImpl(&ParentT::SetScheme, str); }
4676 };
4677
4678 class GURL {
4679 public:
4680 typedef StringPieceReplacements<std::string> UrlReplacements;
4681 GURL() {}
4682 GURL ReplaceComponents(const Replacements<char>&) const {
4683 return GURL();
4684 }
4685 uint16_t a;
4686 };
4687 "};
4688 let rs = quote! {
4689 ffi::GURL::new().within_unique_ptr();
4690 };
4691 // The block! directives here are to avoid running into
4692 // https://github.com/rust-lang/rust-bindgen/pull/1975
4693 run_test_ex(
4694 "",
4695 hdr,
4696 rs,
4697 quote! { generate!("GURL") block!("StringPiece") block!("Replacements") },
4698 None,
4699 None,
4700 None,
4701 );
4702}
4703
4704#[test]
4705#[ignore] // https://github.com/rust-lang/rust-bindgen/pull/1975, https://github.com/google/autocxx/issues/106
4706fn test_dependent_qualified_type() {
4707 let hdr = indoc! {"
4708 #include <stddef.h>
4709 struct MyString {
4710 typedef char value_type;
4711 };
4712 template<typename T> struct MyStringView {
4713 typedef typename T::value_type view_value_type;
4714 const view_value_type* start;
4715 size_t length;
4716 };
4717 const char* HELLO = \"hello\";
4718 inline MyStringView<MyString> make_string_view() {
4719 MyStringView<MyString> r;
4720 r.start = HELLO;
4721 r.length = 2;
4722 return r;
4723 }
4724 inline size_t take_string_view(const MyStringView<MyString>& bit) {
4725 return bit.length;
4726 }
4727 "};
4728 let rs = quote! {
4729 let sv = ffi::make_string_view();
4730 assert_eq!(ffi::take_string_view(sv.as_ref().unwrap()), 2);
4731 };
4732 run_test("", hdr, rs, &["take_string_view", "make_string_view"], &[]);
4733}
4734
4735#[test]
4736fn test_simple_dependent_qualified_type() {
4737 // bindgen seems to cope with this case just fine
4738 let hdr = indoc! {"
4739 #include <stddef.h>
4740 #include <stdint.h>
4741 struct MyString {
4742 typedef char value_type;
4743 };
4744 template<typename T> struct MyStringView {
4745 typedef typename T::value_type view_value_type;
4746 const view_value_type* start;
4747 size_t length;
4748 };
4749 typedef MyStringView<MyString>::view_value_type MyChar;
4750 inline MyChar make_char() {
4751 return 'a';
4752 }
4753 inline uint32_t take_char(MyChar c) {
4754 return static_cast<unsigned char>(c);
4755 }
4756 "};
4757 let rs = quote! {
4758 let c = ffi::make_char();
4759 assert_eq!(ffi::take_char(c), 97);
4760 };
4761 run_test("", hdr, rs, &["make_char", "take_char"], &[]);
4762}
4763
4764#[test]
4765fn test_ignore_dependent_qualified_type() {
4766 let hdr = indoc! {"
4767 #include <stddef.h>
4768 struct MyString {
4769 typedef char value_type;
4770 };
4771 template<typename T> struct MyStringView {
4772 typedef typename T::value_type view_value_type;
4773 const view_value_type* start;
4774 size_t length;
4775 };
4776 MyStringView<MyString> make_string_view();
4777 struct B {
4778 B() {}
4779 inline size_t take_string_view(const MyStringView<MyString> bit) {
4780 return bit.length;
4781 }
4782 };
4783 "};
4784 let cpp = indoc! {"
4785 const char* HELLO = \"hello\";
4786 MyStringView<MyString> make_string_view() {
4787 MyStringView<MyString> r;
4788 r.start = HELLO;
4789 r.length = 2;
4790 return r;
4791 }
4792 "};
4793 let rs = quote! {
4794 ffi::B::new().within_unique_ptr();
4795 };
4796 run_test(cpp, hdr, rs, &["B"], &[]);
4797}
4798
4799#[test]
4800fn test_ignore_dependent_qualified_type_reference() {
4801 let hdr = indoc! {"
4802 #include <stddef.h>
4803 struct MyString {
4804 typedef char value_type;
4805 };
4806 template<typename T> struct MyStringView {
4807 typedef typename T::value_type view_value_type;
4808 const view_value_type* start;
4809 size_t length;
4810 };
4811 MyStringView<MyString> make_string_view();
4812 struct B {
4813 B() {}
4814 inline size_t take_string_view(const MyStringView<MyString>& bit) {
4815 return bit.length;
4816 }
4817 };
4818 "};
4819 let cpp = indoc! {"
4820 const char* HELLO = \"hello\";
4821 MyStringView<MyString> make_string_view() {
4822 MyStringView<MyString> r;
4823 r.start = HELLO;
4824 r.length = 2;
4825 return r;
4826 }
4827 "};
4828 let rs = quote! {
4829 ffi::B::new().within_unique_ptr();
4830 };
4831 run_test(cpp, hdr, rs, &["B"], &[]);
4832}
4833
4834#[test]
4835fn test_specialization() {
4836 let hdr = indoc! {"
4837 #include <stddef.h>
4838 #include <stdint.h>
4839 #include <string>
4840 #include <type_traits>
4841
4842 template <typename T, bool = std::is_trivially_destructible<T>::value>
4843 struct OptionalStorageBase {
4844 T value_;
4845 };
4846
4847 template <typename T,
4848 bool = std::is_trivially_copy_constructible<T>::value,
4849 bool = std::is_trivially_move_constructible<T>::value>
4850 struct OptionalStorage : OptionalStorageBase<T> {};
4851
4852 template <typename T>
4853 struct OptionalStorage<T,
4854 true /* trivially copy constructible */,
4855 false /* trivially move constructible */>
4856 : OptionalStorageBase<T> {
4857 };
4858
4859 template <typename T>
4860 struct OptionalStorage<T,
4861 false /* trivially copy constructible */,
4862 true /* trivially move constructible */>
4863 : OptionalStorageBase<T> {
4864 };
4865
4866 template <typename T>
4867 struct OptionalStorage<T,
4868 true /* trivially copy constructible */,
4869 true /* trivially move constructible */>
4870 : OptionalStorageBase<T> {
4871 };
4872
4873 template <typename T>
4874 class OptionalBase {
4875 private:
4876 OptionalStorage<T> storage_;
4877 };
4878
4879 template <typename T>
4880 class Optional : public OptionalBase<T> {
4881
4882 };
4883
4884 struct B {
4885 B() {}
4886 void take_optional(Optional<std::string>) {}
4887 uint32_t a;
4888 };
4889 "};
4890 let rs = quote! {
4891 ffi::B::new().within_unique_ptr();
4892 };
4893 run_test("", hdr, rs, &["B"], &[]);
4894}
4895
4896#[test]
4897fn test_private_constructor_make_unique() {
4898 let hdr = indoc! {"
4899 #include <stdint.h>
4900 struct A {
4901 private:
4902 A() {};
4903 public:
4904 uint32_t a;
4905 };
4906 "};
4907 let rs = quote! {};
4908 run_test("", hdr, rs, &["A"], &[]);
4909}
4910
4911#[test]
4912#[ignore] // https://github.com/google/autocxx/issues/266
4913fn test_take_array() {
4914 let hdr = indoc! {"
4915 #include <cstdint>
4916 uint32_t take_array(const uint32_t a[4]) {
4917 return a[0] + a[2];
4918 }
4919 "};
4920 let rs = quote! {
4921 let c: [u32; 4usize] = [ 10, 20, 30, 40 ];
4922 let c = c as *const [_];
4923 assert_eq!(ffi::take_array(&c), 40);
4924 };
4925 run_test("", hdr, rs, &["take_array"], &[]);
4926}
4927
4928#[test]
4929fn test_take_array_in_struct() {
4930 let hdr = indoc! {"
4931 #include <cstdint>
4932 struct data {
4933 char a[4];
4934 };
4935 uint32_t take_array(const data a) {
4936 return a.a[0] + a.a[2];
4937 }
4938 "};
4939 let rs = quote! {
4940 let c = ffi::data { a: [ 10, 20, 30, 40 ] };
4941 assert_eq!(ffi::take_array(c), 40);
4942 };
4943 run_test("", hdr, rs, &["take_array"], &["data"]);
4944}
4945
4946#[test]
4947fn test_union_ignored() {
4948 let hdr = indoc! {"
4949 #include <cstdint>
4950 union A {
4951 uint32_t a;
4952 float b;
4953 };
4954 struct B {
4955 B() :a(1) {}
4956 uint32_t take_union(A) const {
4957 return 3;
4958 }
4959 uint32_t get_a() const { return 2; }
4960 uint32_t a;
4961 };
4962 "};
4963 let rs = quote! {
4964 let b = ffi::B::new().within_unique_ptr();
4965 assert_eq!(b.get_a(), 2);
4966 };
4967 run_test("", hdr, rs, &["B"], &[]);
4968}
4969
4970#[test]
4971fn test_double_underscores_ignored() {
4972 let hdr = indoc! {"
4973 #include <cstdint>
4974 struct __FOO {
4975 uint32_t a;
4976 };
4977 struct B {
4978 B() :a(1) {}
4979 uint32_t take_foo(__FOO) const {
4980 return 3;
4981 }
4982 void do__something() const { }
4983 uint32_t get_a() const { return 2; }
4984 uint32_t a;
4985 };
4986
4987 struct __default { __default() = default; };
4988 struct __destructor { ~__destructor() = default; };
4989 struct __copy { __copy(const __copy&) = default; };
4990 struct __copy_operator { __copy_operator &operator=(const __copy_operator&) = default; };
4991 struct __move { __move(__move&&) = default; };
4992 struct __move_operator { __move_operator &operator=(const __move_operator&) = default; };
4993 "};
4994 let rs = quote! {
4995 let b = ffi::B::new().within_unique_ptr();
4996 assert_eq!(b.get_a(), 2);
4997 };
4998 run_test(
4999 "",
5000 hdr,
5001 rs,
5002 &[
5003 "B",
5004 "__default",
5005 "__destructor",
5006 "__copy",
5007 "__copy_operator",
5008 "__move",
5009 "__move_operator",
5010 ],
5011 &[],
5012 );
5013}
5014
5015// This test fails on Windows gnu but not on Windows msvc
5016#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
5017#[test]
5018fn test_double_underscore_typedef_ignored() {
5019 let hdr = indoc! {"
5020 #include <cstdint>
5021 typedef int __int32_t;
5022 typedef __int32_t __darwin_pid_t;
5023 typedef __darwin_pid_t pid_t;
5024 struct B {
5025 B() :a(1) {}
5026 uint32_t take_foo(pid_t) const {
5027 return 3;
5028 }
5029 uint32_t get_a() const { return 2; }
5030 uint32_t a;
5031 };
5032 "};
5033 let rs = quote! {
5034 let b = ffi::B::new().within_unique_ptr();
5035 assert_eq!(b.get_a(), 2);
5036 };
5037 run_test("", hdr, rs, &["B"], &[]);
5038}
5039
5040#[test]
5041fn test_double_underscores_fn_namespace() {
5042 let hdr = indoc! {"
5043 namespace __B {
5044 inline void a() {}
5045 };
5046 "};
5047 run_test_ex(
5048 "",
5049 hdr,
5050 quote! {},
5051 quote! { generate_all!() },
5052 None,
5053 None,
5054 None,
5055 );
5056}
5057
5058#[test]
5059fn test_typedef_to_ptr_is_marked_unsafe() {
5060 let hdr = indoc! {"
5061 struct _xlocalefoo; /* forward reference */
5062 typedef struct _xlocalefoo * locale_tfoo;
5063 extern \"C\" {
5064 locale_tfoo duplocalefoo(locale_tfoo);
5065 }
5066 "};
5067 let rs = quote! {};
5068 run_test("", hdr, rs, &["duplocalefoo"], &[]);
5069}
5070
5071#[test]
5072fn test_issue_264() {
5073 let hdr = indoc! {"
5074 namespace a {
5075 typedef int b;
5076 //inline namespace c {}
5077 template <typename> class aa;
5078 inline namespace c {
5079 template <typename d, typename = d, typename = aa<d>> class e;
5080 }
5081 typedef e<char> f;
5082 template <typename g, typename, template <typename> typename> struct h {
5083 using i = g;
5084 };
5085 template <typename g, template <typename> class k> using j = h<g, void, k>;
5086 template <typename g, template <typename> class k>
5087 using m = typename j<g, k>::i;
5088 template <typename> struct l { typedef b ab; };
5089 template <typename p> class aa {
5090 public:
5091 typedef p n;
5092 };
5093 struct r {
5094 template <typename p> using o = typename p::c;
5095 };
5096 template <typename ad> struct u : r {
5097 typedef typename ad::n n;
5098 using ae = m<n, o>;
5099 template <typename af, typename> struct v { using i = typename l<f>::ab; };
5100 using ab = typename v<ad, ae>::i;
5101 };
5102 } // namespace a
5103 namespace q {
5104 template <typename ad> struct w : a::u<ad> {};
5105 } // namespace q
5106 namespace a {
5107 inline namespace c {
5108 template <typename, typename, typename ad> class e {
5109 typedef q::w<ad> s;
5110 public:
5111 typedef typename s::ab ab;
5112 };
5113 } // namespace c
5114 } // namespace a
5115 namespace ag {
5116 namespace ah {
5117 typedef a::f::ab t;
5118 class ai {
5119 public:
5120 t aj;
5121 };
5122 class al;
5123 namespace am {
5124 class an {
5125 public:
5126 void ao(ai);
5127 };
5128 } // namespace am
5129 class ap {
5130 public:
5131 al aq();
5132 };
5133 class ar {
5134 public:
5135 am::an as;
5136 };
5137 class al {
5138 public:
5139 ar at;
5140 };
5141 struct au {
5142 ap av;
5143 };
5144 } // namespace ah
5145 } // namespace ag
5146 namespace operations_research {
5147 class aw {
5148 public:
5149 ag::ah::au ax;
5150 };
5151 class Solver {
5152 public:
5153 aw ay;
5154 };
5155 } // namespace operations_research
5156 "};
5157 let rs = quote! {};
5158 run_test_ex(
5159 "",
5160 hdr,
5161 rs,
5162 directives_from_lists(&["operations_research::Solver"], &[], None),
5163 make_cpp17_adder(),
5164 None,
5165 None,
5166 );
5167}
5168
5169#[test]
5170fn test_unexpected_use() {
5171 // https://github.com/google/autocxx/issues/303
5172 let hdr = indoc! {"
5173 typedef int a;
5174 namespace b {
5175 namespace c {
5176 enum d : a;
5177 }
5178 } // namespace b
5179 namespace {
5180 using d = b::c::d;
5181 }
5182 namespace content {
5183 class RenderFrameHost {
5184 public:
5185 RenderFrameHost() {}
5186 d e;
5187 };
5188 } // namespace content
5189 "};
5190 let rs = quote! {
5191 let _ = ffi::content::RenderFrameHost::new().within_unique_ptr();
5192 };
5193 run_test("", hdr, rs, &["content::RenderFrameHost"], &[]);
5194}
5195
5196#[test]
5197fn test_get_pure_virtual() {
5198 let hdr = indoc! {"
5199 #include <cstdint>
5200 class A {
5201 public:
5202 virtual ~A() {}
5203 virtual uint32_t get_val() const = 0;
5204 };
5205 class B : public A {
5206 public:
5207 virtual uint32_t get_val() const { return 3; }
5208 };
5209 const B b;
5210 inline const A* get_a() { return &b; };
5211 "};
5212 let rs = quote! {
5213 let a = ffi::get_a();
5214 let a_ref = unsafe { a.as_ref() }.unwrap();
5215 assert_eq!(a_ref.get_val(), 3);
5216 };
5217 run_test("", hdr, rs, &["A", "get_a"], &[]);
5218}
5219
5220#[test]
5221fn test_abstract_class_no_make_unique() {
5222 // We shouldn't generate a new().within_unique_ptr() for abstract classes.
5223 // The test is successful if the bindings compile, i.e. if autocxx doesn't
5224 // attempt to instantiate the class.
5225 let hdr = indoc! {"
5226 class A {
5227 public:
5228 A() {}
5229 virtual ~A() {}
5230 virtual void foo() const = 0;
5231 };
5232 "};
5233 let rs = quote! {};
5234 run_test("", hdr, rs, &["A"], &[]);
5235}
5236
5237#[test]
5238fn test_derived_abstract_class_no_make_unique() {
5239 let hdr = indoc! {"
5240 class A {
5241 public:
5242 A();
5243 virtual ~A() {}
5244 virtual void foo() const = 0;
5245 };
5246
5247 class B : public A {
5248 public:
5249 B();
5250 };
5251 "};
5252 let rs = quote! {};
5253 run_test("", hdr, rs, &["A", "B"], &[]);
5254}
5255
5256#[test]
5257fn test_recursive_derived_abstract_class_no_make_unique() {
5258 let hdr = indoc! {"
5259 class A {
5260 public:
5261 A() {}
5262 virtual ~A() {}
5263 virtual void foo() const = 0;
5264 };
5265
5266 class B : public A {
5267 public:
5268 B() {};
5269 };
5270
5271 class C : public B {
5272 public:
5273 C() {};
5274 };
5275 "};
5276 let rs = quote! {};
5277 run_test("", hdr, rs, &["A", "B", "C"], &[]);
5278}
5279
5280#[test]
5281fn test_derived_abstract_class_with_no_allowlisting_no_make_unique() {
5282 let hdr = indoc! {"
5283 class A {
5284 public:
5285 A();
5286 virtual ~A() {}
5287 virtual void foo() const = 0;
5288 };
5289
5290 class B : public A {
5291 public:
5292 B();
5293 };
5294 "};
5295 let rs = quote! {};
5296 run_test("", hdr, rs, &["B"], &[]);
5297}
5298
5299#[test]
5300fn test_vector_of_pointers() {
5301 // Just ensures the troublesome API is ignored
5302 let hdr = indoc! {"
5303 #include <vector>
5304 namespace operations_research {
5305 class a;
5306 class Solver {
5307 public:
5308 struct b c(std::vector<a *>);
5309 };
5310 class a {};
5311 } // namespace operations_research
5312 "};
5313 let rs = quote! {};
5314 run_test("", hdr, rs, &["operations_research::Solver"], &[]);
5315}
5316
5317#[test]
5318fn test_vec_and_up_of_primitives() {
5319 let hdr = indoc! {"
5320 #include <vector>
5321 #include <memory>
5322 #include <cstdint>
5323 class Value {
5324 public:
5325 Value(std::vector<uint32_t>) {} // OK
5326 Value(std::unique_ptr<uint32_t>) {} // should be ignored
5327 Value(std::vector<int>) {} // should be ignored
5328 Value(std::unique_ptr<int>) {} // should be ignored
5329 Value(std::vector<char>) {} // should be ignored
5330 Value(std::unique_ptr<char>) {} // should be ignored
5331 Value(std::vector<float>) {} // OK
5332 Value(std::unique_ptr<float>) {} // should be ignored
5333 Value(std::vector<bool>) {} // should be ignored
5334 Value(std::unique_ptr<bool>) {} // should be ignored
5335 Value(std::vector<size_t>) {} // OK
5336 Value(std::unique_ptr<size_t>) {} // should be ignored
5337 };
5338 inline std::vector<uint32_t> make_vec_uint32_t() {
5339 std::vector<uint32_t> a;
5340 return a;
5341 }
5342 inline std::vector<float> make_vec_float() {
5343 std::vector<float> a;
5344 return a;
5345 }
5346 inline std::vector<size_t> make_vec_size_t() {
5347 std::vector<size_t> a;
5348 return a;
5349 }
5350 "};
5351 let rs = quote! {
5352 ffi::Value::new(ffi::make_vec_uint32_t()).within_box();
5353 ffi::Value::new6(ffi::make_vec_float()).within_box();
5354 ffi::Value::new10(ffi::make_vec_size_t()).within_box();
5355 };
5356 run_test(
5357 "",
5358 hdr,
5359 rs,
5360 &[
5361 "Value",
5362 "make_vec_uint32_t",
5363 "make_vec_float",
5364 "make_vec_size_t",
5365 ],
5366 &[],
5367 );
5368}
5369
5370#[test]
5371fn test_pointer_to_pointer() {
5372 // Just ensures the troublesome API is ignored
5373 let hdr = indoc! {"
5374 namespace operations_research {
5375 class a;
5376 class Solver {
5377 public:
5378 struct b c(a **);
5379 };
5380 class a {};
5381 } // namespace operations_research
5382 "};
5383 let rs = quote! {};
5384 run_test("", hdr, rs, &["operations_research::Solver"], &[]);
5385}
5386
5387#[test]
5388fn test_defines_effective() {
5389 let hdr = indoc! {"
5390 #include <cstdint>
5391 #ifdef FOO
5392 inline uint32_t a() { return 4; }
5393 #endif
5394 "};
5395 let rs = quote! {
5396 ffi::a();
5397 };
5398 run_test_ex(
5399 "",
5400 hdr,
5401 rs,
5402 quote! { generate!("a") },
5403 make_clang_arg_adder(&["-DFOO"]),
5404 None,
5405 None,
5406 );
5407}
5408
5409#[test]
5410#[ignore] // https://github.com/google/autocxx/issues/227
5411fn test_function_pointer_template() {
5412 let hdr = indoc! {"
5413 typedef int a;
5414 namespace std {
5415 template <typename> class b;
5416 }
5417 typedef a c;
5418 namespace operations_research {
5419 class d;
5420 class Solver {
5421 public:
5422 typedef std::b<c()> IndexEvaluator3;
5423 d e(IndexEvaluator3);
5424 };
5425 class d {};
5426 } // namespace operations_research
5427 "};
5428 let rs = quote! {};
5429 run_test("", hdr, rs, &["operations_research::Solver"], &[]);
5430}
5431
5432#[test]
5433fn test_cvoid() {
5434 let hdr = indoc! {"
5435 #include <memory>
5436 #include <cstdint>
5437 inline void* a() {
5438 return static_cast<void*>(new int(3));
5439 }
5440 inline uint32_t b(void* p) {
5441 int* p_int = static_cast<int*>(p);
5442 auto val = *p_int;
5443 delete p_int;
5444 return val;
5445 }
5446 "};
5447 let rs = quote! {
5448 let ptr = ffi::a();
5449 let res = unsafe { ffi::b(ptr) };
5450 assert_eq!(res, 3);
5451 };
5452 run_test("", hdr, rs, &["a", "b"], &[]);
5453}
5454
5455#[test]
5456fn test_c_schar() {
5457 let hdr = indoc! {"
5458 inline signed char a() {
5459 return 8;
5460 }
5461 "};
5462 let rs = quote! {
5463 assert_eq!(ffi::a(), 8);
5464 };
5465 run_test("", hdr, rs, &["a"], &[]);
5466}
5467
5468#[test]
5469fn test_c_uchar() {
5470 let hdr = indoc! {"
5471 inline unsigned char a() {
5472 return 8;
5473 }
5474 "};
5475 let rs = quote! {
5476 assert_eq!(ffi::a(), 8);
5477 };
5478 run_test("", hdr, rs, &["a"], &[]);
5479}
5480
5481#[test]
5482fn test_c_ulonglong() {
5483 // We don't test all the different variable-length integer types which we populate.
5484 // If one works, they probably all do. Hopefully.
5485 let hdr = indoc! {"
5486 inline unsigned long long a() {
5487 return 8;
5488 }
5489 "};
5490 let rs = quote! {
5491 assert_eq!(ffi::a(), autocxx::c_ulonglong(8));
5492 };
5493 run_test("", hdr, rs, &["a"], &[]);
5494}
5495
5496#[test]
5497fn test_string_transparent_function() {
5498 let hdr = indoc! {"
5499 #include <string>
5500 #include <cstdint>
5501 inline uint32_t take_string(std::string a) { return a.size(); }
5502 "};
5503 let rs = quote! {
5504 assert_eq!(ffi::take_string("hello"), 5);
5505 };
5506 run_test("", hdr, rs, &["take_string"], &[]);
5507}
5508
5509#[test]
5510fn test_string_transparent_method() {
5511 let hdr = indoc! {"
5512 #include <string>
5513 #include <cstdint>
5514 struct A {
5515 A() {}
5516 inline uint32_t take_string(std::string a) const { return a.size(); }
5517 };
5518 "};
5519 let rs = quote! {
5520 let a = ffi::A::new().within_unique_ptr();
5521 assert_eq!(a.take_string("hello"), 5);
5522 };
5523 run_test("", hdr, rs, &["A"], &[]);
5524}
5525
5526#[test]
5527fn test_string_transparent_static_method() {
5528 let hdr = indoc! {"
5529 #include <string>
5530 #include <cstdint>
5531 struct A {
5532 A() {}
5533 static inline uint32_t take_string(std::string a) { return a.size(); }
5534 };
5535 "};
5536 let rs = quote! {
5537 assert_eq!(ffi::A::take_string("hello"), 5);
5538 };
5539 run_test("", hdr, rs, &["A"], &[]);
5540}
5541
5542#[test]
5543#[ignore] // https://github.com/google/autocxx/issues/490
5544fn test_issue_490() {
5545 let hdr = indoc! {"
5546 typedef int a;
5547 typedef long unsigned size_t;
5548 namespace std {
5549 namespace {
5550 using ::size_t;
5551 template <class b, b c> struct g { static const b value = c; };
5552 template <bool d> using e = g<bool, d>;
5553 typedef e<true> true_type;
5554 template <size_t, size_t> struct ag {};
5555 template <class b> typename b ::h move();
5556 template <class> class allocator;
5557 template <class> class vector;
5558 } // namespace
5559 } // namespace std
5560 void *operator new(size_t, void *);
5561 namespace std {
5562 namespace {
5563 template <class> struct iterator;
5564 template <class b, class> struct ay { using h = b *; };
5565 template <class b> struct bj { b bk; };
5566 template <class bm, class> class bn : bj<bm> {};
5567 template <class b, class i = b> class unique_ptr {
5568 typedef i bp;
5569 typedef typename ay<b, bp>::h bh;
5570 bn<bh, bp> bq;
5571
5572 public:
5573 unique_ptr();
5574 unique_ptr(bh);
5575 bh get() const;
5576 bh release();
5577 };
5578 template <class = void> struct bt;
5579 } // namespace
5580 } // namespace std
5581 typedef a bv;
5582 namespace absl {
5583 template <typename ce> class cj {
5584 public:
5585 using bh = ce *;
5586 using iterator = bh;
5587 };
5588 namespace j {
5589 template <class ce> struct cp {
5590 using k = ce;
5591 using cq = std::bt<>;
5592 };
5593 template <class ce> using cr = typename cp<ce>::k;
5594 template <class ce> using cs = typename cp<ce>::cq;
5595 template <class, class, class, class> class ct {
5596 public:
5597 class iterator {};
5598 class cu {
5599 cu(iterator);
5600 iterator cv;
5601 };
5602 };
5603 template <typename> struct cw;
5604 } // namespace j
5605 template <class ce, class k = j::cr<ce>, class cq = j::cs<ce>,
5606 class cx = std::allocator<ce>>
5607 class cy : public j::ct<j::cw<ce>, k, cq, cx> {};
5608 } // namespace absl
5609 namespace cz {
5610 template <typename da> class db { std::ag<sizeof(a), alignof(da)> c; };
5611 } // namespace cz
5612 namespace spanner {
5613 class l;
5614 class ColumnList {
5615 public:
5616 typedef absl::cj<l>::iterator iterator;
5617 iterator begin();
5618 };
5619 class dd {
5620 union {
5621 cz::db<absl::cy<bv>::cu> e;
5622 };
5623 };
5624 class Row {
5625 public:
5626 bool f(dd);
5627 };
5628 } // namespace spanner
5629 "};
5630 let rs = quote! {};
5631 run_test("", hdr, rs, &["spanner::Row", "spanner::ColumnList"], &[]);
5632}
5633
5634#[test]
5635fn test_immovable_object() {
5636 let hdr = indoc! {"
5637 class A {
5638 public:
5639 A();
5640 A(A&&) = delete;
5641 };
5642
5643 class B{
5644 public:
5645 B();
5646 B(const B&) = delete;
5647 };
5648 "};
5649 let rs = quote! {};
5650 run_test("", hdr, rs, &["A", "B"], &[]);
5651}
5652
5653#[test]
5654fn test_struct_with_reference() {
5655 let hdr = indoc! {"
5656 #include <cstdint>
5657 #include <utility>
5658 struct A {
5659 uint32_t a;
5660 };
5661 struct B {
5662 B(const A& param) : a(param) {}
5663 const A& a;
5664 };
5665 "};
5666 let rs = quote! {};
5667 run_test("", hdr, rs, &["A", "B"], &[]);
5668}
5669
5670#[test]
5671fn test_struct_with_rvalue() {
5672 let hdr = indoc! {"
5673 #include <cstdint>
5674 #include <utility>
5675 struct A {
5676 uint32_t a;
5677 };
5678 struct B {
5679 B(A&& param) : a(std::move(param)) {}
5680 A&& a;
5681 };
5682 "};
5683 let rs = quote! {};
5684 run_test("", hdr, rs, &["A", "B"], &[]);
5685}
5686
5687#[test]
5688fn test_immovable_nested_object() {
5689 let hdr = indoc! {"
5690 struct C {
5691 class A {
5692 public:
5693 A();
5694 A(A&&) = delete;
5695 };
5696
5697 class B{
5698 public:
5699 B();
5700 B(const B&) = delete;
5701 };
5702 };
5703 "};
5704 let rs = quote! {};
5705 run_test("", hdr, rs, &["C_A", "C_B"], &[]);
5706}
5707
5708#[test]
5709fn test_type_called_type() {
5710 let hdr = indoc! {"
5711 namespace a {
5712 template<int _Len>
5713 struct b
5714 {
5715 union type
5716 {
5717 unsigned char __data[_Len];
5718 struct foo {
5719 int a;
5720 };
5721 };
5722 };
5723 }
5724 inline void take_type(a::b<4>::type) {}
5725 "};
5726 let rs = quote! {};
5727 run_test("", hdr, rs, &["take_type"], &[]);
5728}
5729
5730#[test]
5731fn test_bridge_conflict_ty() {
5732 let hdr = indoc! {"
5733 namespace a {
5734 struct Key { int a; };
5735 }
5736 namespace b {
5737 struct Key { int a; };
5738 }
5739 "};
5740 let rs = quote! {};
5741 run_test("", hdr, rs, &["a::Key", "b::Key"], &[]);
5742}
5743
5744#[test]
5745fn test_bridge_conflict_ty_fn() {
5746 let hdr = indoc! {"
5747 namespace a {
5748 struct Key { int a; };
5749 }
5750 namespace b {
5751 inline void Key() {}
5752 }
5753 "};
5754 let rs = quote! {};
5755 run_test("", hdr, rs, &["a::Key", "b::Key"], &[]);
5756}
5757
5758#[test]
5759fn test_issue_506() {
5760 let hdr = indoc! {"
5761 namespace std {
5762 template <class, class> class am;
5763 typedef am<char, char> an;
5764 } // namespace std
5765 namespace be {
5766 class bf {
5767 virtual std::an bg() = 0;
5768 };
5769 class bh : bf {};
5770 } // namespace be
5771 namespace spanner {
5772 class Database;
5773 class Row {
5774 public:
5775 Row(be::bh *);
5776 };
5777 } // namespace spanner
5778 "};
5779 let rs = quote! {};
5780 run_test("", hdr, rs, &["spanner::Database", "spanner::Row"], &[]);
5781}
5782
5783#[test]
5784fn test_private_inheritance() {
5785 let hdr = indoc! {"
5786 class A {
5787 public:
5788 void foo() {}
5789 int a;
5790 };
5791 class B : A {
5792 public:
5793 void bar() {}
5794 int b;
5795 };
5796 "};
5797 let rs = quote! {};
5798 run_test("", hdr, rs, &["A", "B"], &[]);
5799}
5800
5801#[test]
5802fn test_error_generated_for_static_data() {
5803 let hdr = indoc! {"
5804 #include <cstdint>
5805 struct A {
5806 A() {}
5807 uint32_t a;
5808 };
5809 static A FOO = A();
5810 "};
5811 let rs = quote! {};
5812 run_test_ex(
5813 "",
5814 hdr,
5815 rs,
5816 quote! { generate!("FOO")},
5817 None,
5818 Some(make_error_finder("FOO")),
5819 None,
5820 );
5821}
5822
5823#[test]
5824fn test_error_generated_for_array_dependent_function() {
5825 let hdr = indoc! {"
5826 #include <cstdint>
5827 #include <functional>
5828 inline void take_func(std::function<bool(const uint32_t number)>) {
5829 }
5830 "};
5831 let rs = quote! {};
5832 run_test_ex(
5833 "",
5834 hdr,
5835 rs,
5836 quote! { generate! ("take_func")},
5837 None,
5838 Some(make_error_finder("take_func")),
5839 None,
5840 );
5841}
5842
5843#[test]
5844#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
5845#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
5846fn test_error_generated_for_array_dependent_method() {
5847 let hdr = indoc! {"
5848 #include <cstdint>
5849 #include <functional>
5850 struct A {
5851 void take_func(std::function<bool(const uint32_t number)>) {
5852 }
5853 };
5854 "};
5855 let rs = quote! {};
5856 run_test_ex(
5857 "",
5858 hdr,
5859 rs,
5860 quote! { generate! ("A")},
5861 None,
5862 Some(make_string_finder(
5863 ["take_func", "couldn't be generated"]
5864 .map(|s| s.to_string())
5865 .to_vec(),
5866 )),
5867 None,
5868 );
5869}
5870
5871#[test]
5872fn test_error_generated_for_pod_with_nontrivial_destructor() {
5873 // take_a is necessary here because cxx won't generate the required
5874 // static assertions unless the type is actually used in some context
5875 // where cxx needs to decide it's trivial or non-trivial.
5876 let hdr = indoc! {"
5877 #include <cstdint>
5878 #include <functional>
5879 struct A {
5880 ~A() {}
5881 };
5882 inline void take_a(A) {}
5883 "};
5884 let rs = quote! {};
5885 run_test_expect_fail("", hdr, rs, &["take_a"], &["A"]);
5886}
5887
5888#[test]
5889fn test_error_generated_for_pod_with_nontrivial_move_constructor() {
5890 // take_a is necessary here because cxx won't generate the required
5891 // static assertions unless the type is actually used in some context
5892 // where cxx needs to decide it's trivial or non-trivial.
5893 let hdr = indoc! {"
5894 #include <cstdint>
5895 #include <functional>
5896 struct A {
5897 A() = default;
5898 A(A&&) {}
5899 };
5900 inline void take_a(A) {}
5901 "};
5902 let rs = quote! {};
5903 run_test_expect_fail("", hdr, rs, &["take_a"], &["A"]);
5904}
5905
5906#[test]
5907fn test_double_destruction() {
5908 let hdr = indoc! {"
5909 #include <stdio.h>
5910 #include <stdlib.h>
5911 // A simple type to let Rust verify the destructor is run.
5912 struct NotTriviallyDestructible {
5913 NotTriviallyDestructible() = default;
5914 NotTriviallyDestructible(const NotTriviallyDestructible&) = default;
5915 NotTriviallyDestructible(NotTriviallyDestructible&&) = default;
5916
5917 ~NotTriviallyDestructible() {}
5918 };
5919
5920 struct ExplicitlyDefaulted {
5921 ExplicitlyDefaulted() = default;
5922 ~ExplicitlyDefaulted() = default;
5923
5924 NotTriviallyDestructible flag;
5925 };
5926 "};
5927 let rs = quote! {
5928 moveit! {
5929 let mut moveit_t = ffi::ExplicitlyDefaulted::new();
5930 }
5931 };
5932 match do_run_test(
5933 "",
5934 hdr,
5935 rs,
5936 directives_from_lists(
5937 &[],
5938 &["NotTriviallyDestructible", "ExplicitlyDefaulted"],
5939 None,
5940 ),
5941 None,
5942 None,
5943 None,
5944 ) {
5945 Err(TestError::CppBuild(_)) => {} // be sure this fails due to a static_assert
5946 // rather than some runtime problem
5947 _ => panic!("Test didn't fail as expected"),
5948 };
5949}
5950
5951#[test]
5952fn test_keyword_function() {
5953 let hdr = indoc! {"
5954 inline void move(int) {};
5955 "};
5956 let rs = quote! {};
5957 run_test("", hdr, rs, &["move_"], &[]);
5958}
5959
5960#[test]
5961fn test_keyword_method() {
5962 let hdr = indoc! {"
5963 struct A {
5964 int a;
5965 inline void move() {};
5966 };
5967 "};
5968 let rs = quote! {};
5969 run_test("", hdr, rs, &["A"], &[]);
5970}
5971
5972#[test]
5973fn test_doc_passthru() {
5974 let hdr = indoc! {"
5975 #include <cstdint>
5976 /// Elephants!
5977 struct A {
5978 uint32_t a;
5979 };
5980 /// Giraffes!
5981 struct B {
5982 uint32_t a;
5983 };
5984 /// Rhinos!
5985 inline uint32_t get_a() { return 3; }
5986 "};
5987 let rs = quote! {};
5988 run_test_ex(
5989 "",
5990 hdr,
5991 rs,
5992 directives_from_lists(&["A", "get_a"], &["B"], None),
5993 None,
5994 Some(make_string_finder(
5995 ["Giraffes", "Elephants", "Rhinos"]
5996 .map(|s| s.to_string())
5997 .to_vec(),
5998 )),
5999 None,
6000 );
6001}
6002
6003#[test]
6004fn test_closure() {
6005 // Ensuring presence of this closure doesn't break other things
6006 let hdr = indoc! {"
6007 #include <functional>
6008 #include <cstdint>
6009
6010 inline bool take_closure(std::function<bool(const uint32_t number)> fn) {
6011 return fn(5);
6012 }
6013 inline uint32_t get_a() {
6014 return 3;
6015 }
6016 "};
6017 let rs = quote! {
6018 assert_eq!(ffi::get_a(), 3);
6019 };
6020 run_test("", hdr, rs, &["get_a"], &[]);
6021}
6022
6023#[test]
6024fn test_multiply_nested_inner_type() {
6025 let hdr = indoc! {"
6026 struct Turkey {
6027 struct Duck {
6028 struct Hen {
6029 int wings;
6030 };
6031 struct HenWithDefault {
6032 HenWithDefault() = default;
6033 int wings;
6034 };
6035 struct HenWithDestructor {
6036 ~HenWithDestructor() = default;
6037 int wings;
6038 };
6039 struct HenWithCopy {
6040 HenWithCopy() = default;
6041 HenWithCopy(const HenWithCopy&) = default;
6042 int wings;
6043 };
6044 struct HenWithMove {
6045 HenWithMove() = default;
6046 HenWithMove(HenWithMove&&) = default;
6047 int wings;
6048 };
6049 };
6050 };
6051 "};
6052 let rs = quote! {
6053 ffi::Turkey_Duck_Hen::new().within_unique_ptr();
6054 ffi::Turkey_Duck_HenWithDefault::new().within_unique_ptr();
6055 ffi::Turkey_Duck_HenWithDestructor::new().within_unique_ptr();
6056 ffi::Turkey_Duck_HenWithCopy::new().within_unique_ptr();
6057 ffi::Turkey_Duck_HenWithMove::new().within_unique_ptr();
6058
6059 moveit! {
6060 let hen = ffi::Turkey_Duck_Hen::new();
6061 let moved_hen = autocxx::moveit::new::mov(hen);
6062 let _copied_hen = autocxx::moveit::new::copy(moved_hen);
6063
6064 let hen = ffi::Turkey_Duck_HenWithDefault::new();
6065 let moved_hen = autocxx::moveit::new::mov(hen);
6066 let _copied_hen = autocxx::moveit::new::copy(moved_hen);
6067
6068 let _hen = ffi::Turkey_Duck_HenWithDestructor::new();
6069
6070 let hen = ffi::Turkey_Duck_HenWithCopy::new();
6071 let _copied_hen = autocxx::moveit::new::copy(hen);
6072
6073 let hen = ffi::Turkey_Duck_HenWithMove::new();
6074 let _moved_hen = autocxx::moveit::new::mov(hen);
6075 }
6076 };
6077 run_test(
6078 "",
6079 hdr,
6080 rs,
6081 &[],
6082 &[
6083 "Turkey_Duck_Hen",
6084 "Turkey_Duck_HenWithDefault",
6085 "Turkey_Duck_HenWithDestructor",
6086 "Turkey_Duck_HenWithCopy",
6087 "Turkey_Duck_HenWithMove",
6088 ],
6089 );
6090}
6091
6092#[test]
6093fn test_underscored_namespace_for_inner_type() {
6094 let hdr = indoc! {"
6095 namespace __foo {
6096 struct daft {
6097 struct bob {
6098 int a;
6099 };
6100 int a;
6101 };
6102 }
6103 inline void bar(__foo::daft::bob) {}
6104 "};
6105 let rs = quote! {};
6106 run_test("", hdr, rs, &["bar"], &[]);
6107}
6108
6109#[test]
6110fn test_blocklist_not_overly_broad() {
6111 // This is a regression test. We used to block anything that starts with "rust" or "std",
6112 // not just items in the "rust" and "std" namespaces. We therefore test that functions starting
6113 // with "rust" or "std" get imported.
6114 let hdr = indoc! {"
6115 inline void rust_func() { }
6116 inline void std_func() { }
6117 "};
6118 let rs = quote! {
6119 ffi::rust_func();
6120 ffi::std_func();
6121 };
6122 run_test("", hdr, rs, &["rust_func", "std_func"], &[]);
6123}
6124
6125#[test]
6126#[ignore] // https://github.com/google/autocxx/issues/837
6127fn test_ref_qualified_method() {
6128 let hdr = indoc! {"
6129 struct A {
6130 void foo() & {}
6131 };
6132 "};
6133 let rs = quote! {
6134 A::new().within_unique_ptr().foo();
6135 };
6136 run_test("", hdr, rs, &["A"], &[]);
6137}
6138
6139#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
6140#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
6141#[test]
6142fn test_stringview() {
6143 // Test that APIs using std::string_view do not otherwise cause errors.
6144 let hdr = indoc! {"
6145 #include <string_view>
6146 #include <string>
6147 void take_string_view(std::string_view) {}
6148 std::string_view return_string_view(const std::string& a) { return std::string_view(a); }
6149 "};
6150 let rs = quote! {};
6151 run_test_ex(
6152 "",
6153 hdr,
6154 rs,
6155 directives_from_lists(&["take_string_view", "return_string_view"], &[], None),
6156 make_cpp17_adder(),
6157 None,
6158 None,
6159 );
6160}
6161
6162#[test]
6163fn test_include_cpp_alone() {
6164 let hdr = indoc! {"
6165 #include <cstdint>
6166 inline uint32_t give_int() {
6167 return 5;
6168 }
6169 "};
6170 let hexathorpe = Token![#](Span::call_site());
6171 let rs = quote! {
6172 use autocxx::include_cpp;
6173 include_cpp! {
6174 #hexathorpe include "input.h"
6175 safety!(unsafe_ffi)
6176 generate!("give_int")
6177 }
6178 fn main() {
6179 assert_eq!(ffi::give_int(), 5);
6180 }
6181 };
6182 do_run_test_manual("", hdr, rs, None, None).unwrap();
6183}
6184
6185#[test]
6186fn test_include_cpp_in_path() {
6187 let hdr = indoc! {"
6188 #include <cstdint>
6189 inline uint32_t give_int() {
6190 return 5;
6191 }
6192 "};
6193 let hexathorpe = Token![#](Span::call_site());
6194 let rs = quote! {
6195 autocxx::include_cpp! {
6196 #hexathorpe include "input.h"
6197 safety!(unsafe_ffi)
6198 generate!("give_int")
6199 }
6200 fn main() {
6201 assert_eq!(ffi::give_int(), 5);
6202 }
6203 };
6204 do_run_test_manual("", hdr, rs, None, None).unwrap();
6205}
6206
6207#[test]
6208fn test_bitset() {
6209 let hdr = indoc! {"
6210 #include <cstddef>
6211 template <size_t _N_words, size_t _Size>
6212 class __bitset
6213 {
6214 public:
6215 typedef size_t __storage_type;
6216 __storage_type __first_[_N_words];
6217 inline bool all() {
6218 return false;
6219 }
6220 };
6221
6222 template <size_t _Size>
6223 class bitset
6224 : private __bitset<_Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) * 8) + 1, _Size>
6225 {
6226 public:
6227 static const unsigned __n_words = _Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) * 8) + 1;
6228 typedef __bitset<__n_words, _Size> base;
6229 bool all() const noexcept;
6230 };
6231
6232
6233 typedef bitset<1> mybitset;
6234 "};
6235
6236 let rs = quote! {};
6237
6238 run_test_ex(
6239 "",
6240 hdr,
6241 rs,
6242 quote! {
6243 generate_all!()
6244 },
6245 None,
6246 None,
6247 None,
6248 );
6249}
6250
6251#[test]
6252fn test_cint_vector() {
6253 let hdr = indoc! {"
6254 #include <vector>
6255 #include <cstdint>
6256 inline std::vector<int32_t> give_vec() {
6257 return std::vector<int32_t> {1,2};
6258 }
6259 "};
6260
6261 let rs = quote! {
6262 assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[1,2]);
6263 };
6264
6265 run_test("", hdr, rs, &["give_vec"], &[]);
6266}
6267
6268#[test]
6269#[ignore] // https://github.com/google/autocxx/issues/422
6270fn test_int_vector() {
6271 let hdr = indoc! {"
6272 #include <vector>
6273 std::vector<int> give_vec() {
6274 return std::vector<int> {1,2};
6275 }
6276 "};
6277
6278 let rs = quote! {
6279 assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[autocxx::c_int(1),autocxx::c_int(2)]);
6280 };
6281
6282 run_test("", hdr, rs, &["give_vec"], &[]);
6283}
6284
6285#[test]
6286fn test_size_t() {
6287 let hdr = indoc! {"
6288 #include <cstddef>
6289 inline size_t get_count() { return 7; }
6290 "};
6291
6292 let rs = quote! {
6293 ffi::get_count();
6294 };
6295
6296 run_test_ex(
6297 "",
6298 hdr,
6299 rs,
6300 directives_from_lists(&["get_count"], &[], None),
6301 None,
6302 Some(make_rust_code_finder(vec![
6303 quote! {fn get_count() -> usize},
6304 ])),
6305 None,
6306 );
6307}
6308
6309#[test]
6310fn test_deleted_function() {
6311 // We shouldn't generate bindings for deleted functions.
6312 // The test is successful if the bindings compile, i.e. if autocxx doesn't
6313 // attempt to call the deleted function.
6314 let hdr = indoc! {"
6315 class A {
6316 public:
6317 void foo() = delete;
6318 };
6319 "};
6320 let rs = quote! {};
6321 run_test("", hdr, rs, &["A"], &[]);
6322}
6323
6324#[test]
6325fn test_ignore_move_constructor() {
6326 let hdr = indoc! {"
6327 class A {
6328 public:
6329 A() {}
6330 A(A&&) {};
6331 };
6332 "};
6333 let rs = quote! {};
6334 run_test("", hdr, rs, &["A"], &[]);
6335}
6336
6337#[test]
6338fn test_ignore_function_with_rvalue_ref() {
6339 let hdr = indoc! {"
6340 #include <string>
6341
6342 void moveme(std::string &&);
6343 "};
6344 let rs = quote! {};
6345 run_test("", hdr, rs, &["moveme"], &[]);
6346}
6347
6348#[test]
6349fn test_take_nonpod_rvalue_from_up() {
6350 let hdr = indoc! {"
6351 #include <string>
6352 struct A {
6353 std::string a;
6354 };
6355 inline void take_a(A&&) {};
6356 "};
6357 let rs = quote! {
6358 let a = ffi::A::new().within_unique_ptr();
6359 ffi::take_a(a);
6360
6361 let a2 = ffi::A::new().within_box();
6362 ffi::take_a(a2);
6363 };
6364 run_test("", hdr, rs, &["A", "take_a"], &[]);
6365}
6366
6367#[test]
6368fn test_take_nonpod_rvalue_from_stack() {
6369 let hdr = indoc! {"
6370 #include <string>
6371 struct A {
6372 std::string a;
6373 };
6374 inline void take_a(A&&) {};
6375 "};
6376 let rs = quote! {
6377 moveit! { let a = ffi::A::new() };
6378 ffi::take_a(a);
6379 };
6380 run_test("", hdr, rs, &["A", "take_a"], &[]);
6381}
6382
6383#[test]
6384fn test_overloaded_ignored_function() {
6385 // When overloaded functions are ignored during import, the placeholder
6386 // functions generated for them should have unique names, just as they
6387 // would have if they had been imported successfully.
6388 // The test is successful if the bindings compile.
6389 let hdr = indoc! {"
6390 struct Blocked {};
6391 class A {
6392 public:
6393 void take_blocked(Blocked);
6394 void take_blocked(Blocked, int);
6395 };
6396 "};
6397 let rs = quote! {};
6398 run_test_ex(
6399 "",
6400 hdr,
6401 rs,
6402 quote! {
6403 generate!("A")
6404 block!("Blocked")
6405 },
6406 None,
6407 None,
6408 None,
6409 );
6410}
6411
6412#[test]
6413fn test_namespaced_constant() {
6414 let hdr = indoc! {"
6415 namespace A {
6416 const int kConstant = 3;
6417 }
6418 "};
6419 let rs = quote! {
6420 assert_eq!(ffi::A::kConstant, 3);
6421 };
6422 run_test("", hdr, rs, &["A::kConstant"], &[]);
6423}
6424
6425#[test]
6426fn test_issue_470_492() {
6427 let hdr = indoc! {"
6428 namespace std {
6429 template <bool, typename _Iftrue, typename _Iffalse> struct a;
6430 }
6431 template <typename> struct b;
6432 template <typename d> struct c {
6433 typedef std::a<b<d>::c, int, int> e;
6434 };
6435 "};
6436 let rs = quote! {};
6437 run_test_ex(
6438 "",
6439 hdr,
6440 rs,
6441 quote! {
6442 generate_all!()
6443 },
6444 None,
6445 None,
6446 None,
6447 );
6448}
6449
6450#[test]
6451fn test_no_impl() {
6452 let hdr = indoc! {"
6453 struct A {
6454 int a;
6455 };
6456 "};
6457 let rs = quote! {};
6458 run_test_ex(
6459 "",
6460 hdr,
6461 rs,
6462 quote! {
6463 exclude_impls!()
6464 exclude_utilities!()
6465 generate!("A")
6466 },
6467 None,
6468 None,
6469 None,
6470 );
6471}
6472
6473#[test]
6474fn test_generate_all() {
6475 let hdr = indoc! {"
6476 #include <cstdint>
6477 inline uint32_t give_int() {
6478 return 5;
6479 }
6480 "};
6481 let rs = quote! {
6482 assert_eq!(ffi::give_int(), 5);
6483 };
6484 run_test_ex(
6485 "",
6486 hdr,
6487 rs,
6488 quote! {
6489 generate_all!()
6490 },
6491 None,
6492 None,
6493 None,
6494 );
6495}
6496
6497#[test]
6498fn test_std_thing() {
6499 let hdr = indoc! {"
6500 #include <cstdint>
6501 namespace std {
6502 struct A {
6503 uint8_t a;
6504 };
6505 }
6506 typedef char daft;
6507 "};
6508 let rs = quote! {};
6509 run_test_ex(
6510 "",
6511 hdr,
6512 rs,
6513 quote! {
6514 generate_all!()
6515 },
6516 None,
6517 None,
6518 None,
6519 );
6520}
6521
6522#[test]
6523fn test_two_mods() {
6524 let hdr = indoc! {"
6525 #include <cstdint>
6526 struct A {
6527 uint32_t a;
6528 };
6529 inline A give_a() {
6530 A a;
6531 a.a = 5;
6532 return a;
6533 }
6534 inline uint32_t get_a(A a) {
6535 return a.a;
6536 }
6537 struct B {
6538 uint32_t a;
6539 };
6540 inline B give_b() {
6541 B a;
6542 a.a = 8;
6543 return a;
6544 }
6545 inline uint32_t get_b(B a) {
6546 return a.a;
6547 }
6548 "};
6549 let hexathorpe = Token![#](Span::call_site());
6550 let rs = quote! {
6551 use autocxx::prelude::*;
6552 include_cpp! {
6553 #hexathorpe include "input.h"
6554 safety!(unsafe_ffi)
6555 generate!("give_a")
6556 generate!("get_a")
6557 }
6558 include_cpp! {
6559 #hexathorpe include "input.h"
6560 name!(ffi2)
6561 generate!("give_b")
6562 generate!("get_b")
6563 }
6564 fn main() {
6565 let a = ffi::give_a().within_unique_ptr();
6566 assert_eq!(ffi::get_a(a), 5);
6567 let b = unsafe { ffi2::give_b().within_unique_ptr() };
6568 assert_eq!(unsafe { ffi2::get_b(b) }, 8);
6569 }
6570 };
6571 do_run_test_manual("", hdr, rs, None, None).unwrap();
6572}
6573
6574#[test]
6575fn test_manual_bridge() {
6576 let hdr = indoc! {"
6577 #include <cstdint>
6578 inline uint32_t give_int() {
6579 return 5;
6580 }
6581 inline uint32_t give_int2() {
6582 return 5;
6583 }
6584 "};
6585 let hexathorpe = Token![#](Span::call_site());
6586 let rs = quote! {
6587 autocxx::include_cpp! {
6588 #hexathorpe include "input.h"
6589 safety!(unsafe_ffi)
6590 generate!("give_int")
6591 }
6592 #[cxx::bridge]
6593 mod ffi2 {
6594 unsafe extern "C++" {
6595 include!("input.h");
6596 fn give_int2() -> u32;
6597 }
6598 }
6599 fn main() {
6600 assert_eq!(ffi::give_int(), 5);
6601 assert_eq!(ffi2::give_int2(), 5);
6602 }
6603 };
6604 do_run_test_manual("", hdr, rs, None, None).unwrap();
6605}
6606
6607#[test]
6608fn test_manual_bridge_mixed_types() {
6609 let hdr = indoc! {"
6610 #include <memory>
6611 struct A {
6612 int a;
6613 };
6614 inline int take_A(const A& a) {
6615 return a.a;
6616 }
6617 inline std::unique_ptr<A> give_A() {
6618 auto a = std::make_unique<A>();
6619 a->a = 5;
6620 return a;
6621 }
6622 "};
6623 let hexathorpe = Token![#](Span::call_site());
6624 let rs = quote! {
6625 use autocxx::prelude::*;
6626 autocxx::include_cpp! {
6627 #hexathorpe include "input.h"
6628 safety!(unsafe_ffi)
6629 generate!("take_A")
6630 generate!("A")
6631 }
6632 #[cxx::bridge]
6633 mod ffi2 {
6634 unsafe extern "C++" {
6635 include!("input.h");
6636 type A = crate::ffi::A;
6637 fn give_A() -> UniquePtr<A>;
6638 }
6639 }
6640 fn main() {
6641 let a = ffi2::give_A();
6642 assert_eq!(ffi::take_A(&a), autocxx::c_int(5));
6643 }
6644 };
6645 do_run_test_manual("", hdr, rs, None, None).unwrap();
6646}
6647
6648#[test]
6649fn test_extern_cpp_type_cxx_bridge() {
6650 let hdr = indoc! {"
6651 #include <cstdint>
6652 struct A {
6653 A() : a(0) {}
6654 int a;
6655 };
6656 inline void handle_a(const A&) {
6657 }
6658 inline A create_a() {
6659 A a;
6660 return a;
6661 }
6662 "};
6663 let hexathorpe = Token![#](Span::call_site());
6664 let rs = quote! {
6665 use autocxx::prelude::*;
6666 include_cpp! {
6667 #hexathorpe include "input.h"
6668 safety!(unsafe_ffi)
6669 generate!("handle_a")
6670 generate!("create_a")
6671 extern_cpp_opaque_type!("A", crate::ffi2::A)
6672 }
6673 #[cxx::bridge]
6674 pub mod ffi2 {
6675 unsafe extern "C++" {
6676 include!("input.h");
6677 type A;
6678 }
6679 impl UniquePtr<A> {}
6680 }
6681 fn main() {
6682 let a = ffi::create_a();
6683 ffi::handle_a(&a);
6684 }
6685 };
6686 do_run_test_manual("", hdr, rs, None, None).unwrap();
6687}
6688
6689#[test]
6690fn test_extern_cpp_type_two_include_cpp() {
6691 let hdr = indoc! {"
6692 #include <cstdint>
6693 struct A {
6694 A() : a(0) {}
6695 int a;
6696 };
6697 enum B {
6698 VARIANT,
6699 };
6700 inline void handle_a(const A&) {
6701 }
6702 inline A create_a(B) {
6703 A a;
6704 return a;
6705 }
6706 "};
6707 let hexathorpe = Token![#](Span::call_site());
6708 let rs = quote! {
6709 pub mod base {
6710 autocxx::include_cpp! {
6711 #hexathorpe include "input.h"
6712 name!(ffi2)
6713 safety!(unsafe_ffi)
6714 generate!("A")
6715 generate!("B")
6716 }
6717 pub use ffi2::*;
6718 }
6719 pub mod dependent {
6720 autocxx::include_cpp! {
6721 #hexathorpe include "input.h"
6722 safety!(unsafe_ffi)
6723 generate!("handle_a")
6724 generate!("create_a")
6725 extern_cpp_type!("A", crate::base::A)
6726 extern_cpp_type!("B", super::super::base::B)
6727 pod!("B")
6728 }
6729 pub use ffi::*;
6730 }
6731 fn main() {
6732 use autocxx::prelude::*;
6733 let a = dependent::create_a(base::B::VARIANT).within_box();
6734 dependent::handle_a(&a);
6735 }
6736 };
6737 do_run_test_manual("", hdr, rs, None, None).unwrap();
6738}
6739
6740#[test]
6741#[ignore] // because we currently require UniquePtrTarget which this can't implement
6742fn test_extern_cpp_type_manual() {
6743 let hdr = indoc! {"
6744 #include <cstdint>
6745 struct A {
6746 int a;
6747 };
6748 inline void handle_a(const A& a) {
6749 }
6750 inline A create_a() {
6751 A a;
6752 return a;
6753 }
6754 "};
6755 let hexathorpe = Token![#](Span::call_site());
6756 let rs = quote! {
6757 autocxx::include_cpp! {
6758 #hexathorpe include "input.h"
6759 safety!(unsafe_ffi)
6760 generate!("handle_a")
6761 generate!("create_a")
6762 extern_cpp_type!("A", crate::ffi2::A)
6763 }
6764 pub mod ffi2 {
6765 use autocxx::cxx::{type_id, ExternType};
6766 #[repr(C)]
6767 pub struct A {
6768 a: std::os::raw::c_int
6769 }
6770 unsafe impl ExternType for A {
6771 type Kind = autocxx::cxx::kind::Opaque;
6772 type Id = type_id!("A");
6773 }
6774
6775 }
6776 fn main() {
6777 let a = ffi2::A { a: 3 };
6778 ffi::handle_a(&a);
6779 }
6780 };
6781 do_run_test_manual("", hdr, rs, None, None).unwrap();
6782}
6783
6784#[test]
6785fn test_issue486() {
6786 let hdr = indoc! {"
6787 namespace a {
6788 namespace spanner {
6789 class Key;
6790 }
6791 } // namespace a
6792 namespace spanner {
6793 class Key {
6794 public:
6795 bool b(a::spanner::Key &);
6796 };
6797 } // namespace spanner
6798 "};
6799 let rs = quote! {};
6800 run_test("", hdr, rs, &["spanner::Key"], &[]);
6801}
6802
6803#[test]
6804#[ignore]
6805fn test_issue616() {
6806 let hdr = indoc! {"
6807 namespace N {
6808 template <typename> class B{};
6809 template <typename c> class C {
6810 public:
6811 using U = B<c>;
6812 };
6813 }
6814 class A : N::C<A> {
6815 U u;
6816 };
6817 "};
6818 let rs = quote! {};
6819 run_test("", hdr, rs, &["A"], &[]);
6820}
6821
6822#[test]
6823fn test_shared_ptr() {
6824 let hdr = indoc! {"
6825 #include <memory>
6826 struct A {
6827 int a;
6828 };
6829 inline std::shared_ptr<A> make_shared_int() {
6830 return std::make_shared<A>(A { 3 });
6831 }
6832 inline int take_shared_int(std::shared_ptr<A> a) {
6833 return a->a;
6834 }
6835 inline std::weak_ptr<A> shared_to_weak(std::shared_ptr<A> a) {
6836 return std::weak_ptr<A>(a);
6837 }
6838 "};
6839 let rs = quote! {
6840 let a = ffi::make_shared_int();
6841 assert_eq!(ffi::take_shared_int(a.clone()), autocxx::c_int(3));
6842 ffi::shared_to_weak(a).upgrade();
6843 };
6844 run_test(
6845 "",
6846 hdr,
6847 rs,
6848 &["make_shared_int", "take_shared_int", "shared_to_weak"],
6849 &[],
6850 );
6851}
6852
6853#[test]
6854#[ignore] // https://github.com/google/autocxx/issues/799
6855fn test_shared_ptr_const() {
6856 let hdr = indoc! {"
6857 #include <memory>
6858 inline std::shared_ptr<const int> make_shared_int() {
6859 return std::make_shared<const int>(3);
6860 }
6861 inline int take_shared_int(std::shared_ptr<const int> a) {
6862 return *a;
6863 }
6864 "};
6865 let rs = quote! {
6866 let a = ffi::make_shared_int();
6867 assert_eq!(ffi::take_shared_int(a.clone()), autocxx::c_int(3));
6868 };
6869 run_test("", hdr, rs, &["make_shared_int", "take_shared_int"], &[]);
6870}
6871
6872#[test]
6873fn test_rust_reference() {
6874 let hdr = indoc! {"
6875 #include <cstdint>
6876
6877 struct RustType;
6878 inline uint32_t take_rust_reference(const RustType&) {
6879 return 4;
6880 }
6881 "};
6882 let rs = quote! {
6883 let foo = RustType(3);
6884 assert_eq!(ffi::take_rust_reference(&foo), 4);
6885 };
6886 run_test_ex(
6887 "",
6888 hdr,
6889 rs,
6890 quote! {
6891 generate!("take_rust_reference")
6892 extern_rust_type!(RustType)
6893 },
6894 None,
6895 None,
6896 Some(quote! {
6897 pub struct RustType(i32);
6898 }),
6899 );
6900}
6901
6902#[test]
6903fn test_rust_reference_autodiscover() {
6904 let hdr = indoc! {"
6905 #include <cstdint>
6906
6907 struct RustType;
6908 inline uint32_t take_rust_reference(const RustType&) {
6909 return 4;
6910 }
6911 "};
6912 let rs = quote! {
6913 let foo = RustType(3);
6914 let result = ffi::take_rust_reference(&foo);
6915 assert_eq!(result, 4);
6916 };
6917 run_test_ex(
6918 "",
6919 hdr,
6920 rs,
6921 quote! {},
6922 Some(Box::new(EnableAutodiscover)),
6923 None,
6924 Some(quote! {
6925 #[autocxx::extern_rust::extern_rust_type]
6926 pub struct RustType(i32);
6927 }),
6928 );
6929}
6930
6931#[test]
6932fn test_pass_thru_rust_reference() {
6933 let hdr = indoc! {"
6934 #include <cstdint>
6935
6936 struct RustType;
6937 inline const RustType& pass_rust_reference(const RustType& a) {
6938 return a;
6939 }
6940 "};
6941 let rs = quote! {
6942 let foo = RustType(3);
6943 assert_eq!(ffi::pass_rust_reference(&foo).0, 3);
6944 };
6945 run_test_ex(
6946 "",
6947 hdr,
6948 rs,
6949 quote! {
6950 generate!("pass_rust_reference")
6951 extern_rust_type!(RustType)
6952 },
6953 None,
6954 None,
6955 Some(quote! {
6956 pub struct RustType(i32);
6957 }),
6958 );
6959}
6960
6961#[test]
6962fn test_extern_rust_method() {
6963 let hdr = indoc! {"
6964 #include <cstdint>
6965 struct RustType;
6966 uint32_t examine(const RustType& foo);
6967 "};
6968 let cxx = indoc! {"
6969 uint32_t examine(const RustType& foo) {
6970 return foo.get();
6971 }"};
6972 let rs = quote! {
6973 let a = RustType(74);
6974 assert_eq!(ffi::examine(&a), 74);
6975 };
6976 run_test_ex(
6977 cxx,
6978 hdr,
6979 rs,
6980 directives_from_lists(&["examine"], &[], None),
6981 Some(Box::new(EnableAutodiscover)),
6982 None,
6983 Some(quote! {
6984 #[autocxx::extern_rust::extern_rust_type]
6985 pub struct RustType(i32);
6986 impl RustType {
6987 #[autocxx::extern_rust::extern_rust_function]
6988 pub fn get(&self) -> i32 {
6989 return self.0
6990 }
6991 }
6992 }),
6993 );
6994}
6995
6996#[test]
6997fn test_rust_reference_no_autodiscover() {
6998 let hdr = indoc! {"
6999 #include <cstdint>
7000
7001 struct RustType;
7002 inline uint32_t take_rust_reference(const RustType&) {
7003 return 4;
7004 }
7005 "};
7006 let rs = quote! {
7007 let foo = RustType(3);
7008 let result = ffi::take_rust_reference(&foo);
7009 assert_eq!(result, 4);
7010 };
7011 run_test_ex(
7012 "",
7013 hdr,
7014 rs,
7015 directives_from_lists(&["take_rust_reference"], &[], None),
7016 None,
7017 None,
7018 Some(quote! {
7019 #[autocxx::extern_rust::extern_rust_type]
7020 pub struct RustType(i32);
7021 }),
7022 );
7023}
7024
7025#[test]
7026#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
7027// TODO - replace make_clang_arg_adder with something that knows how to add an MSVC-suitable
7028// directive for the cc build.
7029fn test_cpp17() {
7030 let hdr = indoc! {"
7031 static_assert(__cplusplus >= 201703L, \"This file expects a C++17 compatible compiler.\");
7032 inline void foo() {}
7033 "};
7034 run_test_ex(
7035 "",
7036 hdr,
7037 quote! {
7038 ffi::foo();
7039 },
7040 quote! {
7041 generate!("foo")
7042 },
7043 make_cpp17_adder(),
7044 None,
7045 None,
7046 );
7047}
7048
7049#[test]
7050fn test_box() {
7051 let hdr = indoc! {"
7052 #include <cxx.h>
7053 struct Foo;
7054 inline void take_box(rust::Box<Foo>) {
7055 }
7056 "};
7057 run_test_ex(
7058 "",
7059 hdr,
7060 quote! {
7061 ffi::take_box(Box::new(Foo { a: "Hello".into() }))
7062 },
7063 quote! {
7064 generate!("take_box")
7065 extern_rust_type!(Foo)
7066 },
7067 None,
7068 None,
7069 Some(quote! {
7070 pub struct Foo {
7071 a: String,
7072 }
7073 }),
7074 );
7075}
7076
7077#[test]
7078fn test_box_via_extern_rust() {
7079 let hdr = indoc! {"
7080 #include <cxx.h>
7081 struct Foo;
7082 inline void take_box(rust::Box<Foo>) {
7083 }
7084 "};
7085 run_test_ex(
7086 "",
7087 hdr,
7088 quote! {
7089 ffi::take_box(Box::new(Foo { a: "Hello".into() }))
7090 },
7091 quote! {},
7092 Some(Box::new(EnableAutodiscover)),
7093 None,
7094 Some(quote! {
7095 #[autocxx::extern_rust::extern_rust_type]
7096 pub struct Foo {
7097 a: String,
7098 }
7099 }),
7100 );
7101}
7102
7103#[test]
7104fn test_box_via_extern_rust_in_mod() {
7105 let hdr = indoc! {"
7106 #include <cxx.h>
7107 struct Foo;
7108 inline void take_box(rust::Box<Foo>) {
7109 }
7110 "};
7111 run_test_ex(
7112 "",
7113 hdr,
7114 quote! {
7115 ffi::take_box(Box::new(bar::Foo { a: "Hello".into() }))
7116 },
7117 quote! {},
7118 Some(Box::new(EnableAutodiscover)),
7119 None,
7120 Some(quote! {
7121 mod bar {
7122 #[autocxx::extern_rust::extern_rust_type]
7123 pub struct Foo {
7124 pub a: String,
7125 }
7126 }
7127 }),
7128 );
7129}
7130
7131#[test]
7132fn test_extern_rust_fn_simple() {
7133 let cpp = indoc! {"
7134 void foo() {
7135 my_rust_fun();
7136 }
7137 "};
7138 let hdr = indoc! {"
7139 #include <cxx.h>
7140 inline void do_thing() {}
7141 "};
7142 run_test_ex(
7143 cpp,
7144 hdr,
7145 quote! {
7146 ffi::do_thing();
7147 },
7148 quote! {
7149 generate!("do_thing")
7150 },
7151 Some(Box::new(EnableAutodiscover)),
7152 None,
7153 Some(quote! {
7154 #[autocxx::extern_rust::extern_rust_function]
7155 fn my_rust_fun() {
7156 }
7157 }),
7158 );
7159}
7160
7161#[test]
7162fn test_extern_rust_fn_in_mod() {
7163 let hdr = indoc! {"
7164 #include <cxx.h>
7165 inline void do_thing() {}
7166 "};
7167 run_test_ex(
7168 "",
7169 hdr,
7170 quote! {},
7171 quote! {
7172 generate!("do_thing")
7173 },
7174 Some(Box::new(EnableAutodiscover)),
7175 None,
7176 Some(quote! {
7177 mod bar {
7178 #[autocxx::extern_rust::extern_rust_function]
7179 pub fn my_rust_fun() {
7180
7181 }
7182 }
7183 }),
7184 );
7185}
7186
7187#[test]
7188fn test_issue_956() {
7189 let hdr = indoc! {"
7190 #include <cstdint>
7191 inline void take_int(int&) {}
7192 inline void take_uin16(uint16_t&) {}
7193 inline void take_char16(char16_t &) {}
7194 "};
7195 run_test(
7196 "",
7197 hdr,
7198 quote! {},
7199 &["take_int", "take_uin16", "take_char16"],
7200 &[],
7201 );
7202}
7203
7204#[test]
7205fn test_extern_rust_fn_no_autodiscover() {
7206 let hdr = indoc! {"
7207 #include <cxx.h>
7208 "};
7209 let cpp = indoc! {"
7210 void call_it() {
7211 my_rust_fun();
7212 }
7213 "};
7214 run_test_ex(
7215 cpp,
7216 hdr,
7217 quote! {},
7218 quote! {},
7219 None,
7220 None,
7221 Some(quote! {
7222 mod bar {
7223 #[autocxx::extern_rust::extern_rust_function]
7224 pub fn my_rust_fun() {
7225
7226 }
7227 }
7228 }),
7229 );
7230}
7231
7232#[test]
7233fn test_pv_subclass_mut() {
7234 let hdr = indoc! {"
7235 #include <cstdint>
7236
7237 class Observer {
7238 public:
7239 Observer() {}
7240 virtual void foo() = 0;
7241 virtual ~Observer() {}
7242 };
7243 inline void bar() {}
7244 "};
7245 run_test_ex(
7246 "",
7247 hdr,
7248 quote! {
7249 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7250 },
7251 quote! {
7252 generate!("bar")
7253 subclass!("Observer",MyObserver)
7254 },
7255 None,
7256 None,
7257 Some(quote! {
7258 use autocxx::subclass::CppSubclass;
7259 use ffi::Observer_methods;
7260 #[autocxx::subclass::subclass]
7261 pub struct MyObserver {
7262 a: u32
7263 }
7264 impl Observer_methods for MyObserver {
7265 fn foo(&mut self) {
7266 }
7267 }
7268 }),
7269 );
7270}
7271
7272#[test]
7273fn test_pv_subclass_const() {
7274 let hdr = indoc! {"
7275 #include <cstdint>
7276
7277 class Observer {
7278 public:
7279 Observer() {}
7280 virtual void foo() const = 0;
7281 virtual ~Observer() {}
7282 };
7283 inline void bar() {}
7284 "};
7285 run_test_ex(
7286 "",
7287 hdr,
7288 quote! {
7289 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7290 },
7291 quote! {
7292 generate!("bar")
7293 subclass!("Observer",MyObserver)
7294 },
7295 None,
7296 None,
7297 Some(quote! {
7298 use autocxx::subclass::CppSubclass;
7299 use ffi::Observer_methods;
7300 #[autocxx::subclass::subclass]
7301 pub struct MyObserver {
7302 a: u32
7303 }
7304 impl Observer_methods for MyObserver {
7305 fn foo(&self) {
7306 }
7307 }
7308 }),
7309 );
7310}
7311
7312#[test]
7313fn test_pv_subclass_calls_impossible() {
7314 let hdr = indoc! {"
7315 #include <cstdint>
7316
7317 class Observer {
7318 public:
7319 Observer() {}
7320 virtual void foo() const = 0;
7321 virtual ~Observer() {}
7322 };
7323 inline void bar() {}
7324 "};
7325 run_test_expect_fail_ex(
7326 "",
7327 hdr,
7328 quote! {
7329 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7330 },
7331 quote! {
7332 generate!("bar")
7333 subclass!("Observer",MyObserver)
7334 },
7335 None,
7336 None,
7337 Some(quote! {
7338 use autocxx::subclass::CppSubclass;
7339 use ffi::Observer_methods;
7340 #[autocxx::subclass::subclass]
7341 pub struct MyObserver {
7342 a: u32
7343 }
7344 impl Observer_methods for MyObserver {
7345 fn foo(&self) {
7346 use ffi::Observer_supers;
7347 self.foo_super()
7348 }
7349 }
7350 }),
7351 );
7352}
7353
7354#[test]
7355fn test_pv_subclass_not_pub() {
7356 let hdr = indoc! {"
7357 #include <cstdint>
7358
7359 class Observer {
7360 public:
7361 Observer() {}
7362 virtual void foo() const = 0;
7363 virtual ~Observer() {}
7364 };
7365 inline void bar() {}
7366 "};
7367 run_test_expect_fail_ex(
7368 "",
7369 hdr,
7370 quote! {
7371 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7372 },
7373 quote! {
7374 generate!("bar")
7375 subclass!("Observer",MyObserver)
7376 },
7377 None,
7378 None,
7379 Some(quote! {
7380 use autocxx::subclass::CppSubclass;
7381 use ffi::Observer_methods;
7382 #[autocxx::subclass::subclass]
7383 struct MyObserver {
7384 a: u32
7385 }
7386 impl Observer_methods for MyObserver {
7387 fn foo(&self) {
7388 }
7389 }
7390 }),
7391 );
7392}
7393
7394#[test]
7395fn test_pv_subclass_ptr_param() {
7396 let hdr = indoc! {"
7397 #include <cstdint>
7398 struct A {
7399 uint8_t a;
7400 };
7401
7402 class Observer {
7403 public:
7404 Observer() {}
7405 virtual void foo(const A*) const {};
7406 virtual ~Observer() {}
7407 };
7408 "};
7409 run_test_ex(
7410 "",
7411 hdr,
7412 quote! {
7413 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7414 },
7415 quote! {
7416 generate!("A")
7417 subclass!("Observer",MyObserver)
7418 },
7419 None,
7420 None,
7421 Some(quote! {
7422 use autocxx::subclass::CppSubclass;
7423 use ffi::Observer_methods;
7424 #[autocxx::subclass::subclass]
7425 pub struct MyObserver {
7426 a: u32
7427 }
7428 impl Observer_methods for MyObserver {
7429 unsafe fn foo(&self, a: *const ffi::A) {
7430 use ffi::Observer_supers;
7431 self.foo_super(a)
7432 }
7433 }
7434 }),
7435 );
7436}
7437
7438#[test]
7439fn test_pv_subclass_return() {
7440 let hdr = indoc! {"
7441 #include <cstdint>
7442
7443 class Observer {
7444 public:
7445 Observer() {}
7446 virtual uint32_t foo() const = 0;
7447 virtual ~Observer() {}
7448 };
7449 inline void bar() {}
7450 "};
7451 run_test_ex(
7452 "",
7453 hdr,
7454 quote! {
7455 MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7456 },
7457 quote! {
7458 generate!("bar")
7459 subclass!("Observer",MyObserver)
7460 },
7461 None,
7462 None,
7463 Some(quote! {
7464 use autocxx::subclass::CppSubclass;
7465 use ffi::Observer_methods;
7466 #[autocxx::subclass::subclass]
7467 pub struct MyObserver {
7468 a: u32
7469 }
7470 impl Observer_methods for MyObserver {
7471 fn foo(&self) -> u32 {
7472 4
7473 }
7474 }
7475 }),
7476 );
7477}
7478
7479#[test]
7480fn test_pv_subclass_passed_to_fn() {
7481 let hdr = indoc! {"
7482 #include <cstdint>
7483
7484 class Observer {
7485 public:
7486 Observer() {}
7487 virtual uint32_t foo() const = 0;
7488 virtual ~Observer() {}
7489 };
7490 inline void take_observer(const Observer&) {}
7491 "};
7492 run_test_ex(
7493 "",
7494 hdr,
7495 quote! {
7496 let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7497 ffi::take_observer(o.borrow().as_ref());
7498 },
7499 quote! {
7500 generate!("take_observer")
7501 subclass!("Observer",MyObserver)
7502 },
7503 None,
7504 None,
7505 Some(quote! {
7506 use autocxx::subclass::CppSubclass;
7507 use ffi::Observer_methods;
7508 #[autocxx::subclass::subclass]
7509 pub struct MyObserver {
7510 a: u32
7511 }
7512 impl Observer_methods for MyObserver {
7513 fn foo(&self) -> u32 {
7514 4
7515 }
7516 }
7517 }),
7518 );
7519}
7520
7521#[test]
7522fn test_pv_subclass_derive_defaults() {
7523 let hdr = indoc! {"
7524 #include <cstdint>
7525
7526 class Observer {
7527 public:
7528 Observer() {}
7529 virtual uint32_t foo() const = 0;
7530 virtual ~Observer() {}
7531 };
7532 inline void take_observer(const Observer&) {}
7533 "};
7534 run_test_ex(
7535 "",
7536 hdr,
7537 quote! {
7538 use autocxx::subclass::CppSubclassDefault;
7539 let o = MyObserver::default_rust_owned();
7540 ffi::take_observer(o.borrow().as_ref());
7541 },
7542 quote! {
7543 generate!("take_observer")
7544 subclass!("Observer",MyObserver)
7545 },
7546 None,
7547 None,
7548 Some(quote! {
7549 #[autocxx::subclass::subclass]
7550 #[derive(Default)]
7551 pub struct MyObserver {
7552 a: u32
7553 }
7554 impl ffi::Observer_methods for MyObserver {
7555 fn foo(&self) -> u32 {
7556 4
7557 }
7558 }
7559 }),
7560 );
7561}
7562
7563#[test]
7564fn test_non_pv_subclass_simple() {
7565 let hdr = indoc! {"
7566 #include <cstdint>
7567
7568 class Observer {
7569 public:
7570 Observer() {}
7571 virtual void foo() const {}
7572 virtual ~Observer() {}
7573 };
7574 inline void bar() {}
7575 "};
7576 run_test_ex(
7577 "",
7578 hdr,
7579 quote! {
7580 let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7581 obs.borrow().foo();
7582 },
7583 quote! {
7584 generate!("bar")
7585 subclass!("Observer",MyObserver)
7586 },
7587 None,
7588 None,
7589 Some(quote! {
7590 use autocxx::subclass::CppSubclass;
7591 use ffi::Observer_methods;
7592 #[autocxx::subclass::subclass]
7593 pub struct MyObserver {
7594 a: u32
7595 }
7596 impl Observer_methods for MyObserver {
7597 }
7598 }),
7599 );
7600}
7601
7602#[test]
7603fn test_two_subclasses() {
7604 let hdr = indoc! {"
7605 #include <cstdint>
7606
7607 class Observer {
7608 public:
7609 Observer() {}
7610 virtual void foo() const {}
7611 virtual ~Observer() {}
7612 };
7613 inline void bar() {}
7614 "};
7615 run_test_ex(
7616 "",
7617 hdr,
7618 quote! {
7619 let obs = MyObserverA::new_rust_owned(MyObserverA { a: 3, cpp_peer: Default::default() });
7620 obs.borrow().foo();
7621 let obs = MyObserverB::new_rust_owned(MyObserverB { a: 3, cpp_peer: Default::default() });
7622 obs.borrow().foo();
7623 },
7624 quote! {
7625 generate!("bar")
7626 subclass!("Observer",MyObserverA)
7627 subclass!("Observer",MyObserverB)
7628 },
7629 None,
7630 None,
7631 Some(quote! {
7632 use autocxx::subclass::CppSubclass;
7633 use ffi::Observer_methods;
7634 #[autocxx::subclass::subclass]
7635 pub struct MyObserverA {
7636 a: u32
7637 }
7638 impl Observer_methods for MyObserverA {
7639 }
7640 #[autocxx::subclass::subclass]
7641 pub struct MyObserverB {
7642 a: u32
7643 }
7644 impl Observer_methods for MyObserverB {
7645 }
7646 }),
7647 );
7648}
7649
7650#[test]
7651fn test_two_superclasses_with_same_name_method() {
7652 let hdr = indoc! {"
7653 #include <cstdint>
7654
7655 class ObserverA {
7656 public:
7657 ObserverA() {}
7658 virtual void foo() const {}
7659 virtual ~ObserverA() {}
7660 };
7661
7662 class ObserverB {
7663 public:
7664 ObserverB() {}
7665 virtual void foo() const {}
7666 virtual ~ObserverB() {}
7667 };
7668 inline void bar() {}
7669 "};
7670 run_test_ex(
7671 "",
7672 hdr,
7673 quote! {
7674 let obs = MyObserverA::new_rust_owned(MyObserverA { a: 3, cpp_peer: Default::default() });
7675 obs.borrow().foo();
7676 let obs = MyObserverB::new_rust_owned(MyObserverB { a: 3, cpp_peer: Default::default() });
7677 obs.borrow().foo();
7678 },
7679 quote! {
7680 generate!("bar")
7681 subclass!("ObserverA",MyObserverA)
7682 subclass!("ObserverB",MyObserverB)
7683 },
7684 None,
7685 None,
7686 Some(quote! {
7687 use autocxx::subclass::CppSubclass;
7688 use ffi::ObserverA_methods;
7689 use ffi::ObserverB_methods;
7690 #[autocxx::subclass::subclass]
7691 pub struct MyObserverA {
7692 a: u32
7693 }
7694 impl ObserverA_methods for MyObserverA {
7695 }
7696 #[autocxx::subclass::subclass]
7697 pub struct MyObserverB {
7698 a: u32
7699 }
7700 impl ObserverB_methods for MyObserverB {
7701 }
7702 }),
7703 );
7704}
7705
7706#[test]
7707fn test_pv_protected_constructor() {
7708 let hdr = indoc! {"
7709 #include <cstdint>
7710
7711 class Observer {
7712 protected:
7713 Observer() {}
7714 public:
7715 virtual void foo() const {}
7716 virtual ~Observer() {}
7717 };
7718 inline void bar() {}
7719 "};
7720 run_test_ex(
7721 "",
7722 hdr,
7723 quote! {
7724 let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7725 obs.borrow().foo();
7726 },
7727 quote! {
7728 generate!("bar")
7729 subclass!("Observer",MyObserver)
7730 },
7731 None,
7732 None,
7733 Some(quote! {
7734 use autocxx::subclass::CppSubclass;
7735 use ffi::Observer_methods;
7736 #[autocxx::subclass::subclass]
7737 pub struct MyObserver {
7738 a: u32
7739 }
7740 impl Observer_methods for MyObserver {
7741 }
7742 }),
7743 );
7744}
7745
7746#[test]
7747fn test_pv_protected_method() {
7748 let hdr = indoc! {"
7749 #include <cstdint>
7750
7751 class Observer {
7752 public:
7753 Observer() {}
7754 virtual void foo() const {}
7755 virtual ~Observer() {}
7756 protected:
7757 virtual void baz() const {}
7758 };
7759 inline void bar() {}
7760 "};
7761 run_test_ex(
7762 "",
7763 hdr,
7764 quote! {
7765 let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
7766 obs.borrow().foo();
7767 },
7768 quote! {
7769 generate!("bar")
7770 subclass!("Observer",MyObserver)
7771 },
7772 None,
7773 None,
7774 Some(quote! {
7775 use autocxx::subclass::CppSubclass;
7776 use ffi::Observer_methods;
7777 #[autocxx::subclass::subclass]
7778 pub struct MyObserver {
7779 a: u32
7780 }
7781 impl Observer_methods for MyObserver {
7782 fn baz(&self) {
7783 }
7784
7785 fn foo(&self) {
7786 use ffi::Observer_supers;
7787 self.baz_super()
7788 }
7789 }
7790 }),
7791 );
7792}
7793
7794#[test]
7795fn test_pv_subclass_allocation_not_self_owned() {
7796 let hdr = indoc! {"
7797 #include <cstdint>
7798 extern \"C\" void mark_freed() noexcept;
7799 extern \"C\" void mark_allocated() noexcept;
7800
7801 class TestObserver {
7802 public:
7803 TestObserver() {
7804 mark_allocated();
7805 }
7806 virtual void a() const = 0;
7807 virtual ~TestObserver() {
7808 mark_freed();
7809 }
7810 };
7811 inline void TriggerTestObserverA(const TestObserver& obs) {
7812 obs.a();
7813 }
7814 "};
7815 run_test_ex(
7816 "",
7817 hdr,
7818 quote! {
7819 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7820 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7821 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7822
7823 // Test when owned by C++
7824 let obs = MyTestObserver::new_cpp_owned(
7825 MyTestObserver::new()
7826 );
7827 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7828 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7829 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7830 let obs_superclass = obs.as_ref().unwrap(); // &subclass
7831 let obs_superclass = unsafe { std::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) };
7832 ffi::TriggerTestObserverA(obs_superclass);
7833 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
7834 std::mem::drop(obs);
7835 Lazy::force(&STATUS).lock().unwrap().a_called = false;
7836 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7837 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7838 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7839
7840 // Test when owned by Rust
7841 let obs = MyTestObserver::new_rust_owned(
7842 MyTestObserver::new()
7843 );
7844 //let cpp_peer_ptr = unsafe { obs.borrow_mut().peer_mut().get_unchecked_mut() as *mut ffi::MyTestObserverCpp };
7845 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7846 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7847 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7848 ffi::TriggerTestObserverA(obs.as_ref().borrow().as_ref());
7849 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
7850 Lazy::force(&STATUS).lock().unwrap().a_called = false;
7851 std::mem::drop(obs);
7852 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7853 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7854 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7855 },
7856 quote! {
7857 generate!("TriggerTestObserverA")
7858 subclass!("TestObserver",MyTestObserver)
7859 },
7860 None,
7861 None,
7862 Some(quote! {
7863 use once_cell::sync::Lazy;
7864 use std::sync::Mutex;
7865
7866 use autocxx::subclass::CppSubclass;
7867 use ffi::TestObserver_methods;
7868 #[autocxx::subclass::subclass]
7869 pub struct MyTestObserver {
7870 data: ExternalEngine,
7871 }
7872 impl TestObserver_methods for MyTestObserver {
7873 fn a(&self) {
7874 self.data.do_something();
7875 }
7876 }
7877 impl MyTestObserver {
7878 fn new() -> Self {
7879 Self {
7880 cpp_peer: Default::default(),
7881 data: ExternalEngine::default(),
7882 }
7883 }
7884 }
7885
7886 #[no_mangle]
7887 pub fn mark_allocated() {
7888 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = true;
7889 }
7890
7891 #[no_mangle]
7892 pub fn mark_freed() {
7893 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = false;
7894 }
7895
7896 #[derive(Default)]
7897 struct Status {
7898 cpp_allocated: bool,
7899 rust_allocated: bool,
7900 a_called: bool,
7901 }
7902
7903 static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
7904
7905 pub struct ExternalEngine;
7906
7907 impl ExternalEngine {
7908 fn do_something(&self) {
7909 Lazy::force(&STATUS).lock().unwrap().a_called = true;
7910 }
7911 }
7912
7913 impl Default for ExternalEngine {
7914 fn default() -> Self {
7915 Lazy::force(&STATUS).lock().unwrap().rust_allocated = true;
7916 ExternalEngine
7917 }
7918 }
7919
7920 impl Drop for ExternalEngine {
7921 fn drop(&mut self) {
7922 Lazy::force(&STATUS).lock().unwrap().rust_allocated = false;
7923 }
7924 }
7925 }),
7926 );
7927}
7928
7929#[test]
7930fn test_pv_subclass_allocation_self_owned() {
7931 let hdr = indoc! {"
7932 #include <cstdint>
7933 extern \"C\" void mark_freed() noexcept;
7934 extern \"C\" void mark_allocated() noexcept;
7935
7936 class TestObserver {
7937 public:
7938 TestObserver() {
7939 mark_allocated();
7940 }
7941 virtual void a() const = 0;
7942 virtual ~TestObserver() {
7943 mark_freed();
7944 }
7945 };
7946 inline void TriggerTestObserverA(const TestObserver& obs) {
7947 const_cast<TestObserver&>(obs).a();
7948 }
7949 "};
7950 run_test_ex(
7951 "",
7952 hdr,
7953 quote! {
7954 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7955 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7956 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7957
7958 // Test when owned by C++
7959 let obs = MyTestObserver::new_cpp_owned(
7960 MyTestObserver::new(false)
7961 );
7962 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7963 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7964 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7965 let obs_superclass = obs.as_ref().unwrap(); // &subclass
7966 let obs_superclass = unsafe { std::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) };
7967
7968 ffi::TriggerTestObserverA(obs_superclass);
7969 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
7970 std::mem::drop(obs);
7971 Lazy::force(&STATUS).lock().unwrap().a_called = false;
7972 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7973 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7974 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7975
7976 // Test when owned by Rust
7977 let obs = MyTestObserver::new_rust_owned(
7978 MyTestObserver::new(false)
7979 );
7980 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7981 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7982 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7983 ffi::TriggerTestObserverA(obs.as_ref().borrow().as_ref());
7984
7985 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
7986 Lazy::force(&STATUS).lock().unwrap().a_called = false;
7987 std::mem::drop(obs);
7988 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
7989 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
7990 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
7991
7992 // Test when self-owned
7993 let obs = MyTestObserver::new_self_owned(
7994 MyTestObserver::new(true)
7995 );
7996 let obs_superclass_ptr: *const ffi::TestObserver = obs.as_ref().borrow().as_ref();
7997 // Retain just a pointer on the Rust side, so there is no Rust-side
7998 // ownership.
7999 std::mem::drop(obs);
8000 assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8001 assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8002 assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
8003 ffi::TriggerTestObserverA(unsafe { obs_superclass_ptr.as_ref().unwrap() });
8004
8005 assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
8006 assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
8007 assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
8008 },
8009 quote! {
8010 generate!("TriggerTestObserverA")
8011 subclass!("TestObserver",MyTestObserver)
8012 },
8013 None,
8014 None,
8015 Some(quote! {
8016 use once_cell::sync::Lazy;
8017 use std::sync::Mutex;
8018
8019 use autocxx::subclass::CppSubclass;
8020 use autocxx::subclass::CppSubclassSelfOwned;
8021 use ffi::TestObserver_methods;
8022 #[autocxx::subclass::subclass(self_owned)]
8023 pub struct MyTestObserver {
8024 data: ExternalEngine,
8025 self_owning: bool,
8026 }
8027 impl TestObserver_methods for MyTestObserver {
8028 fn a(&self) {
8029 self.data.do_something();
8030 if self.self_owning {
8031 self.delete_self();
8032 }
8033 }
8034 }
8035 impl MyTestObserver {
8036 fn new(self_owning: bool) -> Self {
8037 Self {
8038 cpp_peer: Default::default(),
8039 data: ExternalEngine::default(),
8040 self_owning,
8041 }
8042 }
8043 }
8044
8045 #[no_mangle]
8046 pub fn mark_allocated() {
8047 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = true;
8048 }
8049
8050 #[no_mangle]
8051 pub fn mark_freed() {
8052 Lazy::force(&STATUS).lock().unwrap().cpp_allocated = false;
8053 }
8054
8055 #[derive(Default)]
8056 struct Status {
8057 cpp_allocated: bool,
8058 rust_allocated: bool,
8059 a_called: bool,
8060 }
8061
8062 static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
8063
8064 pub struct ExternalEngine;
8065
8066 impl ExternalEngine {
8067 fn do_something(&self) {
8068 Lazy::force(&STATUS).lock().unwrap().a_called = true;
8069 }
8070 }
8071
8072 impl Default for ExternalEngine {
8073 fn default() -> Self {
8074 Lazy::force(&STATUS).lock().unwrap().rust_allocated = true;
8075 ExternalEngine
8076 }
8077 }
8078
8079 impl Drop for ExternalEngine {
8080 fn drop(&mut self) {
8081 Lazy::force(&STATUS).lock().unwrap().rust_allocated = false;
8082 }
8083 }
8084 }),
8085 );
8086}
8087
8088#[test]
8089fn test_pv_subclass_calls() {
8090 let hdr = indoc! {"
8091 #include <cstdint>
8092 extern \"C\" void mark_c_called() noexcept;
8093 extern \"C\" void mark_d_called() noexcept;
8094 extern \"C\" void mark_e_called() noexcept;
8095 extern \"C\" void mark_f_called() noexcept;
8096 extern \"C\" void mark_g_called() noexcept;
8097 extern \"C\" void mark_h_called() noexcept;
8098
8099 class TestObserver {
8100 public:
8101 TestObserver() {}
8102 virtual uint32_t a(uint32_t) const = 0;
8103 virtual uint32_t b(uint32_t) = 0;
8104 virtual uint32_t c(uint32_t) const { mark_c_called(); return 0; };
8105 virtual uint32_t d(uint32_t) { mark_d_called(); return 0; };
8106 virtual uint32_t e(uint32_t) const { mark_e_called(); return 0; };
8107 virtual uint32_t f(uint32_t) { mark_f_called(); return 0; };
8108 virtual uint32_t g(uint32_t) const { mark_g_called(); return 0; };
8109 virtual uint32_t h(uint32_t) { mark_h_called(); return 0; };
8110 virtual ~TestObserver() {}
8111 };
8112
8113 extern TestObserver* obs;
8114
8115 inline void register_observer(TestObserver& a) {
8116 obs = &a;
8117 }
8118 inline uint32_t call_a(uint32_t param) {
8119 return obs->a(param);
8120 }
8121 inline uint32_t call_b(uint32_t param) {
8122 return obs->b(param);
8123 }
8124 inline uint32_t call_c(uint32_t param) {
8125 return obs->c(param);
8126 }
8127 inline uint32_t call_d(uint32_t param) {
8128 return obs->d(param);
8129 }
8130 inline uint32_t call_e(uint32_t param) {
8131 return obs->e(param);
8132 }
8133 inline uint32_t call_f(uint32_t param) {
8134 return obs->f(param);
8135 }
8136 inline uint32_t call_g(uint32_t param) {
8137 return obs->g(param);
8138 }
8139 inline uint32_t call_h(uint32_t param) {
8140 return obs->h(param);
8141 }
8142 "};
8143 run_test_ex(
8144 "TestObserver* obs;",
8145 hdr,
8146 quote! {
8147 let obs = MyTestObserver::new_rust_owned(
8148 MyTestObserver::default()
8149 );
8150 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8151 assert_eq!(ffi::call_a(1), 2);
8152 assert!(Lazy::force(&STATUS).lock().unwrap().sub_a_called);
8153 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8154
8155 assert_eq!(ffi::call_b(1), 3);
8156 assert!(Lazy::force(&STATUS).lock().unwrap().sub_b_called);
8157 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8158
8159 assert_eq!(ffi::call_c(1), 4);
8160 assert!(Lazy::force(&STATUS).lock().unwrap().sub_c_called);
8161 assert!(!Lazy::force(&STATUS).lock().unwrap().super_c_called);
8162 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8163
8164 assert_eq!(ffi::call_d(1), 5);
8165 assert!(Lazy::force(&STATUS).lock().unwrap().sub_d_called);
8166 assert!(!Lazy::force(&STATUS).lock().unwrap().super_d_called);
8167 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8168
8169 assert_eq!(ffi::call_e(1), 0);
8170 assert!(Lazy::force(&STATUS).lock().unwrap().sub_e_called);
8171 assert!(Lazy::force(&STATUS).lock().unwrap().super_e_called);
8172 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8173
8174 assert_eq!(ffi::call_f(1), 0);
8175 assert!(Lazy::force(&STATUS).lock().unwrap().sub_f_called);
8176 assert!(Lazy::force(&STATUS).lock().unwrap().super_f_called);
8177 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8178
8179 assert_eq!(ffi::call_g(1), 0);
8180 assert!(Lazy::force(&STATUS).lock().unwrap().super_g_called);
8181 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8182
8183 assert_eq!(ffi::call_h(1), 0);
8184 assert!(Lazy::force(&STATUS).lock().unwrap().super_h_called);
8185 *Lazy::force(&STATUS).lock().unwrap() = Default::default();
8186 },
8187 quote! {
8188 generate!("register_observer")
8189 generate!("call_a")
8190 generate!("call_b")
8191 generate!("call_c")
8192 generate!("call_d")
8193 generate!("call_e")
8194 generate!("call_f")
8195 generate!("call_g")
8196 generate!("call_h")
8197 subclass!("TestObserver",MyTestObserver)
8198 },
8199 None,
8200 None,
8201 Some(quote! {
8202 use once_cell::sync::Lazy;
8203 use std::sync::Mutex;
8204
8205 use autocxx::subclass::CppSubclass;
8206 use ffi::TestObserver_methods;
8207 #[autocxx::subclass::subclass]
8208 #[derive(Default)]
8209 pub struct MyTestObserver {
8210 }
8211 impl TestObserver_methods for MyTestObserver {
8212
8213 // a and b are pure virtual
8214 fn a(&self, param: u32) -> u32 {
8215 Lazy::force(&STATUS).lock().unwrap().sub_a_called = true;
8216 param + 1
8217 }
8218 fn b(&mut self, param: u32) -> u32 {
8219 Lazy::force(&STATUS).lock().unwrap().sub_b_called = true;
8220 param + 2
8221 }
8222
8223 // c and d we override the superclass
8224 fn c(&self, param: u32) -> u32 {
8225 Lazy::force(&STATUS).lock().unwrap().sub_c_called = true;
8226 param + 3
8227 }
8228 fn d(&mut self, param: u32) -> u32 {
8229 Lazy::force(&STATUS).lock().unwrap().sub_d_called = true;
8230 param + 4
8231 }
8232
8233 // e and f we call through to the superclass
8234 fn e(&self, param: u32) -> u32 {
8235 Lazy::force(&STATUS).lock().unwrap().sub_e_called = true;
8236 self.peer().e_super(param)
8237 }
8238 fn f(&mut self, param: u32) -> u32 {
8239 Lazy::force(&STATUS).lock().unwrap().sub_f_called = true;
8240 self.peer_mut().f_super(param)
8241 }
8242
8243 // g and h we do not do anything, so calls should only call
8244 // the superclass
8245 }
8246
8247 #[no_mangle]
8248 pub fn mark_c_called() {
8249 Lazy::force(&STATUS).lock().unwrap().super_c_called = true;
8250 }
8251 #[no_mangle]
8252 pub fn mark_d_called() {
8253 Lazy::force(&STATUS).lock().unwrap().super_d_called = true;
8254 }
8255 #[no_mangle]
8256 pub fn mark_e_called() {
8257 Lazy::force(&STATUS).lock().unwrap().super_e_called = true;
8258 }
8259 #[no_mangle]
8260 pub fn mark_f_called() {
8261 Lazy::force(&STATUS).lock().unwrap().super_f_called = true;
8262 }
8263 #[no_mangle]
8264 pub fn mark_g_called() {
8265 Lazy::force(&STATUS).lock().unwrap().super_g_called = true;
8266 }
8267 #[no_mangle]
8268 pub fn mark_h_called() {
8269 Lazy::force(&STATUS).lock().unwrap().super_h_called = true;
8270 }
8271
8272 #[derive(Default)]
8273 struct Status {
8274 super_c_called: bool,
8275 super_d_called: bool,
8276 super_e_called: bool,
8277 super_f_called: bool,
8278 super_g_called: bool,
8279 super_h_called: bool,
8280 sub_a_called: bool,
8281 sub_b_called: bool,
8282 sub_c_called: bool,
8283 sub_d_called: bool,
8284 sub_e_called: bool,
8285 sub_f_called: bool,
8286 }
8287
8288 static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
8289 }),
8290 );
8291}
8292
8293#[test]
8294fn test_cycle_nonpod_simple() {
8295 let hdr = indoc! {"
8296 #include <string>
8297 struct NonPod {
8298 std::string a;
8299 };
8300 inline NonPod make_non_pod(std::string a) {
8301 NonPod p;
8302 p.a = a;
8303 return p;
8304 }
8305 inline NonPod call_n(NonPod param) {
8306 return param;
8307 }
8308 "};
8309 let rs = quote! {
8310 let nonpod = ffi::make_non_pod("hello").within_unique_ptr();
8311 ffi::call_n(nonpod).within_unique_ptr();
8312 };
8313 run_test("", hdr, rs, &["NonPod", "make_non_pod", "call_n"], &[])
8314}
8315
8316#[test]
8317fn test_pv_subclass_types() {
8318 let hdr = indoc! {"
8319 #include <cstdint>
8320 #include <string>
8321 #include <vector>
8322
8323 struct Fwd;
8324 struct Pod {
8325 uint32_t a;
8326 };
8327 struct NonPod {
8328 std::string a;
8329 };
8330 class TestObserver {
8331 public:
8332 TestObserver() {}
8333 virtual std::string s(std::string p) const { return p; }
8334 virtual Pod p(Pod p) const { return p; }
8335 virtual NonPod n(NonPod p) const { return p; }
8336 virtual void f(const Fwd&) const { }
8337 virtual std::vector<NonPod> v(std::vector<NonPod> v) const { return v; }
8338 virtual const std::vector<NonPod>& vr(const std::vector<NonPod>& vr) const { return vr; }
8339 virtual const std::vector<Fwd>& vfr(const std::vector<Fwd>& vfr) const { return vfr; }
8340 virtual ~TestObserver() {}
8341 };
8342
8343 extern TestObserver* obs;
8344
8345 inline void register_observer(TestObserver& a) {
8346 obs = &a;
8347 }
8348 inline std::string call_s(std::string param) {
8349 return obs->s(param);
8350 }
8351 inline Pod call_p(Pod param) {
8352 return obs->p(param);
8353 }
8354 inline NonPod call_n(NonPod param) {
8355 return obs->n(param);
8356 }
8357 inline NonPod make_non_pod(std::string a) {
8358 NonPod p;
8359 p.a = a;
8360 return p;
8361 }
8362 "};
8363 run_test_ex(
8364 "TestObserver* obs;",
8365 hdr,
8366 quote! {
8367 let obs = MyTestObserver::new_rust_owned(
8368 MyTestObserver::default()
8369 );
8370 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8371 ffi::call_p(ffi::Pod { a: 3 });
8372 ffi::call_s("hello");
8373 ffi::call_n(ffi::make_non_pod("goodbye").within_unique_ptr());
8374 },
8375 quote! {
8376 generate!("register_observer")
8377 generate!("call_s")
8378 generate!("call_n")
8379 generate!("call_p")
8380 generate!("NonPod")
8381 generate!("make_non_pod")
8382 generate_pod!("Pod")
8383 subclass!("TestObserver",MyTestObserver)
8384 },
8385 None,
8386 None,
8387 Some(quote! {
8388 use autocxx::subclass::CppSubclass;
8389 use ffi::TestObserver_methods;
8390 #[autocxx::subclass::subclass]
8391 #[derive(Default)]
8392 pub struct MyTestObserver {
8393 }
8394 impl TestObserver_methods for MyTestObserver {
8395 fn s(&self, p: cxx::UniquePtr<cxx::CxxString>) -> cxx::UniquePtr<cxx::CxxString> {
8396 self.peer().s_super(p)
8397 }
8398
8399 fn p(&self, p: ffi::Pod) -> ffi::Pod {
8400 self.peer().p_super(p)
8401 }
8402
8403 fn n(&self, p: cxx::UniquePtr<ffi::NonPod>) -> cxx::UniquePtr<ffi::NonPod> {
8404 self.peer().n_super(p)
8405 }
8406 }
8407 }),
8408 );
8409}
8410
8411#[test]
8412fn test_pv_subclass_constructors() {
8413 // Also tests a Rust-side subclass type which is an empty struct
8414 let hdr = indoc! {"
8415 #include <cstdint>
8416 #include <string>
8417
8418 class TestObserver {
8419 public:
8420 TestObserver() {}
8421 TestObserver(uint8_t) {}
8422 TestObserver(std::string) {}
8423 virtual void call() const { }
8424 virtual ~TestObserver() {}
8425 };
8426
8427 extern TestObserver* obs;
8428
8429 inline void register_observer(TestObserver& a) {
8430 obs = &a;
8431 }
8432 inline void do_a_thing() {
8433 return obs->call();
8434 }
8435 "};
8436 run_test_ex(
8437 "TestObserver* obs;",
8438 hdr,
8439 quote! {
8440 let obs = MyTestObserver::new_rust_owned(
8441 MyTestObserver::default()
8442 );
8443 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8444 ffi::do_a_thing();
8445 },
8446 quote! {
8447 generate!("register_observer")
8448 generate!("do_a_thing")
8449 subclass!("TestObserver",MyTestObserver)
8450 },
8451 None,
8452 None,
8453 Some(quote! {
8454 use autocxx::subclass::prelude::*;
8455 #[subclass]
8456 #[derive(Default)]
8457 pub struct MyTestObserver;
8458 impl ffi::TestObserver_methods for MyTestObserver {
8459 fn call(&self) {
8460 self.peer().call_super()
8461 }
8462 }
8463 impl CppPeerConstructor<ffi::MyTestObserverCpp> for MyTestObserver {
8464 fn make_peer(&mut self, peer_holder: CppSubclassRustPeerHolder<Self>) -> cxx::UniquePtr<ffi::MyTestObserverCpp> {
8465 ffi::MyTestObserverCpp::new1(peer_holder, 3u8).within_unique_ptr()
8466 }
8467 }
8468 }),
8469 );
8470}
8471
8472#[test]
8473fn test_pv_subclass_fancy_constructor() {
8474 let hdr = indoc! {"
8475 #include <cstdint>
8476
8477 class Observer {
8478 public:
8479 Observer(uint8_t) {}
8480 virtual uint32_t foo() const = 0;
8481 virtual ~Observer() {}
8482 };
8483 inline void take_observer(const Observer&) {}
8484 "};
8485 run_test_expect_fail_ex(
8486 "",
8487 hdr,
8488 quote! {
8489 let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() }, ffi::MyObserverCpp::make_unique);
8490 ffi::take_observer(o.borrow().as_ref());
8491 },
8492 quote! {
8493 generate!("take_observer")
8494 subclass!("Observer",MyObserver)
8495 },
8496 None,
8497 None,
8498 Some(quote! {
8499 use autocxx::subclass::CppSubclass;
8500 use ffi::Observer_methods;
8501 #[autocxx::subclass::subclass]
8502 pub struct MyObserver {
8503 a: u32
8504 }
8505 impl Observer_methods for MyObserver {
8506 fn foo(&self) -> u32 {
8507 4
8508 }
8509 }
8510 }),
8511 );
8512}
8513
8514#[test]
8515fn test_non_pv_subclass_overloads() {
8516 let hdr = indoc! {"
8517 #include <cstdint>
8518 #include <string>
8519
8520 class TestObserver {
8521 public:
8522 TestObserver() {}
8523 virtual void call(uint8_t) const {}
8524 virtual void call(std::string) const {}
8525 virtual ~TestObserver() {}
8526 };
8527
8528 extern TestObserver* obs;
8529
8530 inline void register_observer(TestObserver& a) {
8531 obs = &a;
8532 }
8533 inline void do_a_thing() {
8534 return obs->call(8);
8535 }
8536 "};
8537 run_test_ex(
8538 "TestObserver* obs;",
8539 hdr,
8540 quote! {
8541 let obs = MyTestObserver::new_rust_owned(
8542 MyTestObserver::default()
8543 );
8544 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8545 ffi::do_a_thing();
8546 },
8547 quote! {
8548 generate!("register_observer")
8549 generate!("do_a_thing")
8550 subclass!("TestObserver",MyTestObserver)
8551 },
8552 None,
8553 None,
8554 Some(quote! {
8555 use autocxx::subclass::prelude::*;
8556 #[subclass]
8557 #[derive(Default)]
8558 pub struct MyTestObserver;
8559 impl ffi::TestObserver_methods for MyTestObserver {
8560 fn call(&self, a: u8) {
8561 self.peer().call_super(a)
8562 }
8563 fn call1(&self, a: cxx::UniquePtr<cxx::CxxString>) {
8564 self.peer().call1_super(a)
8565 }
8566 }
8567 }),
8568 );
8569}
8570
8571#[test]
8572fn test_pv_subclass_overrides() {
8573 let hdr = indoc! {"
8574 #include <cstdint>
8575 #include <string>
8576
8577 class TestObserver {
8578 public:
8579 TestObserver() {}
8580 virtual void call(uint8_t) const = 0;
8581 virtual void call(std::string) const = 0;
8582 virtual ~TestObserver() {}
8583 };
8584
8585 extern TestObserver* obs;
8586
8587 inline void register_observer(TestObserver& a) {
8588 obs = &a;
8589 }
8590 inline void do_a_thing() {
8591 return obs->call(8);
8592 }
8593 "};
8594 run_test_ex(
8595 "TestObserver* obs;",
8596 hdr,
8597 quote! {
8598 let obs = MyTestObserver::new_rust_owned(
8599 MyTestObserver::default()
8600 );
8601 ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
8602 ffi::do_a_thing();
8603 },
8604 quote! {
8605 generate!("register_observer")
8606 generate!("do_a_thing")
8607 subclass!("TestObserver",MyTestObserver)
8608 },
8609 None,
8610 None,
8611 Some(quote! {
8612 use autocxx::subclass::prelude::*;
8613 #[subclass]
8614 #[derive(Default)]
8615 pub struct MyTestObserver;
8616 impl ffi::TestObserver_methods for MyTestObserver {
8617 fn call(&self, _a: u8) {
8618 }
8619 fn call1(&self, _a: cxx::UniquePtr<cxx::CxxString>) {
8620 }
8621 }
8622 }),
8623 );
8624}
8625
8626#[test]
8627fn test_pv_subclass_namespaced_superclass() {
8628 let hdr = indoc! {"
8629 #include <cstdint>
8630
8631 namespace a {
8632 class Observer {
8633 public:
8634 Observer() {}
8635 virtual uint32_t foo() const = 0;
8636 virtual ~Observer() {}
8637 };
8638 }
8639 inline void take_observer(const a::Observer&) {}
8640 "};
8641 run_test_ex(
8642 "",
8643 hdr,
8644 quote! {
8645 let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
8646 ffi::take_observer(o.borrow().as_ref());
8647 },
8648 quote! {
8649 generate!("take_observer")
8650 subclass!("a::Observer",MyObserver)
8651 },
8652 None,
8653 None,
8654 Some(quote! {
8655 use autocxx::subclass::CppSubclass;
8656 #[autocxx::subclass::subclass]
8657 pub struct MyObserver {
8658 a: u32
8659 }
8660 impl ffi::a::Observer_methods for MyObserver {
8661 fn foo(&self) -> u32 {
8662 4
8663 }
8664 }
8665 }),
8666 );
8667}
8668
8669#[test]
8670fn test_no_constructor_make_unique() {
8671 let hdr = indoc! {"
8672 #include <stdint.h>
8673 struct A {
8674 uint32_t a;
8675 };
8676 "};
8677 let rs = quote! {
8678 ffi::A::new().within_unique_ptr();
8679 };
8680 run_test("", hdr, rs, &["A"], &[]);
8681}
8682
8683#[test]
8684fn test_constructor_moveit() {
8685 let hdr = indoc! {"
8686 #include <stdint.h>
8687 #include <string>
8688 struct A {
8689 A() {}
8690 void set(uint32_t val) { a = val; }
8691 uint32_t get() const { return a; }
8692 uint32_t a;
8693 std::string so_we_are_non_trivial;
8694 };
8695 "};
8696 let rs = quote! {
8697 moveit! {
8698 let mut stack_obj = ffi::A::new();
8699 }
8700 stack_obj.as_mut().set(42);
8701 assert_eq!(stack_obj.get(), 42);
8702 };
8703 run_test("", hdr, rs, &["A"], &[]);
8704}
8705
8706#[test]
8707fn test_move_out_of_uniqueptr() {
8708 let hdr = indoc! {"
8709 #include <stdint.h>
8710 #include <string>
8711 struct A {
8712 A() {}
8713 std::string so_we_are_non_trivial;
8714 };
8715 inline A get_a() {
8716 A a;
8717 return a;
8718 }
8719 "};
8720 let rs = quote! {
8721 let a = ffi::get_a().within_unique_ptr();
8722 moveit! {
8723 let _stack_obj = autocxx::moveit::new::mov(a);
8724 }
8725 };
8726 run_test("", hdr, rs, &["A", "get_a"], &[]);
8727}
8728
8729#[test]
8730fn test_implicit_constructor_with_typedef_field() {
8731 let hdr = indoc! {"
8732 #include <stdint.h>
8733 #include <string>
8734 struct B {
8735 uint32_t b;
8736 };
8737 typedef struct B C;
8738 struct A {
8739 B field;
8740 uint32_t a;
8741 std::string so_we_are_non_trivial;
8742 };
8743 "};
8744 let rs = quote! {
8745 moveit! {
8746 let mut stack_obj = ffi::A::new();
8747 }
8748 };
8749 run_test("", hdr, rs, &["A"], &[]);
8750}
8751
8752#[test]
8753fn test_implicit_constructor_with_array_field() {
8754 let hdr = indoc! {"
8755 #include <stdint.h>
8756 #include <string>
8757 struct A {
8758 uint32_t a[3];
8759 std::string so_we_are_non_trivial;
8760 };
8761 "};
8762 let rs = quote! {
8763 moveit! {
8764 let mut _stack_obj = ffi::A::new();
8765 }
8766 };
8767 run_test("", hdr, rs, &["A"], &[]);
8768}
8769
8770#[test]
8771fn test_implicit_constructor_moveit() {
8772 let hdr = indoc! {"
8773 #include <stdint.h>
8774 #include <string>
8775 struct A {
8776 void set(uint32_t val) { a = val; }
8777 uint32_t get() const { return a; }
8778 uint32_t a;
8779 std::string so_we_are_non_trivial;
8780 };
8781 "};
8782 let rs = quote! {
8783 moveit! {
8784 let mut stack_obj = ffi::A::new();
8785 }
8786 stack_obj.as_mut().set(42);
8787 assert_eq!(stack_obj.get(), 42);
8788 };
8789 run_test("", hdr, rs, &["A"], &[]);
8790}
8791
8792#[test]
8793fn test_pass_by_value_moveit() {
8794 let hdr = indoc! {"
8795 #include <stdint.h>
8796 #include <string>
8797 struct A {
8798 void set(uint32_t val) { a = val; }
8799 uint32_t a;
8800 std::string so_we_are_non_trivial;
8801 };
8802 inline void take_a(A) {}
8803 struct B {
8804 B() {}
8805 B(const B&) {}
8806 B(B&&) {}
8807 std::string so_we_are_non_trivial;
8808 };
8809 inline void take_b(B) {}
8810 "};
8811 let rs = quote! {
8812 moveit! {
8813 let mut stack_obj = ffi::A::new();
8814 }
8815 stack_obj.as_mut().set(42);
8816 ffi::take_a(&*stack_obj);
8817 ffi::take_a(as_copy(stack_obj.as_ref()));
8818 ffi::take_a(as_copy(stack_obj.as_ref()));
8819 // A has no move constructor so we can't consume it.
8820
8821 let heap_obj = ffi::A::new().within_unique_ptr();
8822 ffi::take_a(heap_obj.as_ref().unwrap());
8823 ffi::take_a(&heap_obj);
8824 ffi::take_a(autocxx::as_copy(heap_obj.as_ref().unwrap()));
8825 ffi::take_a(heap_obj); // consume
8826
8827 let heap_obj2 = ffi::A::new().within_box();
8828 ffi::take_a(heap_obj2.as_ref().get_ref());
8829 ffi::take_a(&heap_obj2);
8830 ffi::take_a(autocxx::as_copy(heap_obj2.as_ref().get_ref()));
8831 ffi::take_a(heap_obj2); // consume
8832
8833 moveit! {
8834 let mut stack_obj = ffi::B::new();
8835 }
8836 ffi::take_b(&*stack_obj);
8837 ffi::take_b(as_copy(stack_obj.as_ref()));
8838 ffi::take_b(as_copy(stack_obj.as_ref()));
8839 ffi::take_b(as_mov(stack_obj)); // due to move constructor
8840
8841 // Test direct-from-New-to-param.
8842 ffi::take_b(as_new(ffi::B::new()));
8843 };
8844 run_test("", hdr, rs, &["A", "take_a", "B", "take_b"], &[]);
8845}
8846
8847#[test]
8848fn test_nonconst_reference_parameter() {
8849 let hdr = indoc! {"
8850 #include <stdint.h>
8851 #include <string>
8852
8853 // Force generating a wrapper for the second `take_a`.
8854 struct NOP { void take_a() {}; };
8855
8856 struct A {
8857 std::string so_we_are_non_trivial;
8858 };
8859 inline void take_a(A&) {}
8860 "};
8861 let rs = quote! {
8862 let mut heap_obj = ffi::A::new().within_unique_ptr();
8863 ffi::take_a(heap_obj.pin_mut());
8864 };
8865 run_test("", hdr, rs, &["NOP", "A", "take_a"], &[]);
8866}
8867
8868#[test]
8869fn test_nonconst_reference_method_parameter() {
8870 let hdr = indoc! {"
8871 #include <stdint.h>
8872 #include <string>
8873
8874 // Force generating a wrapper for the second `take_a`.
8875 struct NOP { void take_a() {}; };
8876
8877 struct A {
8878 std::string so_we_are_non_trivial;
8879 };
8880 struct B {
8881 inline void take_a(A&) const {}
8882 };
8883 "};
8884 let rs = quote! {
8885 let mut a = ffi::A::new().within_unique_ptr();
8886 let b = ffi::B::new().within_unique_ptr();
8887 b.take_a(a.pin_mut());
8888 };
8889 run_test("", hdr, rs, &["NOP", "A", "B"], &[]);
8890}
8891
8892fn destruction_test(ident: proc_macro2::Ident, extra_bit: Option<TokenStream>) {
8893 let hdr = indoc! {"
8894 #include <stdint.h>
8895 #include <string>
8896 extern bool gConstructed;
8897 struct A {
8898 A() { gConstructed = true; }
8899 virtual ~A() { gConstructed = false; }
8900 void set(uint32_t val) { a = val; }
8901 uint32_t get() const { return a; }
8902 uint32_t a;
8903 std::string so_we_are_non_trivial;
8904 };
8905 inline bool is_constructed() { return gConstructed; }
8906 struct B: public A {
8907 uint32_t b;
8908 };
8909 "};
8910 let cpp = indoc! {"
8911 bool gConstructed = false;
8912 "};
8913 let rs = quote! {
8914 assert!(!ffi::is_constructed());
8915 {
8916 moveit! {
8917 let mut _stack_obj = ffi::#ident::new();
8918 }
8919 assert!(ffi::is_constructed());
8920 #extra_bit
8921 }
8922 assert!(!ffi::is_constructed());
8923 };
8924 run_test(cpp, hdr, rs, &[&ident.to_string(), "is_constructed"], &[]);
8925}
8926
8927#[test]
8928fn test_destructor_moveit() {
8929 destruction_test(
8930 parse_quote! { A },
8931 Some(quote! {
8932 _stack_obj.as_mut().set(42);
8933 assert_eq!(_stack_obj.get(), 42);
8934 }),
8935 );
8936}
8937
8938#[test]
8939fn test_destructor_derived_moveit() {
8940 destruction_test(parse_quote! { B }, None);
8941}
8942
8943#[test]
8944fn test_copy_and_move_constructor_moveit() {
8945 let hdr = indoc! {"
8946 #include <stdint.h>
8947 #include <string>
8948 struct A {
8949 A() {}
8950 A(const A& other) : a(other.a+1) {}
8951 A(A&& other) : a(other.a+2) { other.a = 666; }
8952 void set(uint32_t val) { a = val; }
8953 uint32_t get() const { return a; }
8954 uint32_t a;
8955 std::string so_we_are_non_trivial;
8956 };
8957 "};
8958 let rs = quote! {
8959 moveit! {
8960 let mut stack_obj = ffi::A::new();
8961 }
8962 stack_obj.as_mut().set(42);
8963 moveit! {
8964 let stack_obj2 = autocxx::moveit::new::copy(stack_obj.as_ref());
8965 }
8966 assert_eq!(stack_obj2.get(), 43);
8967 assert_eq!(stack_obj.get(), 42);
8968 moveit! {
8969 let stack_obj3 = autocxx::moveit::new::mov(stack_obj);
8970 }
8971 assert_eq!(stack_obj3.get(), 44);
8972 // Following line prevented by moveit, even though it would
8973 // be possible in C++.
8974 // assert_eq!(stack_obj.get(), 666);
8975 };
8976 run_test("", hdr, rs, &["A"], &[]);
8977}
8978
8979// This test fails on Windows gnu but not on Windows msvc
8980#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
8981#[test]
8982fn test_uniqueptr_moveit() {
8983 let hdr = indoc! {"
8984 #include <stdint.h>
8985 #include <string>
8986 struct A {
8987 A() {}
8988 void set(uint32_t val) { a = val; }
8989 uint32_t get() const { return a; }
8990 uint32_t a;
8991 std::string so_we_are_non_trivial;
8992 };
8993 "};
8994 let rs = quote! {
8995 use autocxx::moveit::EmplaceUnpinned;
8996 let mut up_obj = cxx::UniquePtr::emplace(ffi::A::new());
8997 up_obj.as_mut().unwrap().set(42);
8998 assert_eq!(up_obj.get(), 42);
8999 };
9000 run_test("", hdr, rs, &["A"], &[]);
9001}
9002
9003// This test fails on Windows gnu but not on Windows msvc
9004#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
9005#[test]
9006fn test_various_emplacement() {
9007 let hdr = indoc! {"
9008 #include <stdint.h>
9009 #include <string>
9010 struct A {
9011 A() {}
9012 void set(uint32_t val) { a = val; }
9013 uint32_t get() const { return a; }
9014 uint32_t a;
9015 std::string so_we_are_non_trivial;
9016 };
9017 "};
9018 let rs = quote! {
9019 use autocxx::moveit::EmplaceUnpinned;
9020 use autocxx::moveit::Emplace;
9021 let mut up_obj = cxx::UniquePtr::emplace(ffi::A::new());
9022 up_obj.pin_mut().set(666);
9023 // Can't current move out of a UniquePtr
9024 let mut box_obj = Box::emplace(ffi::A::new());
9025 box_obj.as_mut().set(667);
9026 let box_obj2 = Box::emplace(autocxx::moveit::new::mov(box_obj));
9027 moveit! { let back_on_stack = autocxx::moveit::new::mov(box_obj2); }
9028 assert_eq!(back_on_stack.get(), 667);
9029 };
9030 run_test("", hdr, rs, &["A"], &[]);
9031}
9032
9033#[test]
9034fn test_emplace_uses_overridden_new_and_delete() {
9035 let hdr = indoc! {"
9036 #include <stdint.h>
9037 #include <string>
9038 struct A {
9039 A() {}
9040 void* operator new(size_t count);
9041 void operator delete(void* ptr) noexcept;
9042 void* operator new(size_t count, void* ptr);
9043 std::string so_we_are_non_trivial;
9044 };
9045 void reset_flags();
9046 bool was_new_called();
9047 bool was_delete_called();
9048 "};
9049 let cxx = indoc! {"
9050 bool new_called;
9051 bool delete_called;
9052 void reset_flags() {
9053 new_called = false;
9054 delete_called = false;
9055 }
9056 void* A::operator new(size_t count) {
9057 new_called = true;
9058 return ::operator new(count);
9059 }
9060 void* A::operator new(size_t count, void* ptr) {
9061 return ::operator new(count, ptr);
9062 }
9063 void A::operator delete(void* ptr) noexcept {
9064 delete_called = true;
9065 ::operator delete(ptr);
9066 }
9067 bool was_new_called() {
9068 return new_called;
9069 }
9070 bool was_delete_called() {
9071 return delete_called;
9072 }
9073 "};
9074 let rs = quote! {
9075 ffi::reset_flags();
9076 {
9077 let _ = ffi::A::new().within_unique_ptr();
9078 assert!(ffi::was_new_called());
9079 }
9080 assert!(ffi::was_delete_called());
9081 ffi::reset_flags();
9082 {
9083 use autocxx::moveit::EmplaceUnpinned;
9084 let _ = cxx::UniquePtr::emplace(ffi::A::new());
9085 }
9086 assert!(ffi::was_delete_called());
9087 };
9088 run_test(
9089 cxx,
9090 hdr,
9091 rs,
9092 &["A", "reset_flags", "was_new_called", "was_delete_called"],
9093 &[],
9094 );
9095}
9096
9097#[test]
9098fn test_pass_by_reference_to_value_param() {
9099 let hdr = indoc! {"
9100 #include <stdint.h>
9101 #include <string>
9102 struct A {
9103 A() : count(0) {}
9104 std::string so_we_are_non_trivial;
9105 uint32_t count;
9106 };
9107 void take_a(A a) {
9108 a.count++;
9109 }
9110 uint32_t report_on_a(const A& a) {
9111 return a.count;
9112 }
9113 "};
9114 let rs = quote! {
9115 let a = ffi::A::new().within_unique_ptr();
9116 ffi::take_a(a.as_ref().unwrap());
9117 ffi::take_a(&a); // syntactic sugar
9118 assert_eq!(ffi::report_on_a(&a), 0); // should have acted upon copies
9119 };
9120 run_test("", hdr, rs, &["A", "take_a", "report_on_a"], &[]);
9121}
9122
9123#[test]
9124fn test_explicit_everything() {
9125 let hdr = indoc! {"
9126 #include <stdint.h>
9127 #include <string>
9128 struct A {
9129 A() {} // default constructor
9130 A(A&&) {} // move constructor
9131 A(const A&) {} // copy constructor
9132 A& operator=(const A&) { return *this; } // copy assignment operator
9133 A& operator=(A&&) { return *this; } // move assignment operator
9134 ~A() {} // destructor
9135 void set(uint32_t val) { a = val; }
9136 uint32_t get() const { return a; }
9137 uint32_t a;
9138 std::string so_we_are_non_trivial;
9139 };
9140 "};
9141 let rs = quote! {};
9142 run_test("", hdr, rs, &["A"], &[]);
9143}
9144
9145#[test]
9146fn test_generate_ns() {
9147 let hdr = indoc! {"
9148 namespace A {
9149 inline void foo() {}
9150 inline void bar() {}
9151 }
9152 namespace B {
9153 inline void baz() {}
9154 }
9155 "};
9156 let rs = quote! {
9157 ffi::A::foo();
9158 };
9159 run_test_ex(
9160 "",
9161 hdr,
9162 rs,
9163 quote! {
9164 generate_ns!("A")
9165 safety!(unsafe_ffi)
9166 },
9167 None,
9168 None,
9169 None,
9170 );
9171}
9172
9173#[test]
9174fn test_no_constructor_make_unique_ns() {
9175 let hdr = indoc! {"
9176 #include <stdint.h>
9177 namespace B {
9178 struct A {
9179 uint32_t a;
9180 };
9181 }
9182 "};
9183 let rs = quote! {
9184 ffi::B::A::new().within_unique_ptr();
9185 };
9186 run_test("", hdr, rs, &["B::A"], &[]);
9187}
9188
9189#[test]
9190fn test_no_constructor_pod_make_unique() {
9191 let hdr = indoc! {"
9192 #include <stdint.h>
9193 struct A {
9194 uint32_t a;
9195 };
9196 "};
9197 let rs = quote! {
9198 ffi::A::new().within_unique_ptr();
9199 };
9200 run_test("", hdr, rs, &[], &["A"]);
9201}
9202
9203#[test]
9204fn test_no_constructor_pv() {
9205 let hdr = indoc! {"
9206 #include <stdint.h>
9207 class A {
9208 public:
9209 virtual ~A() {}
9210 virtual void foo() = 0;
9211 };
9212 "};
9213 let rs = quote! {};
9214 run_test("", hdr, rs, &["A"], &[]);
9215}
9216
9217#[test]
9218fn test_suppress_system_includes() {
9219 let hdr = indoc! {"
9220 #include <stdint.h>
9221 #include <string>
9222 inline void a() {};
9223 "};
9224 let rs = quote! {};
9225 run_test_ex(
9226 "",
9227 hdr,
9228 rs,
9229 quote! { generate("a")},
9230 Some(Box::new(SetSuppressSystemHeaders)),
9231 Some(Box::new(NoSystemHeadersChecker)),
9232 None,
9233 );
9234}
9235
9236#[test]
9237fn test_no_rvo_move() {
9238 let hdr = indoc! {"
9239 #include <memory>
9240 class A {
9241 public:
9242 static std::unique_ptr<A> create() { return std::make_unique<A>(); }
9243 };
9244 "};
9245 let rs = quote! {
9246 ffi::A::create();
9247 };
9248 run_test_ex(
9249 "",
9250 hdr,
9251 rs,
9252 quote! { generate!("A") },
9253 None,
9254 Some(Box::new(CppMatcher::new(
9255 &["return A::create();"],
9256 &["return std::move(A::create());"],
9257 ))),
9258 None,
9259 );
9260}
9261
9262#[test]
9263fn test_abstract_up() {
9264 let hdr = indoc! {"
9265 #include <memory>
9266 class A {
9267 public:
9268 virtual void foo() const = 0;
9269 virtual ~A() {}
9270 };
9271 class B : public A {
9272 public:
9273 void foo() const {}
9274 };
9275 inline std::unique_ptr<A> get_a() { return std::make_unique<B>(); }
9276 "};
9277 let rs = quote! {
9278 let a = ffi::get_a();
9279 a.foo();
9280 };
9281 run_test("", hdr, rs, &["A", "get_a"], &[]);
9282}
9283
9284#[test]
9285fn test_abstract_private() {
9286 let hdr = indoc! {"
9287 #include <memory>
9288 class A {
9289 virtual void foo() const = 0;
9290 public:
9291 virtual ~A() {}
9292 };
9293 "};
9294 let rs = quote! {};
9295 run_test("", hdr, rs, &["A"], &[]);
9296}
9297
9298#[test]
9299fn test_abstract_issue_979() {
9300 let hdr = indoc! {"
9301 class Test {
9302 virtual ~Test() {}
9303 virtual void TestBody() = 0;
9304 };
9305 "};
9306 let rs = quote! {};
9307 run_test("", hdr, rs, &["Test"], &[]);
9308}
9309
9310#[test]
9311fn test_class_having_protected_method() {
9312 let hdr = indoc! {"
9313 #include <cstdint>
9314 class A {
9315 protected:
9316 inline uint32_t protected_method() { return 0; }
9317 };
9318 "};
9319 let rs = quote! {};
9320 run_test("", hdr, rs, &[], &["A"]);
9321}
9322
9323#[test]
9324fn test_protected_inner_class() {
9325 let hdr = indoc! {"
9326 #include <cstdint>
9327 inline uint32_t DoMath(uint32_t a) {
9328 return a * 3;
9329 }
9330
9331 class A {
9332 protected:
9333 inline uint32_t protected_method() { return 0; }
9334
9335 struct B {
9336 int x;
9337 };
9338
9339 inline B protected_method_2() {
9340 return { 0 };
9341 }
9342 };
9343 "};
9344 let rs = quote! {};
9345 run_test("", hdr, rs, &["A"], &[]);
9346}
9347
9348#[test]
9349fn test_private_inner_class() {
9350 let hdr = indoc! {"
9351 #include <cstdint>
9352 inline uint32_t DoMath(uint32_t a) {
9353 return a * 3;
9354 }
9355
9356 class A {
9357 protected:
9358 inline uint32_t protected_method() { return 0; }
9359
9360 private:
9361 struct B {
9362 int x;
9363 };
9364
9365 inline B private_method_2() {
9366 return { 0 };
9367 }
9368 };
9369 "};
9370 let rs = quote! {};
9371 run_test("", hdr, rs, &["A"], &[]);
9372}
9373
9374#[test]
9375fn test_class_having_private_method() {
9376 let hdr = indoc! {"
9377 #include <cstdint>
9378 class A {
9379 private:
9380 inline uint32_t private_method() { return 0; }
9381 };
9382 "};
9383 let rs = quote! {};
9384 run_test("", hdr, rs, &[], &["A"]);
9385}
9386
9387#[test]
9388#[ignore] // https://github.com/google/autocxx/issues/787
9389fn test_chrono_problem() {
9390 let hdr = indoc! {"
9391 #include <chrono>
9392 struct Clock {
9393 typedef std::chrono::nanoseconds duration;
9394 };
9395 struct Class {
9396 int a() { return 42; }
9397 std::chrono::time_point<Clock> b();
9398 };
9399 "};
9400 let rs = quote! {};
9401 run_test("", hdr, rs, &[], &["Class"]);
9402}
9403
9404fn size_and_alignment_test(pod: bool) {
9405 static TYPES: [(&str, &str); 6] = [
9406 ("A", "struct A { uint8_t a; };"),
9407 ("B", "struct B { uint32_t a; };"),
9408 ("C", "struct C { uint64_t a; };"),
9409 ("D", "enum D { Z, X };"),
9410 ("E", "struct E { uint8_t a; uint32_t b; };"),
9411 ("F", "struct F { uint32_t a; uint8_t b; };"),
9412 ];
9413 let type_definitions = TYPES.iter().map(|(_, def)| *def).join("\n");
9414 let function_definitions = TYPES.iter().map(|(name, _)| format!("inline size_t get_sizeof_{}() {{ return sizeof({}); }}\ninline size_t get_alignof_{}() {{ return alignof({}); }}\n",
9415 name, name, name, name)).join("\n");
9416 let hdr = format!(
9417 indoc! {"
9418 #include <cstdint>
9419 #include <cstddef>
9420 {}
9421 {}
9422 "},
9423 type_definitions, function_definitions
9424 );
9425 #[allow(clippy::unnecessary_to_owned)] // wrongly triggers on into_iter() below
9426 let allowlist_fns: Vec<String> = TYPES
9427 .iter()
9428 .flat_map(|(name, _)| {
9429 [
9430 format!("get_sizeof_{}", name),
9431 format!("get_alignof_{}", name),
9432 ]
9433 .to_vec()
9434 .into_iter()
9435 })
9436 .collect_vec();
9437 let allowlist_types: Vec<String> = TYPES.iter().map(|(name, _)| name.to_string()).collect_vec();
9438 let allowlist_both = allowlist_types
9439 .iter()
9440 .cloned()
9441 .chain(allowlist_fns.iter().cloned())
9442 .collect_vec();
9443 let allowlist_types: Vec<&str> = allowlist_types.iter().map(AsRef::as_ref).collect_vec();
9444 let allowlist_fns: Vec<&str> = allowlist_fns.iter().map(AsRef::as_ref).collect_vec();
9445 let allowlist_both: Vec<&str> = allowlist_both.iter().map(AsRef::as_ref).collect_vec();
9446 let rs = TYPES.iter().fold(quote! {}, |mut accumulator, (name, _)| {
9447 let get_align_symbol =
9448 proc_macro2::Ident::new(&format!("get_alignof_{}", name), Span::call_site());
9449 let get_size_symbol =
9450 proc_macro2::Ident::new(&format!("get_sizeof_{}", name), Span::call_site());
9451 let type_symbol = proc_macro2::Ident::new(name, Span::call_site());
9452 accumulator.extend(quote! {
9453 let c_size = ffi::#get_size_symbol();
9454 let c_align = ffi::#get_align_symbol();
9455 assert_eq!(std::mem::size_of::<ffi::#type_symbol>(), c_size);
9456 assert_eq!(std::mem::align_of::<ffi::#type_symbol>(), c_align);
9457 });
9458 accumulator
9459 });
9460 if pod {
9461 run_test("", &hdr, rs, &allowlist_fns, &allowlist_types);
9462 } else {
9463 run_test("", &hdr, rs, &allowlist_both, &[]);
9464 }
9465}
9466
9467#[test]
9468fn test_sizes_and_alignment_nonpod() {
9469 size_and_alignment_test(false)
9470}
9471
9472#[test]
9473fn test_sizes_and_alignment_pod() {
9474 size_and_alignment_test(true)
9475}
9476
9477#[test]
9478fn test_nested_class_methods() {
9479 let hdr = indoc! {"
9480 #include <cstdint>
9481 class A {
9482 public:
9483 virtual ~A() {}
9484 struct B {
9485 virtual void b() const {}
9486 };
9487 virtual void a() const {}
9488 struct C {
9489 virtual void b() const {}
9490 };
9491 virtual void c() const {}
9492 struct D {
9493 virtual void b() const {}
9494 };
9495 };
9496 "};
9497 let rs = quote! {
9498 let a = ffi::A::new().within_unique_ptr();
9499 a.a();
9500 a.c();
9501 };
9502 run_test("", hdr, rs, &["A"], &[]);
9503}
9504
9505#[test]
9506fn test_call_superclass() {
9507 let hdr = indoc! {"
9508 #include <memory>
9509 class A {
9510 public:
9511 virtual void foo() const {};
9512 virtual ~A() {}
9513 };
9514 class B : public A {
9515 public:
9516 void bar() const {}
9517 };
9518 inline std::unique_ptr<B> get_b() { return std::make_unique<B>(); }
9519 "};
9520 let rs = quote! {
9521 let b = ffi::get_b();
9522 b.as_ref().unwrap().as_ref().foo();
9523 };
9524 run_test("", hdr, rs, &["A", "B", "get_b"], &[]);
9525}
9526
9527#[test]
9528fn test_pass_superclass() {
9529 let hdr = indoc! {"
9530 #include <memory>
9531 class A {
9532 public:
9533 virtual void foo() const {};
9534 virtual ~A() {}
9535 };
9536 class B : public A {
9537 public:
9538 void bar() const {}
9539 };
9540 inline std::unique_ptr<B> get_b() { return std::make_unique<B>(); }
9541 inline void take_a(const A&) {}
9542 "};
9543 let rs = quote! {
9544 let b = ffi::get_b();
9545 ffi::take_a(b.as_ref().unwrap().as_ref());
9546 };
9547 run_test("", hdr, rs, &["A", "B", "get_b", "take_a"], &[]);
9548}
9549
9550#[test]
9551fn test_issue486_multi_types() {
9552 let hdr = indoc! {"
9553 namespace a {
9554 namespace spanner {
9555 struct Key {};
9556 }
9557 } // namespace a
9558 namespace b {
9559 namespace spanner {
9560 typedef int Key;
9561 }
9562 } // namespace b
9563 namespace c {
9564 namespace spanner {
9565 enum Key { A, B };
9566 }
9567 } // namespace c
9568 namespace spanner {
9569 class Key {
9570 public:
9571 bool a(a::spanner::Key &);
9572 bool b(b::spanner::Key &);
9573 bool c(c::spanner::Key &);
9574 };
9575 } // namespace spanner
9576 "};
9577 let rs = quote! {};
9578 run_test(
9579 "",
9580 hdr,
9581 rs,
9582 &["spanner::Key", "a::spanner::Key", "b::spanner::Key"],
9583 &[],
9584 );
9585}
9586
9587#[test]
9588/// Tests types with various forms of copy, move, and default constructors. Calls the things which
9589/// should be generated, and will produce C++ compile failures if other wrappers are generated.
9590///
9591/// Specifically, we can have the cross product of any of these:
9592/// * Explicitly deleted
9593/// * Implicitly defaulted
9594/// * User declared
9595/// * Explicitly defaulted
9596/// Not handled yet: https://github.com/google/autocxx/issues/815.
9597/// Once this is handled, add equivalents of all the implicitly defaulted cases, at all
9598/// visibility levels.
9599/// applied to each of these:
9600/// * Default constructor
9601/// * Copy constructor
9602/// * Move constructor
9603/// in any of these:
9604/// * The class itself
9605/// * A base class
9606/// * A field of the class
9607/// * A field of a base class
9608/// with any of these access modifiers:
9609/// * private (impossible for implicitly defaulted)
9610/// * protected (impossible for implicitly defaulted)
9611/// * public
9612///
9613/// Various combinations of these lead to the default versions being deleted. The move and copy
9614/// ones also interact with each other in various ways.
9615///
9616/// TODO: Remove all the `int x` members after https://github.com/google/autocxx/issues/832 is
9617/// fixed.
9618fn test_implicit_constructor_rules() {
9619 let cxx = "";
9620 let hdr = indoc! {"
9621 struct AllImplicitlyDefaulted {
9622 void a() const {}
9623 };
9624
9625 struct PublicDeleted {
9626 PublicDeleted() = delete;
9627 PublicDeleted(const PublicDeleted&) = delete;
9628 PublicDeleted(PublicDeleted&&) = delete;
9629
9630 void a() const {}
9631
9632 int x;
9633 };
9634 struct PublicDeletedDefault {
9635 PublicDeletedDefault() = delete;
9636
9637 void a() const {}
9638
9639 int x;
9640 };
9641 struct PublicDeletedCopy {
9642 PublicDeletedCopy() = default;
9643 PublicDeletedCopy(const PublicDeletedCopy&) = delete;
9644
9645 void a() const {}
9646
9647 int x;
9648 };
9649 struct PublicDeletedCopyNoDefault {
9650 PublicDeletedCopyNoDefault(const PublicDeletedCopyNoDefault&) = delete;
9651
9652 void a() const {}
9653
9654 int x;
9655 };
9656 struct PublicMoveDeletedCopy {
9657 PublicMoveDeletedCopy() = default;
9658 PublicMoveDeletedCopy(const PublicMoveDeletedCopy&) = delete;
9659 PublicMoveDeletedCopy(PublicMoveDeletedCopy&&) = default;
9660
9661 void a() const {}
9662
9663 int x;
9664 };
9665 struct PublicDeletedMove {
9666 PublicDeletedMove() = default;
9667 PublicDeletedMove(PublicDeletedMove&&) = delete;
9668
9669 void a() const {}
9670
9671 int x;
9672 };
9673 struct PublicDeletedDestructor {
9674 PublicDeletedDestructor() = default;
9675 ~PublicDeletedDestructor() = delete;
9676
9677 void a() const {}
9678
9679 int x;
9680 };
9681 struct PublicDestructor {
9682 PublicDestructor() = default;
9683 ~PublicDestructor() = default;
9684
9685 void a() const {}
9686
9687 int x;
9688 };
9689
9690 struct ProtectedDeleted {
9691 void a() const {}
9692
9693 int x;
9694
9695 protected:
9696 ProtectedDeleted() = delete;
9697 ProtectedDeleted(const ProtectedDeleted&) = delete;
9698 ProtectedDeleted(ProtectedDeleted&&) = delete;
9699 };
9700 struct ProtectedDeletedDefault {
9701 void a() const {}
9702
9703 int x;
9704
9705 protected:
9706 ProtectedDeletedDefault() = delete;
9707 };
9708 struct ProtectedDeletedCopy {
9709 ProtectedDeletedCopy() = default;
9710
9711 void a() const {}
9712
9713 int x;
9714
9715 protected:
9716 ProtectedDeletedCopy(const ProtectedDeletedCopy&) = delete;
9717 };
9718 struct ProtectedDeletedCopyNoDefault {
9719 void a() const {}
9720
9721 int x;
9722
9723 protected:
9724 ProtectedDeletedCopyNoDefault(const ProtectedDeletedCopyNoDefault&) = delete;
9725 };
9726 struct ProtectedMoveDeletedCopy {
9727 ProtectedMoveDeletedCopy() = default;
9728
9729 void a() const {}
9730
9731 int x;
9732
9733 protected:
9734 ProtectedMoveDeletedCopy(const ProtectedMoveDeletedCopy&) = delete;
9735 ProtectedMoveDeletedCopy(ProtectedMoveDeletedCopy&&) = default;
9736 };
9737 struct ProtectedDeletedMove {
9738 ProtectedDeletedMove() = default;
9739
9740 void a() const {}
9741
9742 int x;
9743
9744 protected:
9745 ProtectedDeletedMove(ProtectedDeletedMove&&) = delete;
9746 };
9747 struct ProtectedDeletedDestructor {
9748 ProtectedDeletedDestructor() = default;
9749
9750 void a() const {}
9751
9752 int x;
9753
9754 protected:
9755 ~ProtectedDeletedDestructor() = delete;
9756 };
9757 struct ProtectedDestructor {
9758 ProtectedDestructor() = default;
9759
9760 void a() const {}
9761
9762 int x;
9763
9764 protected:
9765 ~ProtectedDestructor() = default;
9766 };
9767
9768 struct PrivateDeleted {
9769 void a() const {}
9770
9771 int x;
9772
9773 private:
9774 PrivateDeleted() = delete;
9775 PrivateDeleted(const PrivateDeleted&) = delete;
9776 PrivateDeleted(PrivateDeleted&&) = delete;
9777 };
9778 struct PrivateDeletedDefault {
9779 void a() const {}
9780
9781 int x;
9782
9783 private:
9784 PrivateDeletedDefault() = delete;
9785 };
9786 struct PrivateDeletedCopy {
9787 PrivateDeletedCopy() = default;
9788
9789 void a() const {}
9790
9791 int x;
9792
9793 private:
9794 PrivateDeletedCopy(const PrivateDeletedCopy&) = delete;
9795 };
9796 struct PrivateDeletedCopyNoDefault {
9797 void a() const {}
9798
9799 int x;
9800
9801 private:
9802 PrivateDeletedCopyNoDefault(const PrivateDeletedCopyNoDefault&) = delete;
9803 };
9804 struct PrivateMoveDeletedCopy {
9805 PrivateMoveDeletedCopy() = default;
9806
9807 void a() const {}
9808
9809 int x;
9810
9811 private:
9812 PrivateMoveDeletedCopy(const PrivateMoveDeletedCopy&) = delete;
9813 PrivateMoveDeletedCopy(PrivateMoveDeletedCopy&&) = default;
9814 };
9815 struct PrivateDeletedMove {
9816 PrivateDeletedMove() = default;
9817
9818 void a() const {}
9819
9820 int x;
9821
9822 private:
9823 PrivateDeletedMove(PrivateDeletedMove&&) = delete;
9824 };
9825 struct PrivateDeletedDestructor {
9826 PrivateDeletedDestructor() = default;
9827
9828 void a() const {}
9829
9830 int x;
9831
9832 private:
9833 ~PrivateDeletedDestructor() = delete;
9834 };
9835 struct PrivateDestructor {
9836 PrivateDestructor() = default;
9837
9838 void a() const {}
9839
9840 int x;
9841
9842 private:
9843 ~PrivateDestructor() = default;
9844 };
9845
9846 struct NonConstCopy {
9847 NonConstCopy() = default;
9848
9849 NonConstCopy(NonConstCopy&) {}
9850 NonConstCopy(NonConstCopy&&) = default;
9851
9852 void a() const {}
9853 };
9854 struct TwoCopy {
9855 TwoCopy() = default;
9856
9857 TwoCopy(TwoCopy&) {}
9858 TwoCopy(const TwoCopy&) {}
9859 TwoCopy(TwoCopy&&) = default;
9860
9861 void a() const {}
9862 };
9863
9864 struct MemberPointerDeleted {
9865 PublicDeleted *x;
9866
9867 void a() const {}
9868 };
9869
9870 struct MemberConstPointerDeleted {
9871 PublicDeleted *const x;
9872
9873 void a() const {}
9874 };
9875
9876 struct MemberConst {
9877 const int x;
9878
9879 void a() const {}
9880 };
9881
9882 struct MemberReferenceDeleted {
9883 PublicDeleted &x;
9884
9885 void a() const {}
9886 };
9887
9888 struct MemberConstReferenceDeleted {
9889 const PublicDeleted &x;
9890
9891 void a() const {}
9892 };
9893
9894 struct MemberReference {
9895 int &x;
9896
9897 void a() const {}
9898 };
9899
9900 struct MemberConstReference {
9901 const int &x;
9902
9903 void a() const {}
9904 };
9905
9906 struct MemberRvalueReferenceDeleted {
9907 PublicDeleted &&x;
9908
9909 void a() const {}
9910 };
9911
9912 struct MemberRvalueReference {
9913 int &&x;
9914
9915 void a() const {}
9916 };
9917
9918 struct BasePublicDeleted : public PublicDeleted {};
9919 struct BasePublicDeletedDefault : public PublicDeletedDefault {};
9920 struct BasePublicDeletedCopy : public PublicDeletedCopy {};
9921 struct BasePublicDeletedCopyNoDefault : public PublicDeletedCopyNoDefault { };
9922 struct BasePublicMoveDeletedCopy : public PublicMoveDeletedCopy {};
9923 struct BasePublicDeletedMove : public PublicDeletedMove {};
9924 struct BasePublicDeletedDestructor : public PublicDeletedDestructor {};
9925 struct BasePublicDestructor : public PublicDestructor {};
9926
9927 struct MemberPublicDeleted {
9928 void a() const {}
9929
9930 PublicDeleted member;
9931 };
9932 struct MemberPublicDeletedDefault {
9933 void a() const {}
9934
9935 PublicDeletedDefault member;
9936 };
9937 struct MemberPublicDeletedCopy {
9938 void a() const {}
9939
9940 PublicDeletedCopy member;
9941 };
9942 struct MemberPublicDeletedCopyNoDefault {
9943 void a() const {}
9944
9945 PublicDeletedCopyNoDefault member;
9946 };
9947 struct MemberPublicMoveDeletedCopy {
9948 void a() const {}
9949
9950 PublicMoveDeletedCopy member;
9951 };
9952 struct MemberPublicDeletedMove {
9953 void a() const {}
9954
9955 PublicDeletedMove member;
9956 };
9957 struct MemberPublicDeletedDestructor {
9958 void a() const {}
9959
9960 PublicDeletedDestructor member;
9961 };
9962 struct MemberPublicDestructor {
9963 void a() const {}
9964
9965 PublicDestructor member;
9966 };
9967
9968 struct BaseMemberPublicDeleted : public MemberPublicDeleted {};
9969 struct BaseMemberPublicDeletedDefault : public MemberPublicDeletedDefault {};
9970 struct BaseMemberPublicDeletedCopy : public MemberPublicDeletedCopy {};
9971 struct BaseMemberPublicDeletedCopyNoDefault : public MemberPublicDeletedCopyNoDefault {};
9972 struct BaseMemberPublicMoveDeletedCopy : public MemberPublicMoveDeletedCopy {};
9973 struct BaseMemberPublicDeletedMove : public MemberPublicDeletedMove {};
9974 struct BaseMemberPublicDeletedDestructor : public MemberPublicDeletedDestructor {};
9975 struct BaseMemberPublicDestructor : public MemberPublicDestructor {};
9976
9977 struct BaseProtectedDeleted : public ProtectedDeleted {};
9978 struct BaseProtectedDeletedDefault : public ProtectedDeletedDefault {};
9979 struct BaseProtectedDeletedCopy : public ProtectedDeletedCopy {};
9980 struct BaseProtectedDeletedCopyNoDefault : public ProtectedDeletedCopyNoDefault {};
9981 struct BaseProtectedMoveDeletedCopy : public ProtectedMoveDeletedCopy {};
9982 struct BaseProtectedDeletedMove : public ProtectedDeletedMove {};
9983 struct BaseProtectedDeletedDestructor : public ProtectedDeletedDestructor {};
9984 struct BaseProtectedDestructor : public ProtectedDestructor {};
9985
9986 struct MemberProtectedDeleted {
9987 void a() const {}
9988
9989 ProtectedDeleted member;
9990 };
9991 struct MemberProtectedDeletedDefault {
9992 void a() const {}
9993
9994 ProtectedDeletedDefault member;
9995 };
9996 struct MemberProtectedDeletedCopy {
9997 void a() const {}
9998
9999 ProtectedDeletedCopy member;
10000 };
10001 struct MemberProtectedDeletedCopyNoDefault {
10002 void a() const {}
10003
10004 ProtectedDeletedCopyNoDefault member;
10005 };
10006 struct MemberProtectedMoveDeletedCopy {
10007 void a() const {}
10008
10009 ProtectedMoveDeletedCopy member;
10010 };
10011 struct MemberProtectedDeletedMove {
10012 void a() const {}
10013
10014 ProtectedDeletedMove member;
10015 };
10016 struct MemberProtectedDeletedDestructor {
10017 void a() const {}
10018
10019 ProtectedDeletedDestructor member;
10020 };
10021 struct MemberProtectedDestructor {
10022 void a() const {}
10023
10024 ProtectedDestructor member;
10025 };
10026
10027 struct BaseMemberProtectedDeleted : public MemberProtectedDeleted {};
10028 struct BaseMemberProtectedDeletedDefault : public MemberProtectedDeletedDefault {};
10029 struct BaseMemberProtectedDeletedCopy : public MemberProtectedDeletedCopy {};
10030 struct BaseMemberProtectedDeletedCopyNoDefault : public MemberProtectedDeletedCopyNoDefault {};
10031 struct BaseMemberProtectedMoveDeletedCopy : public MemberProtectedMoveDeletedCopy {};
10032 struct BaseMemberProtectedDeletedMove : public MemberProtectedDeletedMove {};
10033 struct BaseMemberProtectedDeletedDestructor : public MemberProtectedDeletedDestructor {};
10034 struct BaseMemberProtectedDestructor : public MemberProtectedDestructor {};
10035
10036 struct BasePrivateDeleted : public PrivateDeleted {};
10037 struct BasePrivateDeletedDefault : public PrivateDeletedDefault {};
10038 struct BasePrivateDeletedCopy : public PrivateDeletedCopy {};
10039 struct BasePrivateDeletedCopyNoDefault : public PrivateDeletedCopyNoDefault {};
10040 struct BasePrivateMoveDeletedCopy : public PrivateMoveDeletedCopy {};
10041 struct BasePrivateDeletedMove : public PrivateDeletedMove {};
10042 struct BasePrivateDeletedDestructor : public PrivateDeletedDestructor {};
10043 struct BasePrivateDestructor : public PrivateDestructor {};
10044
10045 struct MemberPrivateDeleted {
10046 void a() const {}
10047
10048 PrivateDeleted member;
10049 };
10050 struct MemberPrivateDeletedDefault {
10051 void a() const {}
10052
10053 PrivateDeletedDefault member;
10054 };
10055 struct MemberPrivateDeletedCopy {
10056 void a() const {}
10057
10058 PrivateDeletedCopy member;
10059 };
10060 struct MemberPrivateDeletedCopyNoDefault {
10061 void a() const {}
10062
10063 PrivateDeletedCopyNoDefault member;
10064 };
10065 struct MemberPrivateMoveDeletedCopy {
10066 void a() const {}
10067
10068 PrivateMoveDeletedCopy member;
10069 };
10070 struct MemberPrivateDeletedMove {
10071 void a() const {}
10072
10073 PrivateDeletedMove member;
10074 };
10075 struct MemberPrivateDeletedDestructor {
10076 void a() const {}
10077
10078 PrivateDeletedDestructor member;
10079 };
10080 struct MemberPrivateDestructor {
10081 void a() const {}
10082
10083 PrivateDestructor member;
10084 };
10085
10086 struct BaseMemberPrivateDeleted : public MemberPrivateDeleted {};
10087 struct BaseMemberPrivateDeletedDefault : public MemberPrivateDeletedDefault {};
10088 struct BaseMemberPrivateDeletedCopy : public MemberPrivateDeletedCopy {};
10089 struct BaseMemberPrivateDeletedCopyNoDefault : public MemberPrivateDeletedCopyNoDefault {};
10090 struct BaseMemberPrivateMoveDeletedCopy : public MemberPrivateMoveDeletedCopy {};
10091 struct BaseMemberPrivateDeletedMove : public MemberPrivateDeletedMove {};
10092 struct BaseMemberPrivateDeletedDestructor : public MemberPrivateDeletedDestructor {};
10093 struct BaseMemberPrivateDestructor : public MemberPrivateDestructor {};
10094 "};
10095 let rs = quote! {
10096 // Some macros to test various operations on our types. Note that some of them define
10097 // functions which take arguments that the APIs defined in this test have no way to
10098 // produce, because we have C++ types which can't be constructed (for example). In a real
10099 // program, there might be other C++ APIs which can instantiate these types.
10100
10101 // TODO: https://github.com/google/autocxx/issues/829: Should this be merged with
10102 // `test_make_unique`? Currently types where the Rust wrappers permit this but not that
10103 // aren't running C++ destructors.
10104 macro_rules! test_constructible {
10105 [$t:ty] => {
10106 moveit! {
10107 let _moveit_t = <$t>::new();
10108 }
10109 }
10110 }
10111 macro_rules! test_make_unique {
10112 [$t:ty] => {
10113 let _unique_t = <$t>::new().within_unique_ptr();
10114 }
10115 }
10116 macro_rules! test_copyable {
10117 [$t:ty] => {
10118 {
10119 fn test_copyable(moveit_t: impl autocxx::moveit::new::New<Output = $t>) {
10120 moveit! {
10121 let moveit_t = moveit_t;
10122 let _copied_t = autocxx::moveit::new::copy(moveit_t);
10123 }
10124 }
10125 }
10126 }
10127 }
10128 macro_rules! test_movable {
10129 [$t:ty] => {
10130 {
10131 fn test_movable(moveit_t: impl autocxx::moveit::new::New<Output = $t>) {
10132 moveit! {
10133 let moveit_t = moveit_t;
10134 let _moved_t = autocxx::moveit::new::mov(moveit_t);
10135 }
10136 }
10137 }
10138 }
10139 }
10140 macro_rules! test_call_a {
10141 [$t:ty] => {
10142 {
10143 fn test_call_a(t: &$t) {
10144 t.a();
10145 }
10146 }
10147 }
10148 }
10149 macro_rules! test_call_a_as {
10150 [$t:ty, $parent:ty] => {
10151 {
10152 fn test_call_a(t: &$t) {
10153 let t: &$parent = t.as_ref();
10154 t.a();
10155 }
10156 }
10157 }
10158 }
10159
10160 test_constructible![ffi::AllImplicitlyDefaulted];
10161 test_make_unique![ffi::AllImplicitlyDefaulted];
10162 test_copyable![ffi::AllImplicitlyDefaulted];
10163 test_movable![ffi::AllImplicitlyDefaulted];
10164 test_call_a![ffi::AllImplicitlyDefaulted];
10165
10166 test_call_a![ffi::PublicDeleted];
10167
10168 test_copyable![ffi::PublicDeletedDefault];
10169 test_movable![ffi::PublicDeletedDefault];
10170 test_call_a![ffi::PublicDeletedDefault];
10171
10172 test_constructible![ffi::PublicDeletedCopy];
10173 test_make_unique![ffi::PublicDeletedCopy];
10174 test_call_a![ffi::PublicDeletedCopy];
10175
10176 test_call_a![ffi::PublicDeletedCopyNoDefault];
10177
10178 test_constructible![ffi::PublicMoveDeletedCopy];
10179 test_make_unique![ffi::PublicMoveDeletedCopy];
10180 test_movable![ffi::PublicMoveDeletedCopy];
10181 test_call_a![ffi::PublicMoveDeletedCopy];
10182
10183 test_constructible![ffi::PublicDeletedMove];
10184 test_make_unique![ffi::PublicDeletedMove];
10185 test_call_a![ffi::PublicDeletedMove];
10186
10187 test_constructible![ffi::PublicDeletedDestructor];
10188 test_copyable![ffi::PublicDeletedDestructor];
10189 test_call_a![ffi::PublicDeletedDestructor];
10190
10191 test_constructible![ffi::PublicDestructor];
10192 test_make_unique![ffi::PublicDestructor];
10193 test_copyable![ffi::PublicDestructor];
10194 test_call_a![ffi::PublicDestructor];
10195
10196 test_call_a![ffi::ProtectedDeleted];
10197
10198 test_copyable![ffi::ProtectedDeletedDefault];
10199 test_movable![ffi::ProtectedDeletedDefault];
10200 test_call_a![ffi::ProtectedDeletedDefault];
10201
10202 test_constructible![ffi::ProtectedDeletedCopy];
10203 test_make_unique![ffi::ProtectedDeletedCopy];
10204 test_call_a![ffi::ProtectedDeletedCopy];
10205
10206 test_call_a![ffi::ProtectedDeletedCopyNoDefault];
10207
10208 test_constructible![ffi::ProtectedMoveDeletedCopy];
10209 test_make_unique![ffi::ProtectedMoveDeletedCopy];
10210 test_call_a![ffi::ProtectedMoveDeletedCopy];
10211
10212 test_constructible![ffi::ProtectedDeletedMove];
10213 test_make_unique![ffi::ProtectedDeletedMove];
10214 test_call_a![ffi::ProtectedDeletedMove];
10215
10216 test_constructible![ffi::ProtectedDeletedDestructor];
10217 test_copyable![ffi::ProtectedDeletedDestructor];
10218 test_call_a![ffi::ProtectedDeletedDestructor];
10219
10220 test_constructible![ffi::ProtectedDestructor];
10221 test_copyable![ffi::ProtectedDestructor];
10222 test_call_a![ffi::ProtectedDestructor];
10223
10224 test_call_a![ffi::PrivateDeleted];
10225
10226 test_copyable![ffi::PrivateDeletedDefault];
10227 test_movable![ffi::PrivateDeletedDefault];
10228 test_call_a![ffi::PrivateDeletedDefault];
10229
10230 test_constructible![ffi::PrivateDeletedCopy];
10231 test_make_unique![ffi::PrivateDeletedCopy];
10232 test_call_a![ffi::PrivateDeletedCopy];
10233
10234 test_call_a![ffi::PrivateDeletedCopyNoDefault];
10235
10236 test_constructible![ffi::PrivateMoveDeletedCopy];
10237 test_make_unique![ffi::PrivateMoveDeletedCopy];
10238 test_call_a![ffi::PrivateMoveDeletedCopy];
10239
10240 test_constructible![ffi::PrivateDeletedMove];
10241 test_make_unique![ffi::PrivateDeletedMove];
10242 test_call_a![ffi::PrivateDeletedMove];
10243
10244 test_constructible![ffi::PrivateDeletedDestructor];
10245 test_copyable![ffi::PrivateDeletedDestructor];
10246 test_call_a![ffi::PrivateDeletedDestructor];
10247
10248 test_constructible![ffi::PrivateDestructor];
10249 test_copyable![ffi::PrivateDestructor];
10250 test_call_a![ffi::PrivateDestructor];
10251
10252 test_constructible![ffi::NonConstCopy];
10253 test_make_unique![ffi::NonConstCopy];
10254 test_movable![ffi::NonConstCopy];
10255 test_call_a![ffi::NonConstCopy];
10256
10257 test_constructible![ffi::TwoCopy];
10258 test_make_unique![ffi::TwoCopy];
10259 test_copyable![ffi::TwoCopy];
10260 test_movable![ffi::TwoCopy];
10261 test_call_a![ffi::TwoCopy];
10262
10263 // TODO: https://github.com/google/autocxx/issues/865
10264 // Treat pointers and references differently so this has a default constructor.
10265 //test_constructible![ffi::MemberPointerDeleted];
10266 //test_make_unique![ffi::MemberPointerDeleted];
10267 test_copyable![ffi::MemberPointerDeleted];
10268 test_movable![ffi::MemberPointerDeleted];
10269 test_call_a![ffi::MemberPointerDeleted];
10270
10271 test_copyable![ffi::MemberConstPointerDeleted];
10272 test_movable![ffi::MemberConstPointerDeleted];
10273 test_call_a![ffi::MemberConstPointerDeleted];
10274
10275 //test_copyable![ffi::MemberConst];
10276 //test_movable![ffi::MemberConst];
10277 //test_call_a![ffi::MemberConst];
10278
10279 test_copyable![ffi::MemberReferenceDeleted];
10280 test_movable![ffi::MemberReferenceDeleted];
10281 test_call_a![ffi::MemberReferenceDeleted];
10282
10283 test_copyable![ffi::MemberConstReferenceDeleted];
10284 test_movable![ffi::MemberConstReferenceDeleted];
10285 test_call_a![ffi::MemberConstReferenceDeleted];
10286
10287 test_copyable![ffi::MemberReference];
10288 test_movable![ffi::MemberReference];
10289 test_call_a![ffi::MemberReference];
10290
10291 test_copyable![ffi::MemberConstReference];
10292 test_movable![ffi::MemberConstReference];
10293 test_call_a![ffi::MemberConstReference];
10294
10295 test_movable![ffi::MemberRvalueReferenceDeleted];
10296 test_call_a![ffi::MemberRvalueReferenceDeleted];
10297
10298 test_movable![ffi::MemberRvalueReference];
10299 test_call_a![ffi::MemberRvalueReference];
10300
10301 test_call_a_as![ffi::BasePublicDeleted, ffi::PublicDeleted];
10302
10303 test_copyable![ffi::BasePublicDeletedDefault];
10304 test_movable![ffi::BasePublicDeletedDefault];
10305 test_call_a_as![ffi::BasePublicDeletedDefault, ffi::PublicDeletedDefault];
10306
10307 test_constructible![ffi::BasePublicDeletedCopy];
10308 test_make_unique![ffi::BasePublicDeletedCopy];
10309 test_call_a_as![ffi::BasePublicDeletedCopy, ffi::PublicDeletedCopy];
10310
10311 test_call_a_as![ffi::BasePublicDeletedCopyNoDefault, ffi::PublicDeletedCopyNoDefault];
10312
10313 test_constructible![ffi::BasePublicMoveDeletedCopy];
10314 test_make_unique![ffi::BasePublicMoveDeletedCopy];
10315 test_movable![ffi::BasePublicMoveDeletedCopy];
10316 test_call_a_as![ffi::BasePublicMoveDeletedCopy, ffi::PublicMoveDeletedCopy];
10317
10318 test_constructible![ffi::BasePublicDeletedMove];
10319 test_make_unique![ffi::BasePublicDeletedMove];
10320 test_call_a_as![ffi::BasePublicDeletedMove, ffi::PublicDeletedMove];
10321
10322 test_call_a_as![ffi::BasePublicDeletedDestructor, ffi::PublicDeletedDestructor];
10323
10324 test_constructible![ffi::BasePublicDestructor];
10325 test_make_unique![ffi::BasePublicDestructor];
10326 test_copyable![ffi::BasePublicDestructor];
10327 test_call_a_as![ffi::BasePublicDestructor, ffi::PublicDestructor];
10328
10329 test_call_a![ffi::MemberPublicDeleted];
10330
10331 test_copyable![ffi::MemberPublicDeletedDefault];
10332 test_movable![ffi::MemberPublicDeletedDefault];
10333 test_call_a![ffi::MemberPublicDeletedDefault];
10334
10335 test_constructible![ffi::MemberPublicDeletedCopy];
10336 test_make_unique![ffi::MemberPublicDeletedCopy];
10337 test_call_a![ffi::MemberPublicDeletedCopy];
10338
10339 test_call_a![ffi::MemberPublicDeletedCopyNoDefault];
10340
10341 test_constructible![ffi::MemberPublicMoveDeletedCopy];
10342 test_make_unique![ffi::MemberPublicMoveDeletedCopy];
10343 test_movable![ffi::MemberPublicMoveDeletedCopy];
10344 test_call_a![ffi::MemberPublicMoveDeletedCopy];
10345
10346 test_constructible![ffi::MemberPublicDeletedMove];
10347 test_make_unique![ffi::MemberPublicDeletedMove];
10348 test_call_a![ffi::MemberPublicDeletedMove];
10349
10350 test_call_a![ffi::MemberPublicDeletedDestructor];
10351
10352 test_constructible![ffi::MemberPublicDestructor];
10353 test_make_unique![ffi::MemberPublicDestructor];
10354 test_copyable![ffi::MemberPublicDestructor];
10355 test_call_a![ffi::MemberPublicDestructor];
10356
10357 test_call_a_as![ffi::BaseMemberPublicDeleted, ffi::MemberPublicDeleted];
10358
10359 test_copyable![ffi::BaseMemberPublicDeletedDefault];
10360 test_movable![ffi::BaseMemberPublicDeletedDefault];
10361 test_call_a_as![ffi::BaseMemberPublicDeletedDefault, ffi::MemberPublicDeletedDefault];
10362
10363 test_constructible![ffi::BaseMemberPublicDeletedCopy];
10364 test_make_unique![ffi::BaseMemberPublicDeletedCopy];
10365 test_call_a_as![ffi::BaseMemberPublicDeletedCopy, ffi::MemberPublicDeletedCopy];
10366
10367 test_call_a_as![ffi::BaseMemberPublicDeletedCopyNoDefault, ffi::MemberPublicDeletedCopyNoDefault];
10368
10369 test_constructible![ffi::BaseMemberPublicMoveDeletedCopy];
10370 test_make_unique![ffi::BaseMemberPublicMoveDeletedCopy];
10371 test_movable![ffi::BaseMemberPublicMoveDeletedCopy];
10372 test_call_a_as![ffi::BaseMemberPublicMoveDeletedCopy, ffi::MemberPublicMoveDeletedCopy];
10373
10374 test_constructible![ffi::BaseMemberPublicDeletedMove];
10375 test_make_unique![ffi::BaseMemberPublicDeletedMove];
10376 test_call_a_as![ffi::BaseMemberPublicDeletedMove, ffi::MemberPublicDeletedMove];
10377
10378 test_call_a_as![ffi::BaseMemberPublicDeletedDestructor, ffi::MemberPublicDeletedDestructor];
10379
10380 test_constructible![ffi::BaseMemberPublicDestructor];
10381 test_make_unique![ffi::BaseMemberPublicDestructor];
10382 test_copyable![ffi::BaseMemberPublicDestructor];
10383 test_call_a_as![ffi::BaseMemberPublicDestructor, ffi::MemberPublicDestructor];
10384
10385 test_call_a_as![ffi::BaseProtectedDeleted, ffi::ProtectedDeleted];
10386
10387 test_copyable![ffi::BaseProtectedDeletedDefault];
10388 test_movable![ffi::BaseProtectedDeletedDefault];
10389 test_call_a_as![ffi::BaseProtectedDeletedDefault, ffi::ProtectedDeletedDefault];
10390
10391 test_constructible![ffi::BaseProtectedDeletedCopy];
10392 test_make_unique![ffi::BaseProtectedDeletedCopy];
10393 test_call_a_as![ffi::BaseProtectedDeletedCopy, ffi::ProtectedDeletedCopy];
10394
10395 test_call_a_as![ffi::BaseProtectedDeletedCopyNoDefault, ffi::ProtectedDeletedCopyNoDefault];
10396
10397 test_constructible![ffi::BaseProtectedMoveDeletedCopy];
10398 test_make_unique![ffi::BaseProtectedMoveDeletedCopy];
10399 test_movable![ffi::BaseProtectedMoveDeletedCopy];
10400 test_call_a_as![ffi::BaseProtectedMoveDeletedCopy, ffi::ProtectedMoveDeletedCopy];
10401
10402 test_constructible![ffi::BaseProtectedDeletedMove];
10403 test_make_unique![ffi::BaseProtectedDeletedMove];
10404 test_call_a_as![ffi::BaseProtectedDeletedMove, ffi::ProtectedDeletedMove];
10405
10406 test_call_a_as![ffi::BaseProtectedDeletedDestructor, ffi::ProtectedDeletedDestructor];
10407
10408 test_constructible![ffi::BaseProtectedDestructor];
10409 test_make_unique![ffi::BaseProtectedDestructor];
10410 test_copyable![ffi::BaseProtectedDestructor];
10411 test_call_a_as![ffi::BaseProtectedDestructor, ffi::ProtectedDestructor];
10412
10413 test_call_a![ffi::MemberProtectedDeleted];
10414
10415 test_copyable![ffi::MemberProtectedDeletedDefault];
10416 test_movable![ffi::MemberProtectedDeletedDefault];
10417 test_call_a![ffi::MemberProtectedDeletedDefault];
10418
10419 test_constructible![ffi::MemberProtectedDeletedCopy];
10420 test_make_unique![ffi::MemberProtectedDeletedCopy];
10421 test_call_a![ffi::MemberProtectedDeletedCopy];
10422
10423 test_call_a![ffi::MemberProtectedDeletedCopyNoDefault];
10424
10425 test_constructible![ffi::MemberProtectedMoveDeletedCopy];
10426 test_make_unique![ffi::MemberProtectedMoveDeletedCopy];
10427 test_call_a![ffi::MemberProtectedMoveDeletedCopy];
10428
10429 test_constructible![ffi::MemberProtectedDeletedMove];
10430 test_make_unique![ffi::MemberProtectedDeletedMove];
10431 test_call_a![ffi::MemberProtectedDeletedMove];
10432
10433 test_call_a![ffi::MemberProtectedDeletedDestructor];
10434
10435 test_call_a![ffi::MemberProtectedDestructor];
10436
10437 test_call_a_as![ffi::BaseMemberProtectedDeleted, ffi::MemberProtectedDeleted];
10438
10439 test_copyable![ffi::BaseMemberProtectedDeletedDefault];
10440 test_movable![ffi::BaseMemberProtectedDeletedDefault];
10441 test_call_a_as![ffi::BaseMemberProtectedDeletedDefault, ffi::MemberProtectedDeletedDefault];
10442
10443 test_constructible![ffi::BaseMemberProtectedDeletedCopy];
10444 test_make_unique![ffi::BaseMemberProtectedDeletedCopy];
10445 test_call_a_as![ffi::BaseMemberProtectedDeletedCopy, ffi::MemberProtectedDeletedCopy];
10446
10447 test_call_a_as![ffi::BaseMemberProtectedDeletedCopyNoDefault, ffi::MemberProtectedDeletedCopyNoDefault];
10448
10449 test_constructible![ffi::BaseMemberProtectedMoveDeletedCopy];
10450 test_make_unique![ffi::BaseMemberProtectedMoveDeletedCopy];
10451 test_call_a_as![ffi::BaseMemberProtectedMoveDeletedCopy, ffi::MemberProtectedMoveDeletedCopy];
10452
10453 test_constructible![ffi::BaseMemberProtectedDeletedMove];
10454 test_make_unique![ffi::BaseMemberProtectedDeletedMove];
10455 test_call_a_as![ffi::BaseMemberProtectedDeletedMove, ffi::MemberProtectedDeletedMove];
10456
10457 test_call_a_as![ffi::BaseMemberProtectedDeletedDestructor, ffi::MemberProtectedDeletedDestructor];
10458
10459 test_call_a_as![ffi::BaseMemberProtectedDestructor, ffi::MemberProtectedDestructor];
10460
10461 test_call_a_as![ffi::BasePrivateDeleted, ffi::PrivateDeleted];
10462
10463 test_copyable![ffi::BasePrivateDeletedDefault];
10464 test_movable![ffi::BasePrivateDeletedDefault];
10465 test_call_a_as![ffi::BasePrivateDeletedDefault, ffi::PrivateDeletedDefault];
10466
10467 test_constructible![ffi::BasePrivateDeletedCopy];
10468 test_make_unique![ffi::BasePrivateDeletedCopy];
10469 test_call_a_as![ffi::BasePrivateDeletedCopy, ffi::PrivateDeletedCopy];
10470
10471 test_call_a_as![ffi::BasePrivateDeletedCopyNoDefault, ffi::PrivateDeletedCopyNoDefault];
10472
10473 test_constructible![ffi::BasePrivateMoveDeletedCopy];
10474 test_make_unique![ffi::BasePrivateMoveDeletedCopy];
10475 test_call_a_as![ffi::BasePrivateMoveDeletedCopy, ffi::PrivateMoveDeletedCopy];
10476
10477 test_constructible![ffi::BasePrivateDeletedMove];
10478 test_make_unique![ffi::BasePrivateDeletedMove];
10479 test_call_a_as![ffi::BasePrivateDeletedMove, ffi::PrivateDeletedMove];
10480
10481 test_call_a_as![ffi::BasePrivateDeletedDestructor, ffi::PrivateDeletedDestructor];
10482
10483 test_call_a_as![ffi::BasePrivateDestructor, ffi::PrivateDestructor];
10484
10485 test_call_a![ffi::MemberPrivateDeleted];
10486
10487 test_copyable![ffi::MemberPrivateDeletedDefault];
10488 test_movable![ffi::MemberPrivateDeletedDefault];
10489 test_call_a![ffi::MemberPrivateDeletedDefault];
10490
10491 test_constructible![ffi::MemberPrivateDeletedCopy];
10492 test_make_unique![ffi::MemberPrivateDeletedCopy];
10493 test_call_a![ffi::MemberPrivateDeletedCopy];
10494
10495 test_call_a![ffi::MemberPrivateDeletedCopyNoDefault];
10496
10497 test_constructible![ffi::MemberPrivateMoveDeletedCopy];
10498 test_make_unique![ffi::MemberPrivateMoveDeletedCopy];
10499 test_call_a![ffi::MemberPrivateMoveDeletedCopy];
10500
10501 test_constructible![ffi::MemberPrivateDeletedMove];
10502 test_make_unique![ffi::MemberPrivateDeletedMove];
10503 test_call_a![ffi::MemberPrivateDeletedMove];
10504
10505 test_call_a![ffi::MemberPrivateDeletedDestructor];
10506
10507 test_call_a![ffi::MemberPrivateDestructor];
10508
10509 test_call_a_as![ffi::BaseMemberPrivateDeleted, ffi::MemberPrivateDeleted];
10510
10511 test_copyable![ffi::BaseMemberPrivateDeletedDefault];
10512 test_movable![ffi::BaseMemberPrivateDeletedDefault];
10513 test_call_a_as![ffi::BaseMemberPrivateDeletedDefault, ffi::MemberPrivateDeletedDefault];
10514
10515 test_constructible![ffi::BaseMemberPrivateDeletedCopy];
10516 test_make_unique![ffi::BaseMemberPrivateDeletedCopy];
10517 test_call_a_as![ffi::BaseMemberPrivateDeletedCopy, ffi::MemberPrivateDeletedCopy];
10518
10519 test_call_a_as![ffi::BaseMemberPrivateDeletedCopyNoDefault, ffi::MemberPrivateDeletedCopyNoDefault];
10520
10521 test_constructible![ffi::BaseMemberPrivateMoveDeletedCopy];
10522 test_make_unique![ffi::BaseMemberPrivateMoveDeletedCopy];
10523 test_call_a_as![ffi::BaseMemberPrivateMoveDeletedCopy, ffi::MemberPrivateMoveDeletedCopy];
10524
10525 test_constructible![ffi::BaseMemberPrivateDeletedMove];
10526 test_make_unique![ffi::BaseMemberPrivateDeletedMove];
10527 test_call_a_as![ffi::BaseMemberPrivateDeletedMove, ffi::MemberPrivateDeletedMove];
10528
10529 test_call_a_as![ffi::BaseMemberPrivateDeletedDestructor, ffi::MemberPrivateDeletedDestructor];
10530
10531 test_call_a_as![ffi::BaseMemberPrivateDestructor, ffi::MemberPrivateDestructor];
10532 };
10533 run_test(
10534 cxx,
10535 hdr,
10536 rs,
10537 &[
10538 "AllImplicitlyDefaulted",
10539 "PublicDeleted",
10540 "PublicDeletedDefault",
10541 "PublicDeletedCopy",
10542 "PublicDeletedCopyNoDefault",
10543 "PublicMoveDeletedCopy",
10544 "PublicDeletedMove",
10545 "PublicDeletedDestructor",
10546 "PublicDestructor",
10547 "ProtectedDeleted",
10548 "ProtectedDeletedDefault",
10549 "ProtectedDeletedCopy",
10550 "ProtectedDeletedCopyNoDefault",
10551 "ProtectedMoveDeletedCopy",
10552 "ProtectedDeletedMove",
10553 "ProtectedDeletedDestructor",
10554 "ProtectedDestructor",
10555 "PrivateDeleted",
10556 "PrivateDeletedDefault",
10557 "PrivateDeletedCopy",
10558 "PrivateDeletedCopyNoDefault",
10559 "PrivateMoveDeletedCopy",
10560 "PrivateDeletedMove",
10561 "PrivateDeletedDestructor",
10562 "PrivateDestructor",
10563 "NonConstCopy",
10564 "TwoCopy",
10565 "MemberPointerDeleted",
10566 "MemberConstPointerDeleted",
10567 // TODO: Handle top-level const on C++ members correctly.
10568 //"MemberConst",
10569 "MemberReferenceDeleted",
10570 "MemberConstReferenceDeleted",
10571 "MemberReference",
10572 "MemberConstReference",
10573 "MemberRvalueReferenceDeleted",
10574 "MemberRvalueReference",
10575 "BasePublicDeleted",
10576 "BasePublicDeletedDefault",
10577 "BasePublicDeletedCopy",
10578 "BasePublicDeletedCopyNoDefault",
10579 "BasePublicMoveDeletedCopy",
10580 "BasePublicDeletedMove",
10581 "BasePublicDeletedDestructor",
10582 "BasePublicDestructor",
10583 "MemberPublicDeleted",
10584 "MemberPublicDeletedDefault",
10585 "MemberPublicDeletedCopy",
10586 "MemberPublicDeletedCopyNoDefault",
10587 "MemberPublicMoveDeletedCopy",
10588 "MemberPublicDeletedMove",
10589 "MemberPublicDeletedDestructor",
10590 "MemberPublicDestructor",
10591 "BaseMemberPublicDeleted",
10592 "BaseMemberPublicDeletedDefault",
10593 "BaseMemberPublicDeletedCopy",
10594 "BaseMemberPublicDeletedCopyNoDefault",
10595 "BaseMemberPublicMoveDeletedCopy",
10596 "BaseMemberPublicDeletedMove",
10597 "BaseMemberPublicDeletedDestructor",
10598 "BaseMemberPublicDestructor",
10599 "BaseProtectedDeleted",
10600 "BaseProtectedDeletedDefault",
10601 "BaseProtectedDeletedCopy",
10602 "BaseProtectedDeletedCopyNoDefault",
10603 "BaseProtectedMoveDeletedCopy",
10604 "BaseProtectedDeletedMove",
10605 "BaseProtectedDeletedDestructor",
10606 "BaseProtectedDestructor",
10607 "MemberProtectedDeleted",
10608 "MemberProtectedDeletedDefault",
10609 "MemberProtectedDeletedCopy",
10610 "MemberProtectedDeletedCopyNoDefault",
10611 "MemberProtectedMoveDeletedCopy",
10612 "MemberProtectedDeletedMove",
10613 "MemberProtectedDeletedDestructor",
10614 "MemberProtectedDestructor",
10615 "BaseMemberProtectedDeleted",
10616 "BaseMemberProtectedDeletedDefault",
10617 "BaseMemberProtectedDeletedCopy",
10618 "BaseMemberProtectedDeletedCopyNoDefault",
10619 "BaseMemberProtectedMoveDeletedCopy",
10620 "BaseMemberProtectedDeletedMove",
10621 "BaseMemberProtectedDeletedDestructor",
10622 "BaseMemberProtectedDestructor",
10623 "BasePrivateDeleted",
10624 "BasePrivateDeletedDefault",
10625 "BasePrivateDeletedCopy",
10626 "BasePrivateDeletedCopyNoDefault",
10627 "BasePrivateMoveDeletedCopy",
10628 "BasePrivateDeletedMove",
10629 "BasePrivateDeletedDestructor",
10630 "BasePrivateDestructor",
10631 "MemberPrivateDeleted",
10632 "MemberPrivateDeletedDefault",
10633 "MemberPrivateDeletedCopy",
10634 "MemberPrivateDeletedCopyNoDefault",
10635 "MemberPrivateMoveDeletedCopy",
10636 "MemberPrivateDeletedMove",
10637 "MemberPrivateDeletedDestructor",
10638 "MemberPrivateDestructor",
10639 "BaseMemberPrivateDeleted",
10640 "BaseMemberPrivateDeletedDefault",
10641 "BaseMemberPrivateDeletedCopy",
10642 "BaseMemberPrivateDeletedCopyNoDefault",
10643 "BaseMemberPrivateMoveDeletedCopy",
10644 "BaseMemberPrivateDeletedMove",
10645 "BaseMemberPrivateDeletedDestructor",
10646 "BaseMemberPrivateDestructor",
10647 ],
10648 &[],
10649 );
10650}
10651
10652#[test]
10653/// Test that destructors hidden in various places are correctly called.
10654///
10655/// Some types are excluded because we know they behave poorly due to
10656/// https://github.com/google/autocxx/issues/829.
10657fn test_tricky_destructors() {
10658 let cxx = "";
10659 let hdr = indoc! {"
10660 #include <stdio.h>
10661 #include <stdlib.h>
10662 // A simple type to let Rust verify the destructor is run.
10663 struct DestructorFlag {
10664 DestructorFlag() = default;
10665 DestructorFlag(const DestructorFlag&) = default;
10666 DestructorFlag(DestructorFlag&&) = default;
10667
10668 ~DestructorFlag() {
10669 if (!flag) return;
10670 if (*flag) {
10671 fprintf(stderr, \"DestructorFlag is already set\\n\");
10672 abort();
10673 }
10674 *flag = true;
10675 // Note we deliberately do NOT clear the value of `flag`, to catch Rust calling
10676 // this destructor twice.
10677 }
10678
10679 bool *flag = nullptr;
10680 };
10681
10682 struct ImplicitlyDefaulted {
10683 DestructorFlag flag;
10684
10685 void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
10686 };
10687 struct ExplicitlyDefaulted {
10688 ExplicitlyDefaulted() = default;
10689 ~ExplicitlyDefaulted() = default;
10690
10691 DestructorFlag flag;
10692
10693 void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
10694 };
10695 struct Explicit {
10696 Explicit() = default;
10697 ~Explicit() {}
10698
10699 DestructorFlag flag;
10700
10701 void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
10702 };
10703
10704 struct BaseImplicitlyDefaulted : public ImplicitlyDefaulted {
10705 void set_flag(bool *flag_pointer) { ImplicitlyDefaulted::set_flag(flag_pointer); }
10706 };
10707 struct BaseExplicitlyDefaulted : public ExplicitlyDefaulted {
10708 void set_flag(bool *flag_pointer) { ExplicitlyDefaulted::set_flag(flag_pointer); }
10709 };
10710 struct BaseExplicit : public Explicit {
10711 void set_flag(bool *flag_pointer) { Explicit::set_flag(flag_pointer); }
10712 };
10713
10714 struct MemberImplicitlyDefaulted {
10715 ImplicitlyDefaulted member;
10716
10717 void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
10718 };
10719 struct MemberExplicitlyDefaulted {
10720 ExplicitlyDefaulted member;
10721
10722 void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
10723 };
10724 struct MemberExplicit {
10725 Explicit member;
10726
10727 void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
10728 };
10729
10730 struct BaseMemberImplicitlyDefaulted : public MemberImplicitlyDefaulted {
10731 void set_flag(bool *flag_pointer) { MemberImplicitlyDefaulted::set_flag(flag_pointer); }
10732 };
10733 struct BaseMemberExplicitlyDefaulted : public MemberExplicitlyDefaulted {
10734 void set_flag(bool *flag_pointer) { MemberExplicitlyDefaulted::set_flag(flag_pointer); }
10735 };
10736 struct BaseMemberExplicit : public MemberExplicit {
10737 void set_flag(bool *flag_pointer) { MemberExplicit::set_flag(flag_pointer); }
10738 };
10739 "};
10740 let rs = quote! {
10741 macro_rules! test_type {
10742 [$t:ty] => {
10743 let mut unique_t = <$t>::new().within_unique_ptr();
10744 let mut destructor_flag = false;
10745 unsafe {
10746 unique_t.pin_mut().set_flag(&mut destructor_flag);
10747 }
10748 std::mem::drop(unique_t);
10749 assert!(destructor_flag, "Destructor did not run with make_unique for {}", quote::quote!{$t});
10750
10751 moveit! {
10752 let mut moveit_t = <$t>::new();
10753 }
10754 let mut destructor_flag = false;
10755 unsafe {
10756 moveit_t.as_mut().set_flag(&mut destructor_flag);
10757 }
10758 std::mem::drop(moveit_t);
10759 assert!(destructor_flag, "Destructor did not run with moveit for {}", quote::quote!{$t});
10760 }
10761 }
10762
10763 test_type![ffi::ImplicitlyDefaulted];
10764 test_type![ffi::ExplicitlyDefaulted];
10765 test_type![ffi::Explicit];
10766 test_type![ffi::BaseImplicitlyDefaulted];
10767 test_type![ffi::BaseExplicitlyDefaulted];
10768 test_type![ffi::BaseExplicit];
10769 test_type![ffi::MemberImplicitlyDefaulted];
10770 test_type![ffi::MemberExplicitlyDefaulted];
10771 test_type![ffi::MemberExplicit];
10772 test_type![ffi::BaseMemberImplicitlyDefaulted];
10773 test_type![ffi::BaseMemberExplicitlyDefaulted];
10774 test_type![ffi::BaseMemberExplicit];
10775 };
10776 run_test(
10777 cxx,
10778 hdr,
10779 rs,
10780 &[
10781 "DestructorFlag",
10782 "ImplicitlyDefaulted",
10783 "ExplicitlyDefaulted",
10784 "Explicit",
10785 "BaseImplicitlyDefaulted",
10786 "BaseExplicitlyDefaulted",
10787 "BaseExplicit",
10788 "MemberImplicitlyDefaulted",
10789 "MemberExplicitlyDefaulted",
10790 "MemberExplicit",
10791 "BaseMemberImplicitlyDefaulted",
10792 "BaseMemberExplicitlyDefaulted",
10793 "BaseMemberExplicit",
10794 ],
10795 &[],
10796 );
10797}
10798
10799#[test]
10800fn test_concretize() {
10801 let hdr = indoc! {"
10802 #include <string>
10803 template<typename CONTENTS>
10804 class Container {
10805 private:
10806 CONTENTS* contents;
10807 };
10808 struct B {
10809 std::string a;
10810 };
10811 "};
10812 run_test_ex(
10813 "",
10814 hdr,
10815 quote! {},
10816 quote! {
10817 concrete!("Container<B>", ContainerOfB)
10818 generate!("B")
10819 },
10820 None,
10821 None,
10822 Some(quote! {
10823 struct HasAField {
10824 contents: ffi::ContainerOfB
10825 }
10826 }),
10827 );
10828}
10829
10830#[test]
10831fn test_doc_comments_survive() {
10832 let hdr = indoc! {"
10833 #include <cstdint>
10834 /// Struct line A
10835 /// Struct line B
10836 struct A { int b; };
10837
10838 /// POD struct line A
10839 /// POD struct line B
10840 struct B {
10841 /// Field line A
10842 /// Field line B
10843 uint32_t b;
10844
10845 /// Method line A
10846 /// Method line B
10847 void foo() {}
10848 };
10849
10850 /// Enum line A
10851 /// Enum line B
10852 enum C {
10853 /// Variant line A
10854 /// Variant line B
10855 VARIANT,
10856 };
10857
10858 /// Function line A
10859 /// Function line B
10860 inline void D() {}
10861 "};
10862
10863 let expected_messages = [
10864 "Struct",
10865 "POD struct",
10866 "Field",
10867 "Method",
10868 "Enum",
10869 "Variant",
10870 "Function",
10871 ]
10872 .into_iter()
10873 .flat_map(|l| [format!("{} line A", l), format!("{} line B", l)])
10874 .collect_vec();
10875
10876 run_test_ex(
10877 "",
10878 hdr,
10879 quote! {},
10880 directives_from_lists(&["A", "C", "D"], &["B"], None),
10881 None,
10882 Some(make_string_finder(expected_messages)),
10883 None,
10884 );
10885}
10886
10887#[test]
10888fn optional_param_in_copy_constructor() {
10889 let hdr = indoc! {"
10890 struct A {
10891 A(const A &other, bool optional_arg = false);
10892 };
10893 "};
10894 run_test("", hdr, quote! {}, &["A"], &[]);
10895}
10896
10897#[test]
10898fn param_in_copy_constructor() {
10899 let hdr = indoc! {"
10900 struct A {
10901 A(const A &other, bool arg);
10902 };
10903 "};
10904 run_test("", hdr, quote! {}, &["A"], &[]);
10905}
10906
10907#[test]
10908fn test_variadic() {
10909 let hdr = indoc! {"
10910 class SomeClass{
10911 public:
10912 inline void foo(int, ... ) {}
10913 };
10914 "};
10915 run_test("", hdr, quote! {}, &["SomeClass"], &[]);
10916}
10917
10918#[test]
10919fn test_typedef_to_enum() {
10920 let hdr = indoc! {"
10921 enum b {};
10922 class c {
10923 public:
10924 typedef b d;
10925 d e();
10926 };
10927 "};
10928 run_test_ex(
10929 "",
10930 hdr,
10931 quote! {},
10932 quote! { generate_all!() },
10933 None,
10934 None,
10935 None,
10936 );
10937}
10938
10939#[test]
10940fn test_typedef_to_ns_enum() {
10941 let hdr = indoc! {"
10942 namespace a {
10943 enum b {};
10944 class c {
10945 public:
10946 typedef b d;
10947 d e();
10948 };
10949 } // namespace
10950 "};
10951 run_test_ex(
10952 "",
10953 hdr,
10954 quote! {},
10955 quote! { generate_all!() },
10956 None,
10957 None,
10958 None,
10959 );
10960}
10961
10962#[test]
10963fn test_typedef_unsupported_type_pub() {
10964 let hdr = indoc! {"
10965 #include <set>
10966 namespace NS{
10967 class cls{
10968 public:
10969 typedef std::set<int> InnerType;
10970 };
10971 }
10972 "};
10973
10974 run_test_ex(
10975 "",
10976 hdr,
10977 quote! {},
10978 quote! { generate_ns!("NS") },
10979 None,
10980 None,
10981 None,
10982 );
10983}
10984
10985#[test]
10986fn test_typedef_unsupported_type_pri() {
10987 let hdr = indoc! {"
10988 #include <set>
10989 namespace NS{
10990 class cls{
10991 private:
10992 typedef std::set<int> InnerType;
10993 };
10994 }
10995 "};
10996
10997 run_test_ex(
10998 "",
10999 hdr,
11000 quote! {},
11001 quote! { generate_ns!("NS") },
11002 None,
11003 None,
11004 None,
11005 );
11006}
11007
11008#[test]
11009fn test_array_trouble1() {
11010 let hdr = indoc! {"
11011 namespace a {
11012 template <typename b> struct array {
11013 typedef b c;
11014 typedef c d;
11015 };
11016 } // namespace a
11017 "};
11018 run_test_ex(
11019 "",
11020 hdr,
11021 quote! {},
11022 quote! { generate_all!() },
11023 None,
11024 None,
11025 None,
11026 );
11027}
11028
11029#[test]
11030fn test_array_trouble2() {
11031 let hdr = indoc! {"
11032 template <typename b> struct array {
11033 typedef b c;
11034 typedef c d;
11035 };
11036 "};
11037 run_test("", hdr, quote! {}, &["array_d"], &[]);
11038}
11039
11040#[test]
11041fn test_issue_1087a() {
11042 let hdr = indoc! {"
11043 template <typename _CharT> class a {
11044 _CharT b;
11045 };
11046 "};
11047 run_test_ex(
11048 "",
11049 hdr,
11050 quote! {},
11051 quote! { generate_all!() },
11052 None,
11053 None,
11054 None,
11055 );
11056}
11057
11058#[test]
11059fn test_issue_1087b() {
11060 let hdr = indoc! {"
11061 template <typename _CharT> class a {
11062 typedef _CharT b;
11063 b c;
11064 };
11065 "};
11066 run_test_ex(
11067 "",
11068 hdr,
11069 quote! {},
11070 quote! { generate_all!() },
11071 None,
11072 None,
11073 None,
11074 );
11075}
11076
11077#[test]
11078fn test_issue_1087c() {
11079 let hdr = indoc! {"
11080 namespace {
11081 namespace {
11082 template <typename _CharT> class a {
11083 typedef _CharT b;
11084 b c;
11085 };
11086 }
11087 }
11088 "};
11089 run_test_ex(
11090 "",
11091 hdr,
11092 quote! {},
11093 quote! { generate_all!() },
11094 None,
11095 None,
11096 None,
11097 );
11098}
11099
11100#[test]
11101fn test_issue_1089() {
11102 let hdr = indoc! {"
11103 namespace a {
11104 template <typename c, c> struct d;
11105 template <bool, typename, typename> struct ab;
11106 inline namespace {
11107 namespace ac {
11108 template <typename, template <typename> class, typename> struct bh;
11109 template <template <typename> class ad, typename... bi>
11110 using bj = bh<void, ad, bi...>;
11111 template <typename ad> using bk = typename ad::b;
11112 template <typename> struct bm;
11113 } // namespace ac
11114 template <typename ad>
11115 struct b : ab<ac::bj<ac::bk, ad>::e, ac::bm<ad>, d<bool, ad ::e>>::bg {};
11116 } // namespace
11117 } // namespace a
11118 "};
11119 run_test_ex(
11120 "",
11121 hdr,
11122 quote! {},
11123 quote! { generate_all!() },
11124 None,
11125 None,
11126 None,
11127 );
11128}
11129
11130#[test]
11131fn test_pass_rust_str_and_return_struct() {
11132 let cxx = indoc! {"
11133 A take_str_return_struct(rust::Str) {
11134 A a;
11135 return a;
11136 }
11137 "};
11138 let hdr = indoc! {"
11139 #include <cxx.h>
11140 struct A {};
11141 A take_str_return_struct(rust::Str);
11142 "};
11143 let rs = quote! {
11144 ffi::take_str_return_struct("hi");
11145 };
11146 run_test(cxx, hdr, rs, &["take_str_return_struct"], &[]);
11147}
11148
11149#[test]
11150fn test_issue_1065a() {
11151 let hdr = indoc! {"
11152 #include <memory>
11153 #include <vector>
11154
11155 template <typename at> class au {
11156 std::unique_ptr<at> aw;
11157 };
11158 class bb;
11159 using bc = au<bb>;
11160 class RenderFrameHost {
11161 public:
11162 virtual std::vector<bc> &bd() = 0;
11163 virtual ~RenderFrameHost() {}
11164 };
11165 "};
11166 let rs = quote! {};
11167 run_test("", hdr, rs, &["RenderFrameHost"], &[]);
11168}
11169
11170#[test]
11171fn test_issue_1065b() {
11172 let hdr = indoc! {"
11173 #include <memory>
11174 #include <vector>
11175
11176 class bb;
11177 using bc = std::unique_ptr<bb>;
11178 class RenderFrameHost {
11179 public:
11180 virtual std::vector<bc> &bd() = 0;
11181 virtual ~RenderFrameHost() {}
11182 };
11183 "};
11184 let rs = quote! {};
11185 run_test("", hdr, rs, &["RenderFrameHost"], &[]);
11186}
11187
11188// Yet to test:
11189// - Ifdef
11190// - Out param pointers
11191// - ExcludeUtilities
11192// - Struct fields which are typedefs
11193// Negative tests:
11194// - Private methods
11195// - Private fields