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_global_number;
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 kMaybeAConstToo = sizeof(T);
57   const int kIsAConstToo = 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 from_a_method = FunctionNotMarkedConstexpr(number);
61   const bool from_a_templated_method =
62       TemplatedFunctionNotMarkedConstexpr(number);
63   // A complex statement of const things is const.
64   const bool kComplexConst = number || (number + 1);
65   // A complex statement with a non-const thing is not const.
66   const bool complex_not_const = number || (g_global_number + 1);
67   // A const built from other consts is a const.
68   const bool kConstFromAConst = kComplexConst || number;
69 }
70 
71 template <int number, typename... T>
F()72 void F() {
73   // These are const but hacker_case so we leave them alone.
74   const int maybe_a_const = sizeof...(T);
75   const int is_a_const = number;
76   // These are const expressions so they get a k prefix.
77   const int kMaybeAConstToo = sizeof...(T);
78   const int kIsAConstToo = number;
79 }
80 
81 namespace test_member_in_template {
82 
83 template <typename T>
84 class HasAMember {
85  public:
HasAMember()86   HasAMember() {}
HasAMember(const T &)87   HasAMember(const T&) {}
88 
UsesMember()89   void UsesMember() { const int not_const = i_; }
90   void AlsoUsesMember();
91 
92  private:
93   int i_;
94 };
95 
96 template <typename T>
AlsoUsesMember()97 void HasAMember<T>::AlsoUsesMember() {
98   const int not_const = i_;
99 }
100 
101 template <typename T>
BasedOnSubType(const HasAMember<T> & t)102 static void BasedOnSubType(const HasAMember<T>& t) {
103   const HasAMember<T> problematic_not_const(t);
104 }
105 
Run()106 void Run() {
107   HasAMember<int>().UsesMember();
108 
109   BasedOnSubType<int>(HasAMember<int>());
110   enum E { A };
111   BasedOnSubType<E>(HasAMember<E>());
112 }
113 }
114 
115 namespace test_template_arg_is_function {
116 
F(int x)117 void F(int x) {}
118 
119 template <typename T, void g(T)>
H(T x)120 void H(T x) {
121   g(x);
122 }
123 
Test()124 void Test() {
125   // f should be rewritten.
126   H<int, F>(0);
127   // Non-Blink should stay the same.
128   H<int, not_blink::function>(1);
129 
130   // The int one makes the methods called from F() considered as constexpr, and
131   // can be collapsed to not have template arguments before it reaches the AST.
132   F<int, 10>();
133   // The enum one makes them not constexpr, as it doesn't collapse away the
134   // template stuff as much. This can lead to conflicting decisions about
135   // the names inside F() vs the above instantiation.
136   enum E { A };
137   F<E, 11>();
138 }
139 
140 }  // namespace test_template_arg_is_function
141 
142 namespace test_template_arg_is_method {
143 
144 class Class {
145  public:
Method()146   void Method() {}
147 };
148 
149 template <typename T, void (T::*g)()>
H(T && x)150 void H(T&& x) {
151   (x.*g)();
152 }
153 
Test()154 void Test() {
155   // method should be rewritten.
156   H<Class, &Class::Method>(Class());
157   // Non-Blink should stay the same.
158   H<not_blink::Class, &not_blink::Class::method>(not_blink::Class());
159 }
160 
161 }  // namespace test_template_arg_is_method
162 
163 namespace test_template_arg_is_function_template {
164 
165 namespace nested {
166 template <typename T>
F(T)167 void F(T) {}
168 }
169 
170 template <typename T, void g(T)>
H(T x)171 void H(T x) {
172   g(x);
173 }
174 
Test()175 void Test() {
176   // f should be rewritten.
177   H<int, nested::F>(0);
178   // Non-Blink should stay the same.
179   H<int, not_blink::functionTemplate>(1);
180 }
181 
182 }  // namespace test_template_arg_is_function_template
183 
184 namespace test_template_arg_is_method_template_in_non_member_context {
185 
186 struct Class {
187   template <typename T>
Fblink::test_template_arg_is_method_template_in_non_member_context::Class188   static void F(T) {}
189 };
190 
191 template <typename T, void g(T)>
H(T x)192 void H(T x) {
193   g(x);
194 }
195 
Test()196 void Test() {
197   // f should be rewritten.
198   H<int, Class::F>(0);
199   // Non-Blink should stay the same.
200   H<int, not_blink::Class::staticMethodTemplate>(1);
201 }
202 
203 }  // test_template_arg_is_method_template_in_non_member_context
204 
205 namespace test_inherited_field {
206 
207 template <typename T>
208 class BaseClass {
209  public:
210   unsigned long size_;
211 };
212 
213 template <typename T>
214 class DerivedClass : protected BaseClass<T> {
215  private:
216   using Base = BaseClass<T>;
217   // https://crbug.com/640016: Need to rewrite |m_size| into |size_|.
218   using Base::size_;
Method()219   void Method() { size_ = 123; }
220 };
221 
222 }  // namespace test_inherited_field
223 
224 namespace test_template_arg_is_method_template_in_member_context {
225 
226 struct Class {
227   template <typename T>
Fblink::test_template_arg_is_method_template_in_member_context::Class228   static void F(T) {}
229 };
230 
231 struct Class2 {
232   template <typename T>
Fblink::test_template_arg_is_method_template_in_member_context::Class2233   void F(T x) {
234     // f should be rewritten.
235     Class c;
236     c.F(x);
237     // Non-Blink should stay the same.
238     not_blink::Class c2;
239     c2.method(x);
240   }
241 };
242 
243 }  // namespace test_template_arg_is_method_template_in_member_context
244 
245 namespace test_unnamed_arg {
246 
247 template <typename T>
248 class Class {
249  public:
250   // Test for https://crbug.com/598141 - shouldn't rewrite
251   //    ...int);
252   // into
253   //    ...intdata_size;
254   void F(int);
255 };
256 
257 template <typename T>
F(int data_size)258 void Class<T>::F(int data_size){};
259 
Foo()260 void Foo() {
261   Class<char>().F(123);
262 };
263 
264 }  // namespace test_unnamed_arg
265 
266 namespace cxx_dependent_scope_member_expr_testing {
267 
268 class PartitionAllocator {
269  public:
Method()270   static void Method() {}
271 };
272 
273 template <typename Allocator = PartitionAllocator>
274 class Vector {
275  public:
276   // https://crbug.com/582315: |Allocator::method| is a
277   // CXXDependentScopeMemberExpr.
AnotherMethod()278   void AnotherMethod() {
279     if (std::is_class<Allocator>::value)  // Shouldn't rename |value|
280       Allocator::Method();                // Should rename |method| -> |Method|.
281   }
282 };
283 
284 template <typename Allocator = PartitionAllocator>
Test()285 void Test() {
286   // https://crbug.com/582315: |Allocator::method| is a
287   // DependentScopeDeclRefExpr.
288   if (std::is_class<Allocator>::value)  // Shouldn't rename |value|.
289     Allocator::Method();                // Should rename |method|.
290 }
291 
292 class InterceptingCanvasBase : public ::not_blink::Class {
293  public:
VirtualMethodInBlink()294   virtual void VirtualMethodInBlink(){};
295 };
296 
297 template <typename DerivedCanvas>
298 class InterceptingCanvas : public InterceptingCanvasBase {
299  public:
virtualMethod()300   void virtualMethod() override {
301     this->Class::virtualMethod();  // https://crbug.com/582315#c19
302     this->InterceptingCanvasBase::VirtualMethodInBlink();
303   }
304 };
305 
306 template <typename T>
307 class ThreadSpecific {
308  public:
309   T* operator->();
310   operator T*();
311 };
312 
313 template <typename T>
operator T*()314 inline ThreadSpecific<T>::operator T*() {
315   return nullptr;
316 }
317 
318 template <typename T>
operator ->()319 inline T* ThreadSpecific<T>::operator->() {
320   return operator T*();
321 }
322 
323 class Class {
324  public:
VirtualMethodInBlink()325   virtual void VirtualMethodInBlink() {}
326 };
327 
328 }  // namespace cxx_dependent_scope_member_expr_testing
329 
330 namespace blacklisting_of_renaming_of_begin_method {
331 
332 template <typename T>
333 class IntrusiveHeap {
334  public:
335   // https://crbug.com/672353: |begin| shouldn't be rewritten to |Begin|.
begin() const336   const T* begin() const { return nullptr; }
337 };
338 
339 }  // namespace blacklisting_of_renaming_of_begin_method
340 
341 namespace specializations {
342 
343 template <unsigned long sizeOfValue>
344 int ToV8SignedIntegerInternal(long value);
345 
346 template <>
ToV8SignedIntegerInternal(long value)347 int ToV8SignedIntegerInternal<4>(long value) {
348   return 123 + value;
349 }
350 
351 template <>
ToV8SignedIntegerInternal(long value)352 int ToV8SignedIntegerInternal<8>(long value) {
353   return 456 + value;
354 }
355 
ToV8(int value)356 int ToV8(int value) {
357   return ToV8SignedIntegerInternal<sizeof value>(value);
358 }
359 
ToV8(long value)360 int ToV8(long value) {
361   return ToV8SignedIntegerInternal<sizeof value>(value);
362 }
363 
364 }  // namespace specializations
365 
366 }  // namespace blink
367 
368 namespace not_blink {
369 
370 namespace cxx_dependent_scope_member_expr_testing {
371 
372 class Base : public ::blink::cxx_dependent_scope_member_expr_testing::Class {
373  public:
virtualMethod()374   virtual void virtualMethod() {}
375 };
376 
377 template <typename T>
378 class Derived : public Base {
379  public:
virtualMethod()380   void virtualMethod() override {
381     this->Class::VirtualMethodInBlink();
382     this->Base::virtualMethod();
383   }
384 };
385 
386 }  // namespace cxx_dependent_scope_member_expr_testing
387 
388 namespace blink_methods_called_from_mojo_traits_are_not_rewritten {
389 
390 template <typename V>
391 struct MapTraits;
392 
393 template <typename V>
394 struct MapTraits<blink::test_unnamed_arg::Class<V>> {
SetToEmptynot_blink::blink_methods_called_from_mojo_traits_are_not_rewritten::MapTraits395   static void SetToEmpty(blink::test_unnamed_arg::Class<V>* output) {
396     // Need to rewrite |f| to |F| below (because this method name
397     // does get rewritten when processing blink::test_unnamed_arg::Class).
398     // See also https://crbug.com/670434.
399     output->F(123);
400   }
401 };
402 
403 }  // namespace blink_methods_called_from_mojo_traits_are_not_rewritten
404 
405 }  // namespace not_blink
406