chromium/tools/clang/rewrite_raw_ptr_fields/tests/general-ref-tests-expected.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include "base/memory/raw_ref.h"

struct MySubStruct {
  MySubStruct(const int& num);
  int member;
  virtual int get_member() const { return member; }
  virtual ~MySubStruct() = default;

  struct inner_s {
    inner_s(const inner_s&);
    // Expected rewrite: const raw_ref<int> inner_int;
    const raw_ref<int> inner_int;
  };
};

// This was added due to a bug in the matcher that was doing erroneous rewrites
// here. No rewrite expected.
MySubStruct::inner_s::inner_s(const inner_s&) = default;

struct MyStruct {
  MyStruct(MySubStruct& s) : ref(s) {}

  // No rewrite expected for `other.ref` since `ref` itself with become a
  // raw_ref.
  MyStruct(const MyStruct& other) : ref(other.ref) {}

  const MySubStruct& get() const;
  // Expected rewrite: const raw_ref<MySubStruct> ref;
  const raw_ref<MySubStruct> ref;
};

template <class T>
struct MyTemplatedStruct {
  MyTemplatedStruct(T& t) : ref(t) {}

  // No rewrite expected for `other.ref` since `ref` itself with become a
  // raw_ref.
  MyTemplatedStruct(const MyTemplatedStruct& other) : ref(other.ref) {}

  // Expected rewrite: ref->member
  void setSubmember(int n) { ref->member = n; }

  // Expected rewrite: return *ref;
  T& get() { return *ref; }

  const T& get() const;
  // Expected rewrite: return *ref;
  T get_by_value() const { return *ref; }

  // Expected rewrite: ref->get_member();
  int getInt() { return ref->get_member(); }

  // Expected rewrite: const raw_ref<T> ref;
  const raw_ref<T> ref;
};

template <class T>
void func(T& ref, const T& ref2) {}

int main() {
  MySubStruct sub{1};
  MyStruct s(sub);
  // Expected rewrite: s.ref->member;
  s.ref->member = 11;
  // Expected rewrite: s.ref->get_member();
  s.ref->get_member();

  // Expected rewrite: MyStruct* s2 = new MyStruct(*s.ref);
  MyStruct* s2 = new MyStruct(*s.ref);

  MyTemplatedStruct<MySubStruct> my_template_inst(sub);
  my_template_inst.setSubmember(1234);

  // Expected rewrites:
  // func(*my_template_inst.ref, my_template_inst.get());
  func(*my_template_inst.ref, my_template_inst.get());
  // func(my_template_inst.get(), *my_template_inst.ref);
  func(my_template_inst.get(), *my_template_inst.ref);
  // func(*my_template_inst.ref, *my_template_inst.ref);
  func(*my_template_inst.ref, *my_template_inst.ref);

  // Expected rewrite: MySubStruct* ptr = &*s.ref;
  MySubStruct* ptr = &*s.ref;

  // Expected rewrite:
  //  auto &ref = *s.ref, &ref2 = *s.ref;
  auto &ref = *s.ref, &ref2 = *s.ref;

  int a = 0;
  int b = 0;

  struct {
    // Expected rewrite: const raw_ref<int> in;
    const raw_ref<int> in;
    // Expected rewrite: const raw_ref<int> out;
    const raw_ref<int> out;
    // Expected rewrite:
    // report_lists[]{{raw_ref(a), raw_ref(b)}, {raw_ref(a), raw_ref(b)}};
  } report_lists[]{{raw_ref(a), raw_ref(b)}, {raw_ref(a), raw_ref(b)}};

  // Reference members of nested anonymous structs declared in a
  // function body are rewritten because they can end up on the heap.
  struct A {
    struct {
      const raw_ref<int> i;
    } member;
  };

  // Expected rewrite:  A obj{raw_ref(a)};
  A obj{raw_ref(a)};
  (*obj.member.i)++;

  // Expected rewrite:  A obj{.member = {raw_ref(a)}};
  A obj2{.member = {raw_ref(a)}};
  (*obj2.member.i)++;
  ++(*obj2.member.i);
  (*obj2.member.i)--;
  --(*obj2.member.i);

  // No rewrite expected here for obj2.member.i since A::member::i itself will
  // be rewritten into raw_ref.
  A obj3{obj2.member.i};
  (*obj3.member.i)++;

  static struct {
    // Expected rewrite: const raw_ref<int> member;
    const raw_ref<int> member;
    // Expected rewrite: st{raw_ref(a)};
  } st{raw_ref(a)};

  struct Temp {
    Temp(int& ref) : member(ref) {}
    // Expected rewrite: const raw_ref<int> member;
    const raw_ref<int> member;
  };
  // No need to add raw_ref() around `a` here because the constructor will be
  // called.
  Temp tmp{a};
  (*tmp.member)++;

  struct StringRefObj {
    const raw_ref<const std::string> member;
  };

  // No need to add raw_ref() around "abcde" here because it results in a
  // temporary string object. A manual fix need to be applied.
  StringRefObj r{"abcde"};
  (void)r;
}

struct B {
  struct {
    // Expected rewrite: const raw_ref<int> i;
    const raw_ref<int> i;
  } member;
};

template <typename T>
const T& MyTemplatedStruct<T>::get() const {
  // Expected rewrite: return *ref;
  return *ref;
}

const MySubStruct& MyStruct::get() const {
  // Expected rewrite: return *ref;
  return *ref;
}

struct key_compare {
  bool operator()(const int& a, const int& b) const { return a < b; }
};

struct KeyValueCompare {
  // The key comparison object must outlive this class.
  explicit KeyValueCompare(const key_compare& comp) : comp_(comp) {}

  bool operator()(const int& lhs, const int& rhs) const {
    // Expected rewrite: return (*comp_)(lhs, rhs);
    return (*comp_)(lhs, rhs);
  }

  template <typename T, typename U>
  bool operator()(const T& lhs, const U& rhs) const {
    // Expected rewrite: return (*comp_)(lhs, rhs);
    return (*comp_)(lhs, rhs);
  }

 private:
  const raw_ref<const key_compare> comp_;
};

struct KeyValueCompare2 {
  // The key comparison object must outlive this class.
  explicit KeyValueCompare2(const key_compare& comp) : comp_(comp) {}

  template <typename T, typename U>
  bool operator()(const T& lhs, const U& rhs) const {
    // Expected rewrite: return (*comp_)(lhs, rhs);
    return (*comp_)(lhs, rhs);
  }

 private:
  const raw_ref<const key_compare> comp_;
};

template <typename T>
void doSomething(T& t) {
  (void)t;
}

template <typename T>
struct VectorMemberRef {
  void iterate() {
    for (T& t : *v) {
      doSomething(t);
    }
  }

  T get_first() { return (*v)[0]; }

  const raw_ref<std::vector<T>> v;
};

struct MyStruct2 {
  MyStruct2(const MyStruct2& other)
      :  // No rewrite expected for `other.int_ref` since `int_ref` itself with
         // become a raw_ref.
        int_ref(other.int_ref),
        // Expected rewrite: i(*other.int_ref)
        i(*other.int_ref),
        func_ref(other.func_ref),
        ref_to_array_of_ints(other.ref_to_array_of_ints) {}

  // Expected rewrite: const raw_ref<int> int_ref;
  const raw_ref<int> int_ref;
  int i;
  // Function references are not rewritten.
  int (&func_ref)();
  // References to arrays are not rewritten.
  int (&ref_to_array_of_ints)[123];
};