1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5struct A {
6  A&& Pass();
7};
8
9struct B {
10  B& Pass();
11};
12
13struct C {
14  A a;
15};
16
17struct D {
18  D&& NotPass();
19};
20
21struct E {
22  E() : a(new A) {}
23  ~E() { delete a; }
24  A* a;
25};
26
27struct F {
28  explicit F(A&&);
29  F&& Pass();
30};
31
32void Test() {
33  // Pass that returns rvalue reference should use std::move.
34  A a1;
35  A a2 = std::move(a1);
36
37  // Pass that doesn't return a rvalue reference should not be rewritten.
38  B b1;
39  B b2 = b1.Pass();
40
41  // std::move() needs to wrap the entire expression when passing a member.
42  C c;
43  A a3 = std::move(c.a);
44
45  // Don't rewrite things that return rvalue references that aren't named Pass.
46  D d1;
47  D d2 = d1.NotPass();
48
49  // Pass via a pointer type should dereference the pointer first.
50  E e;
51  A a4 = std::move(*e.a);
52
53  // Nested Pass() is handled correctly.
54  A a5;
55  F f = std::move(F(std::move(a5)));
56
57  // Chained Pass is handled correctly.
58  A a6;
59  A a7 = std::move(std::move(a6));
60}
61