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