1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file (and other gen-*-test.cc files) tests generation of output for
// --field-filter-file and therefore the expectations file
// (gen-global-scope-expected.txt) needs to be compared against the raw
// output of the rewriter (rather than against the actual edits result). This
// makes the test incompatible with other tests, which require passing
// --apply-edits switch to test_tool.py and so to disable the test it is named
// *-test.cc rather than *-original.cc.
//
// To run the test use tools/clang/rewrite_raw_ptr_fields/tests/run_all_tests.py
// Chromium is built with a warning/error that global and static variables
// may only have trivial destructors. See also:
// https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
// go/totw/110#destruction
//
// If raw_ptr has a non-trivial destructor (e.g. if it is implemented via
// BackupRefPtr) then raw_ptr cannot be used as the type of fields in structs
// that are (recursively/transitively) the type of a global variable:
// struct MyStruct { // Presence of raw_ptr might mean that
// raw_ptr<int> ptr; // <- MyStruct has a non-trivial destructor.
// };
// MyStruct g_struct; // <- Error if MyStruct has a non-trivial destructor.
//
// To account for the constraints described above, the rewriter tool should
// avoid rewriting some of the fields below.
#include "base/containers/span.h"
namespace global_variables_test {
struct MyStruct {
MyStruct(int& r) : ref(r), ref2(r) {}
// Expected to be emitted in automated-fields-to-ignore.txt, because
// of |g_struct| below.
int* ptr;
int& ref;
base::span<int> span_member;
// Verification that *all* fields of a struct are covered (e.g. that the
// |forEach| matcher is used instead of the |has| matcher).
int* ptr2;
int& ref2;
base::span<int> span_member2;
};
int num = 11;
MyStruct g_struct(num);
} // namespace global_variables_test
namespace static_variables_test {
struct MyStruct {
MyStruct(int& r) : ref(r) {}
// Expected to be emitted in automated-fields-to-ignore.txt, because
// of |s_struct| below.
int* ptr;
int& ref;
base::span<int> span_member;
};
void foo() {
static int n = 11;
static MyStruct s_struct(n);
}
} // namespace static_variables_test
namespace nested_struct_test {
struct MyStruct {
MyStruct(int& r) : ref(r) {}
// Expected to be emitted in automated-fields-to-ignore.txt, because
// of |g_outer_struct| below.
int* ptr;
int& ref;
base::span<int> span_member;
};
struct MyOuterStruct {
MyOuterStruct(int& r) : inner_struct(r) {}
MyStruct inner_struct;
};
static int n = 42;
static MyOuterStruct g_outer_struct(n);
} // namespace nested_struct_test
namespace nested_in_array_test {
struct MyStruct {
MyStruct(int& r) : ref(r) {}
// Expected to be emitted in automated-fields-to-ignore.txt, because
// of |g_outer_array| below.
int* ptr;
int& ref;
base::span<int> span_member;
};
static int num = 42;
static MyStruct g_outer_struct[] = {num, num, num};
} // namespace nested_in_array_test
namespace nested_template_test {
template <typename T>
struct MyStruct {
MyStruct(T& r) : ref(r), ref2(r) {}
// Expected to be emitted in automated-fields-to-ignore.txt, because
// of |g_outer_struct| below.
T* ptr;
T* ptr2;
T& ref;
T& ref2;
base::span<int> span_member;
};
struct MyOuterStruct {
MyOuterStruct(int& r) : inner_struct(r) {}
MyStruct<int> inner_struct;
};
static int num = 42;
static MyOuterStruct g_outer_struct(num);
} // namespace nested_template_test
namespace pointer_nesting_test {
struct MyStruct {
// Should not be emitted in automated-fields-to-ignore.txt, because
// |inner_struct| field below is a pointer. (i.e. this is a test that
// |hasNestedFieldDecl| matcher doesn't recurse/traverse over pointers)
int* ptr;
base::span<int> span_member;
};
struct MyOuterStruct {
// Expected to be emitted in automated-fields-to-ignore.txt, because
// of |g_outer_struct| below.
MyStruct* inner_struct;
base::span<int> span_member;
};
static MyOuterStruct g_outer_struct;
} // namespace pointer_nesting_test
|