aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp23/explicit-obj-by-value3.C
blob: e6aff0190fbc51ba12306d3fa3f06b16c3203533 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// P0847R7
// { dg-do run { target c++23 } }

// correct constructor selection when initializing a by value xobj parameter

// see explicit-obj-by-value1.C for details on this test

using uintptr_t = __UINTPTR_TYPE__;
inline constexpr uintptr_t magic = 42;
inline constexpr uintptr_t copy_magic = 5;
inline constexpr uintptr_t move_magic = 10;

struct S {
  uintptr_t _v;
  explicit S(uintptr_t v) : _v(v) {}
  S(S const& other) : _v(other._v + copy_magic) {}
  S(S&& other) : _v(other._v + move_magic) {}
  uintptr_t f(this S self) {
    return self._v;
  }
};

int main() 
{
  S s0{magic};
  S s1{magic};
  // prevent (absurdly improbable (^2)) bogus results
  // it's virtually impossible for both to have a bogus result,
  // but we can guarantee correct results from both easily, so why not?
  S& s_copy_from = magic + copy_magic != (uintptr_t)(&s0) ? s0 : s1;
  S& s_move_from = magic + move_magic != (uintptr_t)(&s0) ? s0 : s1;
  uintptr_t const copy_ret = static_cast<S const&>(s_copy_from).f();
  uintptr_t const move_ret = static_cast<S&&>(s_move_from).f();
  // we test specifically for reinterpretation in other
  // by value tests, it's unnecessary to do it again here
  if (copy_ret != magic + copy_magic)
    __builtin_abort ();
  if (move_ret != magic + move_magic)
    __builtin_abort ();
}