chromium/tools/clang/rewrite_raw_ptr_fields/tests/general-ref-tests-original.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>

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;
    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;
  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;
  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;
    int& in;
    // Expected rewrite: const raw_ref<int> out;
    int& out;
    // Expected rewrite:
    // report_lists[]{{raw_ref(a), raw_ref(b)}, {raw_ref(a), raw_ref(b)}};
  } report_lists[]{{a, b}, {a, 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 {
      int& i;
    } member;
  };

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

  // Expected rewrite:  A obj{.member = {raw_ref(a)}};
  A obj2{.member = {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;
    int& member;
    // Expected rewrite: st{raw_ref(a)};
  } st{a};

  struct Temp {
    Temp(int& ref) : member(ref) {}
    // Expected rewrite: const raw_ref<int> member;
    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 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;
    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 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 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]; }

  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;
  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];
};