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_globalNumber; 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 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 70template <int number, typename... T> 71void 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 80namespace test_member_in_template { 81 82template <typename T> 83class HasAMember { 84 public: 85 HasAMember() {} 86 HasAMember(const T&) {} 87 88 void usesMember() { const int notConst = m_i; } 89 void alsoUsesMember(); 90 91 private: 92 int m_i; 93}; 94 95template <typename T> 96void HasAMember<T>::alsoUsesMember() { 97 const int notConst = m_i; 98} 99 100template <typename T> 101static void basedOnSubType(const HasAMember<T>& t) { 102 const HasAMember<T> problematicNotConst(t); 103} 104 105void Run() { 106 HasAMember<int>().usesMember(); 107 108 basedOnSubType<int>(HasAMember<int>()); 109 enum E { A }; 110 basedOnSubType<E>(HasAMember<E>()); 111} 112} 113 114namespace test_template_arg_is_function { 115 116void f(int x) {} 117 118template <typename T, void g(T)> 119void h(T x) { 120 g(x); 121} 122 123void 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 141namespace test_template_arg_is_method { 142 143class Class { 144 public: 145 void method() {} 146}; 147 148template <typename T, void (T::*g)()> 149void h(T&& x) { 150 (x.*g)(); 151} 152 153void 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 162namespace test_template_arg_is_function_template { 163 164namespace nested { 165template <typename T> 166void f(T) {} 167} 168 169template <typename T, void g(T)> 170void h(T x) { 171 g(x); 172} 173 174void 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 183namespace test_template_arg_is_method_template_in_non_member_context { 184 185struct Class { 186 template <typename T> 187 static void f(T) {} 188}; 189 190template <typename T, void g(T)> 191void h(T x) { 192 g(x); 193} 194 195void 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 204namespace test_inherited_field { 205 206template <typename T> 207class BaseClass { 208 public: 209 unsigned long m_size; 210}; 211 212template <typename T> 213class 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; 218 void method() { m_size = 123; } 219}; 220 221} // namespace test_inherited_field 222 223namespace test_template_arg_is_method_template_in_member_context { 224 225struct Class { 226 template <typename T> 227 static void f(T) {} 228}; 229 230struct Class2 { 231 template <typename T> 232 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 244namespace test_unnamed_arg { 245 246template <typename T> 247class 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 256template <typename T> 257void Class<T>::f(int dataSize){}; 258 259void foo() { 260 Class<char>().f(123); 261}; 262 263} // namespace test_unnamed_arg 264 265namespace cxx_dependent_scope_member_expr_testing { 266 267class PartitionAllocator { 268 public: 269 static void method() {} 270}; 271 272template <typename Allocator = PartitionAllocator> 273class Vector { 274 public: 275 // https://crbug.com/582315: |Allocator::method| is a 276 // CXXDependentScopeMemberExpr. 277 void anotherMethod() { 278 if (std::is_class<Allocator>::value) // Shouldn't rename |value| 279 Allocator::method(); // Should rename |method| -> |Method|. 280 } 281}; 282 283template <typename Allocator = PartitionAllocator> 284void 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 291class InterceptingCanvasBase : public ::not_blink::Class { 292 public: 293 virtual void virtualMethodInBlink(){}; 294}; 295 296template <typename DerivedCanvas> 297class InterceptingCanvas : public InterceptingCanvasBase { 298 public: 299 void virtualMethod() override { 300 this->Class::virtualMethod(); // https://crbug.com/582315#c19 301 this->InterceptingCanvasBase::virtualMethodInBlink(); 302 } 303}; 304 305template <typename T> 306class ThreadSpecific { 307 public: 308 T* operator->(); 309 operator T*(); 310}; 311 312template <typename T> 313inline ThreadSpecific<T>::operator T*() { 314 return nullptr; 315} 316 317template <typename T> 318inline T* ThreadSpecific<T>::operator->() { 319 return operator T*(); 320} 321 322class Class { 323 public: 324 virtual void virtualMethodInBlink() {} 325}; 326 327} // namespace cxx_dependent_scope_member_expr_testing 328 329namespace blacklisting_of_renaming_of_begin_method { 330 331template <typename T> 332class IntrusiveHeap { 333 public: 334 // https://crbug.com/672353: |begin| shouldn't be rewritten to |Begin|. 335 const T* begin() const { return nullptr; } 336}; 337 338} // namespace blacklisting_of_renaming_of_begin_method 339 340} // namespace blink 341 342namespace not_blink { 343 344namespace cxx_dependent_scope_member_expr_testing { 345 346class Base : public ::blink::cxx_dependent_scope_member_expr_testing::Class { 347 public: 348 virtual void virtualMethod() {} 349}; 350 351template <typename T> 352class Derived : public Base { 353 public: 354 void virtualMethod() override { 355 this->Class::virtualMethodInBlink(); 356 this->Base::virtualMethod(); 357 } 358}; 359 360} // namespace cxx_dependent_scope_member_expr_testing 361 362namespace blink_methods_called_from_mojo_traits_are_not_rewritten { 363 364template <typename V> 365struct MapTraits; 366 367template <typename V> 368struct MapTraits<blink::test_unnamed_arg::Class<V>> { 369 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