// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include namespace not_blink { void function(int x) {} class Class { public: void method() {} virtual void virtualMethod() {} template void methodTemplate(T) {} template static void staticMethodTemplate(T) {} }; template void functionTemplate(T x) {} template void functionTemplate2() { T::staticMethodTemplate(123); } template class TemplatedClass { public: void anotherMethod() { T::staticMethodTemplate(123); } }; } // not_blink namespace blink { bool functionNotMarkedConstexpr(int a) { return a == 4 || a == 10; } template bool templatedFunctionNotMarkedConstexpr(T t) { return !!t; } int g_globalNumber; template void F() { // These are const but hacker_case so we leave them alone. const int maybe_a_const = sizeof(T); const int is_a_const = number; // These are const expressions so they get a k prefix. const int maybeAConstToo = sizeof(T); const int isAConstToo = number; // These are built from calls to functions which produces inconsistent // results so they should not be considered const to be safe. const bool fromAMethod = functionNotMarkedConstexpr(number); const bool fromATemplatedMethod = templatedFunctionNotMarkedConstexpr(number); // A complex statement of const things is const. const bool complexConst = number || (number + 1); // A complex statement with a non-const thing is not const. const bool complexNotConst = number || (g_globalNumber + 1); // A const built from other consts is a const. const bool constFromAConst = complexConst || number; } template void F() { // These are const but hacker_case so we leave them alone. const int maybe_a_const = sizeof...(T); const int is_a_const = number; // These are const expressions so they get a k prefix. const int maybeAConstToo = sizeof...(T); const int isAConstToo = number; } namespace test_member_in_template { template class HasAMember { public: HasAMember() {} HasAMember(const T&) {} void usesMember() { const int notConst = m_i; } void alsoUsesMember(); private: int m_i; }; template void HasAMember::alsoUsesMember() { const int notConst = m_i; } template static void basedOnSubType(const HasAMember& t) { const HasAMember problematicNotConst(t); } void Run() { HasAMember().usesMember(); basedOnSubType(HasAMember()); enum E { A }; basedOnSubType(HasAMember()); } } namespace test_template_arg_is_function { void f(int x) {} template void h(T x) { g(x); } void test() { // f should be rewritten. h(0); // Non-Blink should stay the same. h(1); // The int one makes the methods called from F() considered as constexpr, and // can be collapsed to not have template arguments before it reaches the AST. F(); // The enum one makes them not constexpr, as it doesn't collapse away the // template stuff as much. This can lead to conflicting decisions about // the names inside F() vs the above instantiation. enum E { A }; F(); } } // namespace test_template_arg_is_function namespace test_template_arg_is_method { class Class { public: void method() {} }; template void h(T&& x) { (x.*g)(); } void test() { // method should be rewritten. h(Class()); // Non-Blink should stay the same. h(not_blink::Class()); } } // namespace test_template_arg_is_method namespace test_template_arg_is_function_template { namespace nested { template void f(T) {} } template void h(T x) { g(x); } void test() { // f should be rewritten. h(0); // Non-Blink should stay the same. h(1); } } // namespace test_template_arg_is_function_template namespace test_template_arg_is_method_template_in_non_member_context { struct Class { template static void f(T) {} }; template void h(T x) { g(x); } void test() { // f should be rewritten. h(0); // Non-Blink should stay the same. h(1); } } // test_template_arg_is_method_template_in_non_member_context namespace test_inherited_field { template class BaseClass { public: unsigned long m_size; }; template class DerivedClass : protected BaseClass { private: using Base = BaseClass; // https://crbug.com/640016: Need to rewrite |m_size| into |size_|. using Base::m_size; void method() { m_size = 123; } }; } // namespace test_inherited_field namespace test_template_arg_is_method_template_in_member_context { struct Class { template static void f(T) {} }; struct Class2 { template void f(T x) { // f should be rewritten. Class c; c.f(x); // Non-Blink should stay the same. not_blink::Class c2; c2.method(x); } }; } // namespace test_template_arg_is_method_template_in_member_context namespace test_unnamed_arg { template class Class { public: // Test for https://crbug.com/598141 - shouldn't rewrite // ...int); // into // ...intdata_size; void f(int); }; template void Class::f(int dataSize){}; void foo() { Class().f(123); }; } // namespace test_unnamed_arg namespace cxx_dependent_scope_member_expr_testing { class PartitionAllocator { public: static void method() {} }; template class Vector { public: // https://crbug.com/582315: |Allocator::method| is a // CXXDependentScopeMemberExpr. void anotherMethod() { if (std::is_class::value) // Shouldn't rename |value| Allocator::method(); // Should rename |method| -> |Method|. } }; template void test() { // https://crbug.com/582315: |Allocator::method| is a // DependentScopeDeclRefExpr. if (std::is_class::value) // Shouldn't rename |value|. Allocator::method(); // Should rename |method|. } class InterceptingCanvasBase : public ::not_blink::Class { public: virtual void virtualMethodInBlink(){}; }; template class InterceptingCanvas : public InterceptingCanvasBase { public: void virtualMethod() override { this->Class::virtualMethod(); // https://crbug.com/582315#c19 this->InterceptingCanvasBase::virtualMethodInBlink(); } }; template class ThreadSpecific { public: T* operator->(); operator T*(); }; template inline ThreadSpecific::operator T*() { return nullptr; } template inline T* ThreadSpecific::operator->() { return operator T*(); } class Class { public: virtual void virtualMethodInBlink() {} }; } // namespace cxx_dependent_scope_member_expr_testing namespace blacklisting_of_renaming_of_begin_method { template class IntrusiveHeap { public: // https://crbug.com/672353: |begin| shouldn't be rewritten to |Begin|. const T* begin() const { return nullptr; } }; } // namespace blacklisting_of_renaming_of_begin_method } // namespace blink namespace not_blink { namespace cxx_dependent_scope_member_expr_testing { class Base : public ::blink::cxx_dependent_scope_member_expr_testing::Class { public: virtual void virtualMethod() {} }; template class Derived : public Base { public: void virtualMethod() override { this->Class::virtualMethodInBlink(); this->Base::virtualMethod(); } }; } // namespace cxx_dependent_scope_member_expr_testing namespace blink_methods_called_from_mojo_traits_are_not_rewritten { template struct MapTraits; template struct MapTraits> { static void SetToEmpty(blink::test_unnamed_arg::Class* output) { // Need to rewrite |f| to |F| below (because this method name // does get rewritten when processing blink::test_unnamed_arg::Class). // See also https://crbug.com/670434. output->f(123); } }; } // namespace blink_methods_called_from_mojo_traits_are_not_rewritten } // namespace not_blink