1 // Copyright 2016 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 #include <type_traits>
6
7 namespace not_blink {
8
function(int x)9 void function(int x) {}
10
11 class Class {
12 public:
method()13 void method() {}
virtualMethod()14 virtual void virtualMethod() {}
15 template <typename T>
methodTemplate(T)16 void methodTemplate(T) {}
17 template <typename T>
staticMethodTemplate(T)18 static void staticMethodTemplate(T) {}
19 };
20
21 template <typename T>
functionTemplate(T x)22 void functionTemplate(T x) {}
23
24 template <typename T = Class>
functionTemplate2()25 void functionTemplate2() {
26 T::staticMethodTemplate(123);
27 }
28
29 template <typename T = Class>
30 class TemplatedClass {
31 public:
anotherMethod()32 void anotherMethod() { T::staticMethodTemplate(123); }
33 };
34
35 } // not_blink
36
37 namespace blink {
38
functionNotMarkedConstexpr(int a)39 bool functionNotMarkedConstexpr(int a) {
40 return a == 4 || a == 10;
41 }
42
43 template <typename T>
templatedFunctionNotMarkedConstexpr(T t)44 bool templatedFunctionNotMarkedConstexpr(T t) {
45 return !!t;
46 }
47
48 int g_globalNumber;
49
50 template <typename T, int number>
F()51 void F() {
52 // These are const but hacker_case so we leave them alone.
53 const int maybe_a_const = sizeof(T);
54 const int is_a_const = number;
55 // These are const expressions so they get a k prefix.
56 const int maybeAConstToo = sizeof(T);
57 const int isAConstToo = number;
58 // These are built from calls to functions which produces inconsistent
59 // results so they should not be considered const to be safe.
60 const bool fromAMethod = functionNotMarkedConstexpr(number);
61 const bool fromATemplatedMethod = templatedFunctionNotMarkedConstexpr(number);
62 // A complex statement of const things is const.
63 const bool complexConst = number || (number + 1);
64 // A complex statement with a non-const thing is not const.
65 const bool complexNotConst = number || (g_globalNumber + 1);
66 // A const built from other consts is a const.
67 const bool constFromAConst = complexConst || number;
68 }
69
70 template <int number, typename... T>
F()71 void F() {
72 // These are const but hacker_case so we leave them alone.
73 const int maybe_a_const = sizeof...(T);
74 const int is_a_const = number;
75 // These are const expressions so they get a k prefix.
76 const int maybeAConstToo = sizeof...(T);
77 const int isAConstToo = number;
78 }
79
80 namespace test_member_in_template {
81
82 template <typename T>
83 class HasAMember {
84 public:
HasAMember()85 HasAMember() {}
HasAMember(const T &)86 HasAMember(const T&) {}
87
usesMember()88 void usesMember() { const int notConst = m_i; }
89 void alsoUsesMember();
90
91 private:
92 int m_i;
93 };
94
95 template <typename T>
alsoUsesMember()96 void HasAMember<T>::alsoUsesMember() {
97 const int notConst = m_i;
98 }
99
100 template <typename T>
basedOnSubType(const HasAMember<T> & t)101 static void basedOnSubType(const HasAMember<T>& t) {
102 const HasAMember<T> problematicNotConst(t);
103 }
104
Run()105 void Run() {
106 HasAMember<int>().usesMember();
107
108 basedOnSubType<int>(HasAMember<int>());
109 enum E { A };
110 basedOnSubType<E>(HasAMember<E>());
111 }
112 }
113
114 namespace test_template_arg_is_function {
115
f(int x)116 void f(int x) {}
117
118 template <typename T, void g(T)>
h(T x)119 void h(T x) {
120 g(x);
121 }
122
test()123 void test() {
124 // f should be rewritten.
125 h<int, f>(0);
126 // Non-Blink should stay the same.
127 h<int, not_blink::function>(1);
128
129 // The int one makes the methods called from F() considered as constexpr, and
130 // can be collapsed to not have template arguments before it reaches the AST.
131 F<int, 10>();
132 // The enum one makes them not constexpr, as it doesn't collapse away the
133 // template stuff as much. This can lead to conflicting decisions about
134 // the names inside F() vs the above instantiation.
135 enum E { A };
136 F<E, 11>();
137 }
138
139 } // namespace test_template_arg_is_function
140
141 namespace test_template_arg_is_method {
142
143 class Class {
144 public:
method()145 void method() {}
146 };
147
148 template <typename T, void (T::*g)()>
h(T && x)149 void h(T&& x) {
150 (x.*g)();
151 }
152
test()153 void test() {
154 // method should be rewritten.
155 h<Class, &Class::method>(Class());
156 // Non-Blink should stay the same.
157 h<not_blink::Class, ¬_blink::Class::method>(not_blink::Class());
158 }
159
160 } // namespace test_template_arg_is_method
161
162 namespace test_template_arg_is_function_template {
163
164 namespace nested {
165 template <typename T>
f(T)166 void f(T) {}
167 }
168
169 template <typename T, void g(T)>
h(T x)170 void h(T x) {
171 g(x);
172 }
173
test()174 void test() {
175 // f should be rewritten.
176 h<int, nested::f>(0);
177 // Non-Blink should stay the same.
178 h<int, not_blink::functionTemplate>(1);
179 }
180
181 } // namespace test_template_arg_is_function_template
182
183 namespace test_template_arg_is_method_template_in_non_member_context {
184
185 struct Class {
186 template <typename T>
fblink::test_template_arg_is_method_template_in_non_member_context::Class187 static void f(T) {}
188 };
189
190 template <typename T, void g(T)>
h(T x)191 void h(T x) {
192 g(x);
193 }
194
test()195 void test() {
196 // f should be rewritten.
197 h<int, Class::f>(0);
198 // Non-Blink should stay the same.
199 h<int, not_blink::Class::staticMethodTemplate>(1);
200 }
201
202 } // test_template_arg_is_method_template_in_non_member_context
203
204 namespace test_inherited_field {
205
206 template <typename T>
207 class BaseClass {
208 public:
209 unsigned long m_size;
210 };
211
212 template <typename T>
213 class DerivedClass : protected BaseClass<T> {
214 private:
215 using Base = BaseClass<T>;
216 // https://crbug.com/640016: Need to rewrite |m_size| into |size_|.
217 using Base::m_size;
method()218 void method() { m_size = 123; }
219 };
220
221 } // namespace test_inherited_field
222
223 namespace test_template_arg_is_method_template_in_member_context {
224
225 struct Class {
226 template <typename T>
fblink::test_template_arg_is_method_template_in_member_context::Class227 static void f(T) {}
228 };
229
230 struct Class2 {
231 template <typename T>
fblink::test_template_arg_is_method_template_in_member_context::Class2232 void f(T x) {
233 // f should be rewritten.
234 Class c;
235 c.f(x);
236 // Non-Blink should stay the same.
237 not_blink::Class c2;
238 c2.method(x);
239 }
240 };
241
242 } // namespace test_template_arg_is_method_template_in_member_context
243
244 namespace test_unnamed_arg {
245
246 template <typename T>
247 class Class {
248 public:
249 // Test for https://crbug.com/598141 - shouldn't rewrite
250 // ...int);
251 // into
252 // ...intdata_size;
253 void f(int);
254 };
255
256 template <typename T>
f(int dataSize)257 void Class<T>::f(int dataSize){};
258
foo()259 void foo() {
260 Class<char>().f(123);
261 };
262
263 } // namespace test_unnamed_arg
264
265 namespace cxx_dependent_scope_member_expr_testing {
266
267 class PartitionAllocator {
268 public:
method()269 static void method() {}
270 };
271
272 template <typename Allocator = PartitionAllocator>
273 class Vector {
274 public:
275 // https://crbug.com/582315: |Allocator::method| is a
276 // CXXDependentScopeMemberExpr.
anotherMethod()277 void anotherMethod() {
278 if (std::is_class<Allocator>::value) // Shouldn't rename |value|
279 Allocator::method(); // Should rename |method| -> |Method|.
280 }
281 };
282
283 template <typename Allocator = PartitionAllocator>
test()284 void test() {
285 // https://crbug.com/582315: |Allocator::method| is a
286 // DependentScopeDeclRefExpr.
287 if (std::is_class<Allocator>::value) // Shouldn't rename |value|.
288 Allocator::method(); // Should rename |method|.
289 }
290
291 class InterceptingCanvasBase : public ::not_blink::Class {
292 public:
virtualMethodInBlink()293 virtual void virtualMethodInBlink(){};
294 };
295
296 template <typename DerivedCanvas>
297 class InterceptingCanvas : public InterceptingCanvasBase {
298 public:
virtualMethod()299 void virtualMethod() override {
300 this->Class::virtualMethod(); // https://crbug.com/582315#c19
301 this->InterceptingCanvasBase::virtualMethodInBlink();
302 }
303 };
304
305 template <typename T>
306 class ThreadSpecific {
307 public:
308 T* operator->();
309 operator T*();
310 };
311
312 template <typename T>
operator T*()313 inline ThreadSpecific<T>::operator T*() {
314 return nullptr;
315 }
316
317 template <typename T>
operator ->()318 inline T* ThreadSpecific<T>::operator->() {
319 return operator T*();
320 }
321
322 class Class {
323 public:
virtualMethodInBlink()324 virtual void virtualMethodInBlink() {}
325 };
326
327 } // namespace cxx_dependent_scope_member_expr_testing
328
329 namespace blacklisting_of_renaming_of_begin_method {
330
331 template <typename T>
332 class IntrusiveHeap {
333 public:
334 // https://crbug.com/672353: |begin| shouldn't be rewritten to |Begin|.
begin() const335 const T* begin() const { return nullptr; }
336 };
337
338 } // namespace blacklisting_of_renaming_of_begin_method
339
340 } // namespace blink
341
342 namespace not_blink {
343
344 namespace cxx_dependent_scope_member_expr_testing {
345
346 class Base : public ::blink::cxx_dependent_scope_member_expr_testing::Class {
347 public:
virtualMethod()348 virtual void virtualMethod() {}
349 };
350
351 template <typename T>
352 class Derived : public Base {
353 public:
virtualMethod()354 void virtualMethod() override {
355 this->Class::virtualMethodInBlink();
356 this->Base::virtualMethod();
357 }
358 };
359
360 } // namespace cxx_dependent_scope_member_expr_testing
361
362 namespace blink_methods_called_from_mojo_traits_are_not_rewritten {
363
364 template <typename V>
365 struct MapTraits;
366
367 template <typename V>
368 struct MapTraits<blink::test_unnamed_arg::Class<V>> {
SetToEmptynot_blink::blink_methods_called_from_mojo_traits_are_not_rewritten::MapTraits369 static void SetToEmpty(blink::test_unnamed_arg::Class<V>* output) {
370 // Need to rewrite |f| to |F| below (because this method name
371 // does get rewritten when processing blink::test_unnamed_arg::Class).
372 // See also https://crbug.com/670434.
373 output->f(123);
374 }
375 };
376
377 } // namespace blink_methods_called_from_mojo_traits_are_not_rewritten
378
379 } // namespace not_blink
380