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
5 struct A {
6 A&& Pass();
7 };
8
9 struct B {
10 B& Pass();
11 };
12
13 struct C {
14 A a;
15 };
16
17 struct D {
18 D&& NotPass();
19 };
20
21 struct E {
EE22 E() : a(new A) {}
~EE23 ~E() { delete a; }
24 A* a;
25 };
26
27 struct F {
28 explicit F(A&&);
29 F&& Pass();
30 };
31
Test()32 void Test() {
33 // Pass that returns rvalue reference should use std::move.
34 A a1;
35 A a2 = a1.Pass();
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 = c.a.Pass();
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 = e.a->Pass();
52
53 // Nested Pass() is handled correctly.
54 A a5;
55 F f = F(a5.Pass()).Pass();
56
57 // Chained Pass is handled (mostly) correctly. The replacement applier dedupes
58 // the insertion of std::move, so the result is not completely correct...
59 // ... but hopefully there's very little code following this broken pattern.
60 A a6;
61 A a7 = a6.Pass().Pass();
62 }
63