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 7namespace not_blink { 8 9void function(int x) {} 10 11class Class { 12 public: 13 void method() {} 14 virtual void virtualMethod() {} 15 template <typename T> 16 void methodTemplate(T) {} 17 template <typename T> 18 static void staticMethodTemplate(T) {} 19}; 20 21template <typename T> 22void functionTemplate(T x) {} 23 24template <typename T = Class> 25void functionTemplate2() { 26 T::staticMethodTemplate(123); 27} 28 29template <typename T = Class> 30class TemplatedClass { 31 public: 32 void anotherMethod() { T::staticMethodTemplate(123); } 33}; 34 35} // not_blink 36 37namespace blink { 38 39bool FunctionNotMarkedConstexpr(int a) { 40 return a == 4 || a == 10; 41} 42 43template <typename T> 44bool TemplatedFunctionNotMarkedConstexpr(T t) { 45 return !!t; 46} 47 48int g_global_number; 49 50template <typename T, int number> 51void 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 71template <int number, typename... T> 72void 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 81namespace test_member_in_template { 82 83template <typename T> 84class HasAMember { 85 public: 86 HasAMember() {} 87 HasAMember(const T&) {} 88 89 void UsesMember() { const int not_const = i_; } 90 void AlsoUsesMember(); 91 92 private: 93 int i_; 94}; 95 96template <typename T> 97void HasAMember<T>::AlsoUsesMember() { 98 const int not_const = i_; 99} 100 101template <typename T> 102static void BasedOnSubType(const HasAMember<T>& t) { 103 const HasAMember<T> problematic_not_const(t); 104} 105 106void Run() { 107 HasAMember<int>().UsesMember(); 108 109 BasedOnSubType<int>(HasAMember<int>()); 110 enum E { A }; 111 BasedOnSubType<E>(HasAMember<E>()); 112} 113} 114 115namespace test_template_arg_is_function { 116 117void F(int x) {} 118 119template <typename T, void g(T)> 120void H(T x) { 121 g(x); 122} 123 124void 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 142namespace test_template_arg_is_method { 143 144class Class { 145 public: 146 void Method() {} 147}; 148 149template <typename T, void (T::*g)()> 150void H(T&& x) { 151 (x.*g)(); 152} 153 154void Test() { 155 // method should be rewritten. 156 H<Class, &Class::Method>(Class()); 157 // Non-Blink should stay the same. 158 H<not_blink::Class, ¬_blink::Class::method>(not_blink::Class()); 159} 160 161} // namespace test_template_arg_is_method 162 163namespace test_template_arg_is_function_template { 164 165namespace nested { 166template <typename T> 167void F(T) {} 168} 169 170template <typename T, void g(T)> 171void H(T x) { 172 g(x); 173} 174 175void 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 184namespace test_template_arg_is_method_template_in_non_member_context { 185 186struct Class { 187 template <typename T> 188 static void F(T) {} 189}; 190 191template <typename T, void g(T)> 192void H(T x) { 193 g(x); 194} 195 196void 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 205namespace test_inherited_field { 206 207template <typename T> 208class BaseClass { 209 public: 210 unsigned long size_; 211}; 212 213template <typename T> 214class 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_; 219 void Method() { size_ = 123; } 220}; 221 222} // namespace test_inherited_field 223 224namespace test_template_arg_is_method_template_in_member_context { 225 226struct Class { 227 template <typename T> 228 static void F(T) {} 229}; 230 231struct Class2 { 232 template <typename T> 233 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 245namespace test_unnamed_arg { 246 247template <typename T> 248class 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 257template <typename T> 258void Class<T>::F(int data_size){}; 259 260void Foo() { 261 Class<char>().F(123); 262}; 263 264} // namespace test_unnamed_arg 265 266namespace cxx_dependent_scope_member_expr_testing { 267 268class PartitionAllocator { 269 public: 270 static void Method() {} 271}; 272 273template <typename Allocator = PartitionAllocator> 274class Vector { 275 public: 276 // https://crbug.com/582315: |Allocator::method| is a 277 // CXXDependentScopeMemberExpr. 278 void AnotherMethod() { 279 if (std::is_class<Allocator>::value) // Shouldn't rename |value| 280 Allocator::Method(); // Should rename |method| -> |Method|. 281 } 282}; 283 284template <typename Allocator = PartitionAllocator> 285void 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 292class InterceptingCanvasBase : public ::not_blink::Class { 293 public: 294 virtual void VirtualMethodInBlink(){}; 295}; 296 297template <typename DerivedCanvas> 298class InterceptingCanvas : public InterceptingCanvasBase { 299 public: 300 void virtualMethod() override { 301 this->Class::virtualMethod(); // https://crbug.com/582315#c19 302 this->InterceptingCanvasBase::VirtualMethodInBlink(); 303 } 304}; 305 306template <typename T> 307class ThreadSpecific { 308 public: 309 T* operator->(); 310 operator T*(); 311}; 312 313template <typename T> 314inline ThreadSpecific<T>::operator T*() { 315 return nullptr; 316} 317 318template <typename T> 319inline T* ThreadSpecific<T>::operator->() { 320 return operator T*(); 321} 322 323class Class { 324 public: 325 virtual void VirtualMethodInBlink() {} 326}; 327 328} // namespace cxx_dependent_scope_member_expr_testing 329 330namespace blacklisting_of_renaming_of_begin_method { 331 332template <typename T> 333class IntrusiveHeap { 334 public: 335 // https://crbug.com/672353: |begin| shouldn't be rewritten to |Begin|. 336 const T* begin() const { return nullptr; } 337}; 338 339} // namespace blacklisting_of_renaming_of_begin_method 340 341} // namespace blink 342 343namespace not_blink { 344 345namespace cxx_dependent_scope_member_expr_testing { 346 347class Base : public ::blink::cxx_dependent_scope_member_expr_testing::Class { 348 public: 349 virtual void virtualMethod() {} 350}; 351 352template <typename T> 353class Derived : public Base { 354 public: 355 void virtualMethod() override { 356 this->Class::VirtualMethodInBlink(); 357 this->Base::virtualMethod(); 358 } 359}; 360 361} // namespace cxx_dependent_scope_member_expr_testing 362 363namespace blink_methods_called_from_mojo_traits_are_not_rewritten { 364 365template <typename V> 366struct MapTraits; 367 368template <typename V> 369struct MapTraits<blink::test_unnamed_arg::Class<V>> { 370 static void SetToEmpty(blink::test_unnamed_arg::Class<V>* output) { 371 // Need to rewrite |f| to |F| below (because this method name 372 // does get rewritten when processing blink::test_unnamed_arg::Class). 373 // See also https://crbug.com/670434. 374 output->F(123); 375 } 376}; 377 378} // namespace blink_methods_called_from_mojo_traits_are_not_rewritten 379 380} // namespace not_blink 381