1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <memory>
10 
11 // Test arguments destruction order involving unique_ptr<T> with trivial_abi.
12 
13 // ADDITIONAL_COMPILE_FLAGS: -Wno-macro-redefined -D_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
14 
15 // XFAIL: gcc
16 
17 #include <memory>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 
call_something()22 __attribute__((noinline)) void call_something() { asm volatile(""); }
23 
24 struct Base {
25   char* shared_buff;
26   int* cur_idx;
27   const char id;
28 
BaseBase29   explicit Base(char* buf, int* idx, char ch)
30       : shared_buff(buf), cur_idx(idx), id(ch) {}
31   Base(const Base& other) = default;
32   Base& operator=(const Base&) = delete;
~BaseBase33   ~Base() { shared_buff[(*cur_idx)++] = id; }
34 };
35 
36 struct A : Base {
AA37   explicit A(char* buf, int* idx) : Base(buf, idx, 'A') {}
38 };
39 
40 struct B : Base {
BB41   explicit B(char* buf, int* idx) : Base(buf, idx, 'B') {}
42 };
43 
44 struct C : Base {
CC45   explicit C(char* buf, int* idx) : Base(buf, idx, 'C') {}
46 };
47 
func(A,std::unique_ptr<B>,C)48 __attribute__((noinline)) void func(A /*unused*/, std::unique_ptr<B> /*unused*/,
49                                     C /*unused*/) {
50   call_something();
51 }
52 
main(int,char **)53 int main(int, char**) {
54   char shared_buf[3] = {'0', '0', '0'};
55   int cur_idx = 0;
56 
57   func(A(shared_buf, &cur_idx), std::unique_ptr<B>(new B(shared_buf, &cur_idx)),
58        C(shared_buf, &cur_idx));
59 
60 #if defined(TEST_ABI_MICROSOFT)
61   // On Microsoft ABI, the dtor order is always A,B,C (because callee-destroyed)
62   assert(shared_buf[0] == 'A' && shared_buf[1] == 'B' && shared_buf[2] == 'C');
63 #else
64   // With trivial_abi, the std::unique_ptr<B> arg is always destructed first.
65   assert(shared_buf[0] == 'B');
66 #endif
67   return 0;
68 }
69