astrelni updated this revision to Diff 206889.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62977/new/

https://reviews.llvm.org/D62977

Files:
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
  clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-upgrade-googletest-case.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest-typed-test.h
  clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest.h
  
clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest-typed-test.h
  clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest.h
  clang-tools-extra/test/clang-tidy/google-upgrade-googletest-case.cpp
  llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn

Index: llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn
===================================================================
--- llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn
+++ llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn
@@ -28,6 +28,7 @@
     "OverloadedUnaryAndCheck.cpp",
     "TodoCommentCheck.cpp",
     "UnnamedNamespaceInHeaderCheck.cpp",
+    "UpgradeGoogletestCaseCheck.cpp",
     "UsingNamespaceDirectiveCheck.cpp",
   ]
 }
Index: clang-tools-extra/test/clang-tidy/google-upgrade-googletest-case.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-upgrade-googletest-case.cpp
@@ -0,0 +1,1016 @@
+// RUN: %check_clang_tidy %s google-upgrade-googletest-case %t -- -- -I%S/Inputs
+// RUN: %check_clang_tidy -check-suffix=NOSUITE %s google-upgrade-googletest-case %t -- -- -DNOSUITE -I%S/Inputs/gtest/nosuite
+
+#include "gtest/gtest.h"
+
+// When including a version of googletest without the replacement names, this
+// check should not produce any diagnostics. The following dummy fix is present
+// because `check_clang_tidy.py` requires at least one warning, fix or note. 
+void Dummy() {}
+// CHECK-FIXES-NOSUITE: void Dummy() {}
+
+// ----------------------------------------------------------------------------
+// Macros
+
+TYPED_TEST_CASE(FooTest, FooTypes);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case' are deprecated; use equivalent APIs named with 'suite'
+// CHECK-FIXES: TYPED_TEST_SUITE(FooTest, FooTypes);
+TYPED_TEST_CASE_P(FooTest);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: TYPED_TEST_SUITE_P(FooTest);
+REGISTER_TYPED_TEST_CASE_P(FooTest, FooTestName);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: REGISTER_TYPED_TEST_SUITE_P(FooTest, FooTestName);
+INSTANTIATE_TYPED_TEST_CASE_P(FooPrefix, FooTest, FooTypes);
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: INSTANTIATE_TYPED_TEST_SUITE_P(FooPrefix, FooTest, FooTypes);
+
+#ifdef TYPED_TEST_CASE
+// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case'
+#undef TYPED_TEST_CASE
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+#define TYPED_TEST_CASE(CaseName, Types, ...)
+#endif
+
+#ifdef TYPED_TEST_CASE_P
+// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case'
+#undef TYPED_TEST_CASE_P
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+#define TYPED_TEST_CASE_P(SuiteName)
+#endif
+
+#ifdef REGISTER_TYPED_TEST_CASE_P
+// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case'
+#undef REGISTER_TYPED_TEST_CASE_P
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+#define REGISTER_TYPED_TEST_CASE_P(SuiteName, ...)
+#endif
+
+#ifdef INSTANTIATE_TYPED_TEST_CASE_P
+// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case'
+#undef INSTANTIATE_TYPED_TEST_CASE_P
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, SuiteName, Types, ...)
+#endif
+
+TYPED_TEST_CASE(FooTest, FooTypes);
+TYPED_TEST_CASE_P(FooTest);
+REGISTER_TYPED_TEST_CASE_P(FooTest, FooTestName);
+INSTANTIATE_TYPED_TEST_CASE_P(FooPrefix, FooTest, FooTypes);
+
+// ----------------------------------------------------------------------------
+// testing::Test
+
+class FooTest : public testing::Test {
+public:
+  static void SetUpTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: static void SetUpTestSuite();
+  static void TearDownTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: static void TearDownTestSuite();
+};
+
+void FooTest::SetUpTestCase() {}
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: void FooTest::SetUpTestSuite() {}
+
+void FooTest::TearDownTestCase() {}
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: void FooTest::TearDownTestSuite() {}
+
+template <typename T> class FooTypedTest : public testing::Test {
+public:
+  static void SetUpTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: static void SetUpTestSuite();
+  static void TearDownTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: static void TearDownTestSuite();
+};
+
+template <typename T> void FooTypedTest<T>::SetUpTestCase() {}
+// CHECK-MESSAGES: [[@LINE-1]]:45: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: void FooTypedTest<T>::SetUpTestSuite() {}
+
+template <typename T> void FooTypedTest<T>::TearDownTestCase() {}
+// CHECK-MESSAGES: [[@LINE-1]]:45: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: void FooTypedTest<T>::TearDownTestSuite() {}
+
+class BarTest : public testing::Test {
+public:
+  using Test::SetUpTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using Test::SetUpTestSuite;
+  using Test::TearDownTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using Test::TearDownTestSuite;
+};
+
+class BarTest2 : public FooTest {
+public:
+  using FooTest::SetUpTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using FooTest::SetUpTestSuite;
+  using FooTest::TearDownTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using FooTest::TearDownTestSuite;
+};
+
+// If a derived type already has the replacements, we only provide a warning
+// since renaming or deleting the old declarations may not be safe.
+class BarTest3 : public testing::Test {
+ public:
+  static void SetUpTestCase() {}
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  static void SetUpTestSuite() {}
+
+  static void TearDownTestCase() {}
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  static void TearDownTestSuite() {}
+};
+
+namespace nesting_ns {
+namespace testing {
+
+class Test {
+public:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+} // namespace testing
+
+void Test() {
+  testing::Test::SetUpTestCase();
+  testing::Test::TearDownTestCase();
+}
+
+} // namespace nesting_ns
+
+template <typename T>
+void testInstantiationOnlyWarns() {
+  T::SetUpTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Google Test APIs named with 'case'
+  T::TearDownTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Google Test APIs named with 'case'
+}
+
+#define SET_UP_TEST_CASE_MACRO_REPLACE SetUpTestCase
+#define TEST_SET_UP_TEST_CASE_MACRO_WARN_ONLY ::testing::Test::SetUpTestCase
+
+void setUpTearDownCallAndReference() {
+  testing::Test::SetUpTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::Test::SetUpTestSuite();
+  FooTest::SetUpTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: FooTest::SetUpTestSuite();
+
+  testing::Test::TearDownTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::Test::TearDownTestSuite();
+  FooTest::TearDownTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: FooTest::TearDownTestSuite();
+
+  auto F = &testing::Test::SetUpTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F = &testing::Test::SetUpTestSuite;
+  F = &testing::Test::TearDownTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: F = &testing::Test::TearDownTestSuite;
+  F = &FooTest::SetUpTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: F = &FooTest::SetUpTestSuite;
+  F = &FooTest::TearDownTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: F = &FooTest::TearDownTestSuite;
+
+  using MyTest = testing::Test;
+  MyTest::SetUpTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: MyTest::SetUpTestSuite();
+  MyTest::TearDownTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: MyTest::TearDownTestSuite();
+
+  BarTest3::SetUpTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: BarTest3::SetUpTestSuite();
+  BarTest3::TearDownTestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: BarTest3::TearDownTestSuite();
+
+  testInstantiationOnlyWarns<testing::Test>();
+
+  testing::Test::SET_UP_TEST_CASE_MACRO_REPLACE();
+  // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::Test::SetUpTestSuite();
+  TEST_SET_UP_TEST_CASE_MACRO_WARN_ONLY();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+}
+
+// ----------------------------------------------------------------------------
+// testing::TestInfo
+
+class FooTestInfo : public testing::TestInfo {
+public:
+  const char *test_case_name() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const char *test_suite_name() const;
+};
+
+const char *FooTestInfo::test_case_name() const {}
+// CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: const char *FooTestInfo::test_suite_name() const {}
+
+class BarTestInfo : public testing::TestInfo {
+public:
+  using TestInfo::test_case_name;
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using TestInfo::test_suite_name;
+};
+
+class BarTestInfo2 : public FooTestInfo {
+public:
+  using FooTestInfo::test_case_name;
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using FooTestInfo::test_suite_name;
+};
+
+class BarTestInfo3 : public testing::TestInfo {
+ public:
+  const char* test_case_name() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case'
+  const char* test_suite_name() const;
+};
+
+namespace nesting_ns {
+namespace testing {
+
+class TestInfo {
+public:
+  const char *test_case_name() const;
+};
+
+} // namespace testing
+
+void FuncInfo() {
+  testing::TestInfo t;
+  (void)t.test_case_name();
+}
+
+} // namespace nesting_ns
+
+template <typename T>
+void testInfoInstantiationOnlyWarns() {
+  T t;
+  (void)t.test_case_name();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+}
+
+#define TEST_CASE_NAME_MACRO_REPLACE test_case_name
+#define TEST_CASE_NAME_MACRO_WARN_ONLY testing::TestInfo().test_case_name
+
+void testInfoCallAndReference() {
+  (void)testing::TestInfo().test_case_name();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::TestInfo().test_suite_name();
+  (void)FooTestInfo().test_case_name();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)FooTestInfo().test_suite_name();
+  auto F1 = &testing::TestInfo::test_case_name;
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F1 = &testing::TestInfo::test_suite_name;
+  auto F2 = &FooTestInfo::test_case_name;
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F2 = &FooTestInfo::test_suite_name;
+  using MyTestInfo = testing::TestInfo;
+  (void)MyTestInfo().test_case_name();
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)MyTestInfo().test_suite_name();
+  (void)BarTestInfo3().test_case_name();
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)BarTestInfo3().test_suite_name();
+
+  testInfoInstantiationOnlyWarns<testing::TestInfo>();
+
+  (void)testing::TestInfo().TEST_CASE_NAME_MACRO_REPLACE();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::TestInfo().test_suite_name();
+  (void)TEST_CASE_NAME_MACRO_WARN_ONLY();
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: Google Test APIs named with 'case'
+}
+
+// ----------------------------------------------------------------------------
+// testing::TestEventListener
+
+class FooTestEventListener : public testing::TestEventListener {
+public:
+  void OnTestCaseStart(const testing::TestCase &) override;
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+  // CHECK-MESSAGES: [[@LINE-2]]:39: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: void OnTestSuiteStart(const testing::TestSuite &) override;
+  void OnTestCaseEnd(const testing::TestCase &) override;
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+  // CHECK-MESSAGES: [[@LINE-2]]:37: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: void OnTestSuiteEnd(const testing::TestSuite &) override;
+};
+
+void FooTestEventListener::OnTestCaseStart(const testing::TestCase &) {}
+// CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+// CHECK-MESSAGES: [[@LINE-2]]:59: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: void FooTestEventListener::OnTestSuiteStart(const testing::TestSuite &) {}
+
+void FooTestEventListener::OnTestCaseEnd(const testing::TestCase &) {}
+// CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+// CHECK-MESSAGES: [[@LINE-2]]:57: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: void FooTestEventListener::OnTestSuiteEnd(const testing::TestSuite &) {}
+
+class BarTestEventListener : public testing::TestEventListener {
+public:
+  using TestEventListener::OnTestCaseStart;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using TestEventListener::OnTestSuiteStart;
+  using TestEventListener::OnTestCaseEnd;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using TestEventListener::OnTestSuiteEnd;
+};
+
+class BarTestEventListener2 : public BarTestEventListener {
+public:
+  using BarTestEventListener::OnTestCaseStart;
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarTestEventListener::OnTestSuiteStart;
+  using BarTestEventListener::OnTestCaseEnd;
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarTestEventListener::OnTestSuiteEnd;
+};
+
+#ifndef NOSUITE
+
+class BarTestEventListener3 : public testing::TestEventListener {
+public:
+  void OnTestCaseStart(const testing::TestSuite &) override;
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+  void OnTestSuiteStart(const testing::TestSuite &) override;
+
+  void OnTestCaseEnd(const testing::TestSuite &) override;
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case'
+  void OnTestSuiteEnd(const testing::TestSuite &) override;
+};
+
+#endif
+
+namespace nesting_ns {
+namespace testing {
+
+class TestEventListener {
+public:
+  virtual void OnTestCaseStart(const ::testing::TestCase &);
+  // CHECK-MESSAGES: [[@LINE-1]]:49: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: virtual void OnTestCaseStart(const ::testing::TestSuite &);
+  virtual void OnTestCaseEnd(const ::testing::TestCase &);
+  // CHECK-MESSAGES: [[@LINE-1]]:47: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: virtual void OnTestCaseEnd(const ::testing::TestSuite &);
+};
+
+} // namespace testing
+
+void FuncTestEventListener(::testing::TestCase &Case) {
+  // CHECK-MESSAGES: [[@LINE-1]]:39: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: void FuncTestEventListener(::testing::TestSuite &Case) {
+  testing::TestEventListener().OnTestCaseStart(Case);
+  testing::TestEventListener().OnTestCaseEnd(Case);
+}
+
+} // namespace nesting_ns
+
+#ifndef NOSUITE
+
+template <typename T>
+void testEventListenerInstantiationOnlyWarns() {
+  T().OnTestCaseStart(testing::TestSuite());
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  T().OnTestCaseEnd(testing::TestSuite());
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+}
+
+#endif
+
+#define ON_TEST_CASE_START_MACRO_REPLACE OnTestCaseStart
+#define ON_TEST_CASE_START_MACRO_WARN_ONLY                                     \
+  testing::TestEventListener().OnTestCaseStart
+
+#define ON_TEST_CASE_END_MACRO_REPLACE OnTestCaseEnd
+#define ON_TEST_CASE_END_MACRO_WARN_ONLY                                       \
+  testing::TestEventListener().OnTestCaseEnd
+
+void testEventListenerCallAndReference(testing::TestCase &Case) {
+  // CHECK-MESSAGES: [[@LINE-1]]:49: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: void testEventListenerCallAndReference(testing::TestSuite &Case) {
+  testing::TestEventListener().OnTestCaseStart(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestEventListener().OnTestSuiteStart(Case);
+  testing::TestEventListener().OnTestCaseEnd(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestEventListener().OnTestSuiteEnd(Case);
+
+  FooTestEventListener().OnTestCaseStart(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: FooTestEventListener().OnTestSuiteStart(Case);
+  FooTestEventListener().OnTestCaseEnd(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: FooTestEventListener().OnTestSuiteEnd(Case);
+
+  auto F1 = &testing::TestEventListener::OnTestCaseStart;
+  // CHECK-MESSAGES: [[@LINE-1]]:42: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F1 = &testing::TestEventListener::OnTestSuiteStart;
+  F1 = &testing::TestEventListener::OnTestCaseEnd;
+  // CHECK-MESSAGES: [[@LINE-1]]:37: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: F1 = &testing::TestEventListener::OnTestSuiteEnd;
+
+  auto F2 = &FooTestEventListener::OnTestCaseStart;
+  // CHECK-MESSAGES: [[@LINE-1]]:36: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F2 = &FooTestEventListener::OnTestSuiteStart;
+  F2 = &FooTestEventListener::OnTestCaseEnd;
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: F2 = &FooTestEventListener::OnTestSuiteEnd;
+
+#ifndef NOSUITE
+
+  BarTestEventListener3().OnTestCaseStart(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: BarTestEventListener3().OnTestSuiteStart(Case);
+  BarTestEventListener3().OnTestCaseEnd(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: BarTestEventListener3().OnTestSuiteEnd(Case);
+
+  testEventListenerInstantiationOnlyWarns<testing::TestEventListener>();
+
+#endif
+
+  testing::TestEventListener().ON_TEST_CASE_START_MACRO_REPLACE(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestEventListener().OnTestSuiteStart(Case);
+  ON_TEST_CASE_START_MACRO_WARN_ONLY(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+
+  testing::TestEventListener().ON_TEST_CASE_END_MACRO_REPLACE(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestEventListener().OnTestSuiteEnd(Case);
+  ON_TEST_CASE_END_MACRO_WARN_ONLY(Case);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+}
+
+// ----------------------------------------------------------------------------
+// testing::UnitTest
+
+class FooUnitTest : public testing::UnitTest {
+public:
+  testing::TestCase *current_test_case() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case'
+  // CHECK-MESSAGES: [[@LINE-2]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestSuite *current_test_suite() const;
+  int successful_test_case_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: int successful_test_suite_count() const;
+  int failed_test_case_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: int failed_test_suite_count() const;
+  int total_test_case_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: int total_test_suite_count() const;
+  int test_case_to_run_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: int test_suite_to_run_count() const;
+  const testing::TestCase *GetTestCase(int) const;
+  // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+  // CHECK-MESSAGES: [[@LINE-2]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const testing::TestSuite *GetTestSuite(int) const;
+};
+
+testing::TestCase *FooUnitTest::current_test_case() const {}
+// CHECK-MESSAGES: [[@LINE-1]]:10: warning: Google Test APIs named with 'case'
+// CHECK-MESSAGES: [[@LINE-2]]:33: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: testing::TestSuite *FooUnitTest::current_test_suite() const {}
+int FooUnitTest::successful_test_case_count() const {}
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: int FooUnitTest::successful_test_suite_count() const {}
+int FooUnitTest::failed_test_case_count() const {}
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: int FooUnitTest::failed_test_suite_count() const {}
+int FooUnitTest::total_test_case_count() const {}
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: int FooUnitTest::total_test_suite_count() const {}
+int FooUnitTest::test_case_to_run_count() const {}
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: int FooUnitTest::test_suite_to_run_count() const {}
+const testing::TestCase *FooUnitTest::GetTestCase(int) const {}
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: Google Test APIs named with 'case'
+// CHECK-MESSAGES: [[@LINE-2]]:39: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: const testing::TestSuite *FooUnitTest::GetTestSuite(int) const {}
+
+// Type derived from testing::TestCase
+class BarUnitTest : public testing::UnitTest {
+public:
+  using testing::UnitTest::current_test_case;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using testing::UnitTest::current_test_suite;
+  using testing::UnitTest::successful_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using testing::UnitTest::successful_test_suite_count;
+  using testing::UnitTest::failed_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using testing::UnitTest::failed_test_suite_count;
+  using testing::UnitTest::total_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using testing::UnitTest::total_test_suite_count;
+  using testing::UnitTest::test_case_to_run_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using testing::UnitTest::test_suite_to_run_count;
+  using testing::UnitTest::GetTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using testing::UnitTest::GetTestSuite;
+};
+
+class BarUnitTest2 : public BarUnitTest {
+  using BarUnitTest::current_test_case;
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarUnitTest::current_test_suite;
+  using BarUnitTest::successful_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarUnitTest::successful_test_suite_count;
+  using BarUnitTest::failed_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarUnitTest::failed_test_suite_count;
+  using BarUnitTest::total_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarUnitTest::total_test_suite_count;
+  using BarUnitTest::test_case_to_run_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarUnitTest::test_suite_to_run_count;
+  using BarUnitTest::GetTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: using BarUnitTest::GetTestSuite;
+};
+
+#ifndef NOSUITE
+
+class BarUnitTest3 : public testing::UnitTest {
+  testing::TestSuite *current_test_case() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  int successful_test_case_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  int failed_test_case_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  int total_test_case_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  int test_case_to_run_count() const;
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  const testing::TestSuite *GetTestCase(int) const;
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+
+  testing::TestSuite *current_test_suite() const;
+  int successful_test_suite_count() const;
+  int failed_test_suite_count() const;
+  int total_test_suite_count() const;
+  int test_suite_to_run_count() const;
+  const testing::TestSuite *GetTestSuite(int) const;
+};
+
+#endif
+
+namespace nesting_ns {
+namespace testing {
+
+class TestSuite;
+
+class UnitTest {
+public:
+  TestSuite *current_test_case() const;
+  int successful_test_case_count() const;
+  int failed_test_case_count() const;
+  int total_test_case_count() const;
+  int test_case_to_run_count() const;
+  const TestSuite *GetTestCase(int) const;
+};
+
+} // namespace testing
+
+void FuncUnitTest() {
+  testing::UnitTest t;
+  (void)t.current_test_case();
+  (void)t.successful_test_case_count();
+  (void)t.failed_test_case_count();
+  (void)t.total_test_case_count();
+  (void)t.test_case_to_run_count();
+  (void)t.GetTestCase(0);
+}
+
+} // namespace nesting_ns
+
+template <typename T>
+void unitTestInstantiationOnlyWarns() {
+  T t;
+  (void)t.current_test_case();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+  (void)t.successful_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+  (void)t.failed_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+  (void)t.total_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+  (void)t.test_case_to_run_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+  (void)t.GetTestCase(0);
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+}
+
+#define UNIT_TEST_NAME_MACRO_REPLACE1 current_test_case
+#define UNIT_TEST_NAME_MACRO_REPLACE2 successful_test_case_count
+#define UNIT_TEST_NAME_MACRO_REPLACE3 failed_test_case_count
+#define UNIT_TEST_NAME_MACRO_REPLACE4 total_test_case_count
+#define UNIT_TEST_NAME_MACRO_REPLACE5 test_case_to_run_count
+#define UNIT_TEST_NAME_MACRO_REPLACE6 GetTestCase
+#define UNIT_TEST_NAME_MACRO_WARN_ONLY1 testing::UnitTest().current_test_case
+#define UNIT_TEST_NAME_MACRO_WARN_ONLY2                                        \
+  testing::UnitTest().successful_test_case_count
+#define UNIT_TEST_NAME_MACRO_WARN_ONLY3                                        \
+  testing::UnitTest().failed_test_case_count
+#define UNIT_TEST_NAME_MACRO_WARN_ONLY4                                        \
+  testing::UnitTest().total_test_case_count
+#define UNIT_TEST_NAME_MACRO_WARN_ONLY5                                        \
+  testing::UnitTest().test_case_to_run_count
+#define UNIT_TEST_NAME_MACRO_WARN_ONLY6 testing::UnitTest().GetTestCase
+
+void unitTestCallAndReference() {
+  (void)testing::UnitTest().current_test_case();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().current_test_suite();
+  (void)testing::UnitTest().successful_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().successful_test_suite_count();
+  (void)testing::UnitTest().failed_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().failed_test_suite_count();
+  (void)testing::UnitTest().total_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().total_test_suite_count();
+  (void)testing::UnitTest().test_case_to_run_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().test_suite_to_run_count();
+  (void)testing::UnitTest().GetTestCase(0);
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().GetTestSuite(0);
+
+  (void)FooUnitTest().current_test_case();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)FooUnitTest().current_test_suite();
+  (void)FooUnitTest().successful_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)FooUnitTest().successful_test_suite_count();
+  (void)FooUnitTest().failed_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)FooUnitTest().failed_test_suite_count();
+  (void)FooUnitTest().total_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)FooUnitTest().total_test_suite_count();
+  (void)FooUnitTest().test_case_to_run_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)FooUnitTest().test_suite_to_run_count();
+  (void)FooUnitTest().GetTestCase(0);
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)FooUnitTest().GetTestSuite(0);
+
+  auto U1 = &testing::UnitTest::current_test_case;
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto U1 = &testing::UnitTest::current_test_suite;
+  auto U2 = &testing::UnitTest::successful_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto U2 = &testing::UnitTest::successful_test_suite_count;
+  auto U3 = &testing::UnitTest::failed_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto U3 = &testing::UnitTest::failed_test_suite_count;
+  auto U4 = &testing::UnitTest::total_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto U4 = &testing::UnitTest::total_test_suite_count;
+  auto U5 = &testing::UnitTest::test_case_to_run_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto U5 = &testing::UnitTest::test_suite_to_run_count;
+  auto U6 = &testing::UnitTest::GetTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto U6 = &testing::UnitTest::GetTestSuite;
+
+  auto F1 = &FooUnitTest::current_test_case;
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F1 = &FooUnitTest::current_test_suite;
+  auto F2 = &FooUnitTest::successful_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F2 = &FooUnitTest::successful_test_suite_count;
+  auto F3 = &FooUnitTest::failed_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F3 = &FooUnitTest::failed_test_suite_count;
+  auto F4 = &FooUnitTest::total_test_case_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F4 = &FooUnitTest::total_test_suite_count;
+  auto F5 = &FooUnitTest::test_case_to_run_count;
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F5 = &FooUnitTest::test_suite_to_run_count;
+  auto F6 = &FooUnitTest::GetTestCase;
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: auto F6 = &FooUnitTest::GetTestSuite;
+
+  using MyUnitTest = testing::UnitTest;
+  (void)MyUnitTest().current_test_case();
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)MyUnitTest().current_test_suite();
+  (void)MyUnitTest().successful_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)MyUnitTest().successful_test_suite_count();
+  (void)MyUnitTest().failed_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)MyUnitTest().failed_test_suite_count();
+  (void)MyUnitTest().total_test_case_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)MyUnitTest().total_test_suite_count();
+  (void)MyUnitTest().test_case_to_run_count();
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)MyUnitTest().test_suite_to_run_count();
+  (void)MyUnitTest().GetTestCase(0);
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)MyUnitTest().GetTestSuite(0);
+
+  unitTestInstantiationOnlyWarns<testing::UnitTest>();
+
+  (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE1();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().current_test_suite();
+  (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE2();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().successful_test_suite_count();
+  (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE3();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().failed_test_suite_count();
+  (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE4();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().total_test_suite_count();
+  (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE5();
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().test_suite_to_run_count();
+  (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE6(0);
+  // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)testing::UnitTest().GetTestSuite(0);
+
+  UNIT_TEST_NAME_MACRO_WARN_ONLY1();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+  UNIT_TEST_NAME_MACRO_WARN_ONLY2();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+  UNIT_TEST_NAME_MACRO_WARN_ONLY3();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+  UNIT_TEST_NAME_MACRO_WARN_ONLY4();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+  UNIT_TEST_NAME_MACRO_WARN_ONLY5();
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+  UNIT_TEST_NAME_MACRO_WARN_ONLY6(0);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+}
+
+// ----------------------------------------------------------------------------
+// testing::TestCase
+
+template <typename T>
+void TestCaseInTemplate() {
+  T t;
+
+  testing::TestCase Case;
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestSuite Case;
+}
+
+#define TEST_CASE_CAN_FIX TestCase
+#define TEST_CASE_WARN_ONLY testing::TestCase
+
+const testing::TestCase *testCaseUses(const testing::TestCase &Case) {
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: Google Test APIs named with 'case'
+  // CHECK-MESSAGES: [[@LINE-2]]:54: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const testing::TestSuite *testCaseUses(const testing::TestSuite &Case) {
+
+  // No change for implicit declarations:
+  auto Lambda = [&Case]() {};
+
+  TestCaseInTemplate<testing::TestCase>();
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: TestCaseInTemplate<testing::TestSuite>();
+
+  testing::TEST_CASE_CAN_FIX C1;
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestSuite C1;
+  TEST_CASE_WARN_ONLY C2;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+
+  (void)new testing::TestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)new testing::TestSuite();
+  const testing::TestCase *Result = &Case;
+  // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const testing::TestSuite *Result = &Case;
+  return Result;
+}
+
+struct TestCaseHolder {
+  testing::TestCase Case;
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: testing::TestSuite Case;
+};
+
+class MyTest : public testing::TestCase {};
+// CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: class MyTest : public testing::TestSuite {};
+
+template <typename T = testing::TestCase>
+// CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: template <typename T = testing::TestSuite>
+class TestTypeHolder {};
+
+template <>
+class TestTypeHolder<testing::TestCase> {};
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: class TestTypeHolder<testing::TestSuite> {};
+
+namespace shadow_using_ns {
+
+using testing::TestCase;
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: using testing::TestSuite;
+
+const TestCase *testCaseUses(const TestCase &Case) {
+  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case'
+  // CHECK-MESSAGES: [[@LINE-2]]:36: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const TestSuite *testCaseUses(const TestSuite &Case) {
+
+  // No change for implicit declarations:
+  auto Lambda = [&Case]() {};
+
+  (void)new TestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:13: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)new TestSuite();
+  const TestCase *Result = &Case;
+  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const TestSuite *Result = &Case;
+  return Result;
+}
+
+struct TestCaseHolder {
+  TestCase Case;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: TestSuite Case;
+};
+
+class MyTest : public TestCase {};
+// CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: class MyTest : public TestSuite {};
+
+template <typename T = TestCase>
+// CHECK-MESSAGES: [[@LINE-1]]:24: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: template <typename T = TestSuite>
+class TestTypeHolder {};
+
+template <>
+class TestTypeHolder<TestCase> {};
+// CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: class TestTypeHolder<TestSuite> {};
+
+} // namespace shadow_using_ns
+
+const shadow_using_ns::TestCase *shadowTestCaseUses(
+    const shadow_using_ns::TestCase &Case) {
+  // CHECK-MESSAGES: [[@LINE-2]]:24: warning: Google Test APIs named with 'case'
+  // CHECK-MESSAGES: [[@LINE-2]]:28: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const shadow_using_ns::TestSuite *shadowTestCaseUses(
+  // CHECK-FIXES: const shadow_using_ns::TestSuite &Case) {
+
+  // No match for implicit declarations, as in the lambda capture:
+  auto Lambda = [&Case]() {};
+
+  (void)new shadow_using_ns::TestCase();
+  // CHECK-MESSAGES: [[@LINE-1]]:30: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: (void)new shadow_using_ns::TestSuite();
+  const shadow_using_ns::TestCase *Result = &Case;
+  // CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: const shadow_using_ns::TestSuite *Result = &Case;
+  return Result;
+}
+
+struct ShadowTestCaseHolder {
+  shadow_using_ns::TestCase Case;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: Google Test APIs named with 'case'
+  // CHECK-FIXES: shadow_using_ns::TestSuite Case;
+};
+
+class ShadowMyTest : public shadow_using_ns::TestCase {};
+// CHECK-MESSAGES: [[@LINE-1]]:46: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: class ShadowMyTest : public shadow_using_ns::TestSuite {};
+
+template <typename T = shadow_using_ns::TestCase>
+// CHECK-MESSAGES: [[@LINE-1]]:41: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: template <typename T = shadow_using_ns::TestSuite>
+class ShadowTestTypeHolder {};
+
+template <>
+class ShadowTestTypeHolder<shadow_using_ns::TestCase> {};
+// CHECK-MESSAGES: [[@LINE-1]]:45: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: class ShadowTestTypeHolder<shadow_using_ns::TestSuite> {};
+
+namespace typedef_ns {
+
+typedef testing::TestCase MyTestCase;
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: typedef testing::TestSuite MyTestCase;
+
+const MyTestCase *testCaseUses(const MyTestCase &Case) {
+  auto Lambda = [&Case]() {};
+  (void)new MyTestCase();
+  const MyTestCase *Result = &Case;
+  return Result;
+}
+
+struct TestCaseHolder {
+  MyTestCase Case;
+};
+
+class MyTest : public MyTestCase {};
+
+template <typename T = MyTestCase>
+class TestTypeHolder {};
+
+template <>
+class TestTypeHolder<MyTestCase> {};
+
+} // namespace typedef_ns
+
+const typedef_ns::MyTestCase *typedefTestCaseUses(
+    const typedef_ns::MyTestCase &Case) {
+  auto Lambda = [&Case]() {};
+  (void)new typedef_ns::MyTestCase();
+  const typedef_ns::MyTestCase *Result = &Case;
+  return Result;
+}
+
+struct TypedefTestCaseHolder {
+  typedef_ns::MyTestCase Case;
+};
+
+class TypedefMyTest : public typedef_ns::MyTestCase {};
+template <typename T = typedef_ns::MyTestCase> class TypedefTestTypeHolder {};
+template <> class TypedefTestTypeHolder<typedef_ns::MyTestCase> {};
+
+namespace alias_ns {
+
+using MyTestCase = testing::TestCase;
+// CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case'
+// CHECK-FIXES: using MyTestCase = testing::TestSuite;
+
+const MyTestCase *testCaseUses(const MyTestCase &Case) {
+  auto Lambda = [&Case]() {};
+  (void)new MyTestCase();
+  const MyTestCase *Result = &Case;
+  return Result;
+}
+
+struct TestCaseHolder {
+  MyTestCase Case;
+};
+
+class MyTest : public MyTestCase {};
+template <typename T = MyTestCase> class TestTypeHolder {};
+template <> class TestTypeHolder<MyTestCase> {};
+
+} // namespace alias_ns
+
+const alias_ns::MyTestCase *aliasTestCaseUses(
+    const alias_ns::MyTestCase &Case) {
+  auto Lambda = [&Case]() {};
+  (void)new alias_ns::MyTestCase();
+  const alias_ns::MyTestCase *Result = &Case;
+  return Result;
+}
+
+struct AliasTestCaseHolder {
+  alias_ns::MyTestCase Case;
+};
+
+class AliasMyTest : public alias_ns::MyTestCase {};
+template <typename T = alias_ns::MyTestCase> class AliasTestTypeHolder {};
+template <> class AliasTestTypeHolder<alias_ns::MyTestCase> {};
+
+template <typename T>
+void templateFunction(const T& t) {
+  (void)t.current_test_case();
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case'
+}
+
+void instantiateTemplateFunction(const testing::UnitTest &Test) {
+  templateFunction(Test);
+}
Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest.h
@@ -0,0 +1,47 @@
+#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_
+#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_
+
+#include "gtest/gtest-typed-test.h"
+
+namespace testing {
+
+class Test {
+public:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+class TestCase {};
+
+class TestInfo {
+public:
+  const char *test_case_name() const;
+};
+
+class TestEventListener {
+public:
+  virtual void OnTestCaseStart(const TestCase &);
+  virtual void OnTestCaseEnd(const TestCase &);
+};
+
+class EmptyTestEventListener : public TestEventListener {
+public:
+  void OnTestCaseStart(const TestCase &) override;
+  void OnTestCaseEnd(const TestCase &) override;
+};
+
+class UnitTest {
+public:
+  static UnitTest *GetInstance();
+
+  TestCase *current_test_case() const;
+  int successful_test_case_count() const;
+  int failed_test_case_count() const;
+  int total_test_case_count() const;
+  int test_case_to_run_count() const;
+  const TestCase *GetTestCase(int) const;
+};
+
+} // namespace testing
+
+#endif // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_
Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest-typed-test.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest-typed-test.h
@@ -0,0 +1,12 @@
+#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_
+#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_
+
+#define TYPED_TEST_CASE(CaseName, Types, ...)
+
+#define TYPED_TEST_CASE_P(SuiteName)
+
+#define REGISTER_TYPED_TEST_CASE_P(SuiteName, ...)
+
+#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, SuiteName, Types, ...)
+
+#endif  // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_
Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest.h
@@ -0,0 +1,66 @@
+#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_
+#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_
+
+#include "gtest/gtest-typed-test.h"
+
+namespace testing {
+
+class Test {
+public:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+
+  static void SetUpTestSuite();
+  static void TearDownTestSuite();
+};
+
+class TestSuite {};
+using TestCase = TestSuite;
+
+class TestInfo {
+public:
+  const char *test_case_name() const;
+
+  const char *test_suite_name() const;
+};
+
+class TestEventListener {
+public:
+  virtual void OnTestCaseStart(const TestCase &);
+  virtual void OnTestCaseEnd(const TestCase &);
+
+  virtual void OnTestSuiteStart(const TestCase &);
+  virtual void OnTestSuiteEnd(const TestCase &);
+};
+
+class EmptyTestEventListener : public TestEventListener {
+public:
+  void OnTestCaseStart(const TestCase &) override;
+  void OnTestCaseEnd(const TestCase &) override;
+
+  void OnTestSuiteStart(const TestCase &) override;
+  void OnTestSuiteEnd(const TestCase &) override;
+};
+
+class UnitTest {
+public:
+  static UnitTest *GetInstance();
+
+  TestCase *current_test_case() const;
+  int successful_test_case_count() const;
+  int failed_test_case_count() const;
+  int total_test_case_count() const;
+  int test_case_to_run_count() const;
+  const TestCase *GetTestCase(int) const;
+
+  TestSuite *current_test_suite() const;
+  int successful_test_suite_count() const;
+  int failed_test_suite_count() const;
+  int total_test_suite_count() const;
+  int test_suite_to_run_count() const;
+  const TestSuite *GetTestSuite(int) const;
+};
+
+} // namespace testing
+
+#endif // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_
Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest-typed-test.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest-typed-test.h
@@ -0,0 +1,16 @@
+#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_
+#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_
+
+#define TYPED_TEST_SUITE(CaseName, Types, ...)
+#define TYPED_TEST_CASE TYPED_TEST_SUITE
+
+#define TYPED_TEST_SUITE_P(SuiteName)
+#define TYPED_TEST_CASE_P TYPED_TEST_SUITE_P
+
+#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...)
+#define REGISTER_TYPED_TEST_CASE_P REGISTER_TYPED_TEST_SUITE_P
+
+#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...)
+#define INSTANTIATE_TYPED_TEST_CASE_P INSTANTIATE_TYPED_TEST_SUITE_P
+
+#endif  // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -149,6 +149,7 @@
    google-runtime-int
    google-runtime-operator
    google-runtime-references
+   google-upgrade-googletest-case
    hicpp-avoid-c-arrays (redirects to modernize-avoid-c-arrays) <hicpp-avoid-c-arrays>
    hicpp-avoid-goto
    hicpp-braces-around-statements (redirects to readability-braces-around-statements) <hicpp-braces-around-statements>
Index: clang-tools-extra/docs/clang-tidy/checks/google-upgrade-googletest-case.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-upgrade-googletest-case.rst
@@ -0,0 +1,53 @@
+.. title:: clang-tidy - google-upgrade-googletest-case
+
+google-upgrade-googletest-case
+==============================
+
+Finds uses of deprecated Google Test version 1.9 APIs with names containing
+``case`` and replaces them with equivalent APIs with ``suite``.
+
+All names containing ``case`` are being replaced to be consistent with the
+meanings of "test case" and "test suite" as used by the International
+Software Testing Qualifications Board and ISO 29119.
+
+The new names are a part of Google Test version 1.9 (release pending). It is
+recommended that users update their dependency to version 1.9 and then use this
+check to remove deprecated names.
+
+The affected APIs are:
+
+- Member functions of ``testing::Test``, ``testing::TestInfo``,
+  ``testing::TestEventListener``, ``testing::UnitTest``, and any type inheriting
+  from these types
+- The macros ``TYPED_TEST_CASE``, ``TYPED_TEST_CASE_P``,
+  ``REGISTER_TYPED_TEST_CASE_P``, and ``INSTANTIATE_TYPED_TEST_CASE_P``
+- The type alias ``testing::TestCase``
+
+Examples of fixes created by this check:
+
+.. code-block:: c++
+
+  class FooTest : public testing::Test {
+  public:
+    static void SetUpTestCase();
+    static void TearDownTestCase();
+  };
+
+  TYPED_TEST_CASE(BarTest, BarTypes);
+
+becomes
+
+.. code-block:: c++
+
+  class FooTest : public testing::Test {
+  public:
+    static void SetUpTestSuite();
+    static void TearDownTestSuite();
+  };
+
+  TYPED_TEST_SUITE(BarTest, BarTypes);
+
+For better consistency of user code, the check renames both virtual and
+non-virtual member functions with matching names in derived types. The check
+tries to provide a only warning when a fix cannot be made safely, as is the case
+with some template and macro uses.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -128,6 +128,12 @@
   Checks for calls to ``+new`` or overrides of it, which are prohibited by the
   Google Objective-C style guide.
 
+- New :doc:`google-upgrade-googletest-case
+  <clang-tidy/checks/google-upgrade-googletest-case>` check.
+
+  Finds uses of deprecated Googletest APIs with names containing ``case`` and
+  replaces them with equivalent APIs with ``suite``.
+
 - New :doc:`objc-super-self <clang-tidy/checks/objc-super-self>` check.
 
   Finds invocations of ``-self`` on super instances in initializers of
Index: clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.h
@@ -0,0 +1,40 @@
+//===--- UpgradeGoogletestCaseCheck.h - clang-tidy --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UPGRADEGOOGLETESTCASECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UPGRADEGOOGLETESTCASECHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+
+/// Finds uses of deprecated Googletest APIs with names containing "case" and
+/// replaces them with equivalent names containing "suite".
+///
+/// For the user-facing documentation see:
+/// https://clang.llvm.org/extra/clang-tidy/checks/google-upgrade-googletest-case.html
+class UpgradeGoogletestCaseCheck : public ClangTidyCheck {
+public:
+  UpgradeGoogletestCaseCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+                           Preprocessor *ModuleExpanderPP) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  llvm::DenseSet<unsigned> MatchedTemplateLocations;
+};
+
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UPGRADEGOOGLETESTCASECHECK_H
Index: clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
@@ -0,0 +1,354 @@
+//===--- UpgradeGoogletestCaseCheck.cpp - clang-tidy ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "UpgradeGoogletestCaseCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace google {
+
+static const llvm::StringRef RenameCaseToSuiteMessage =
+    "Google Test APIs named with 'case' are deprecated; use equivalent APIs "
+    "named with 'suite'";
+
+static llvm::Optional<llvm::StringRef>
+getNewMacroName(llvm::StringRef MacroName) {
+  std::pair<llvm::StringRef, llvm::StringRef> ReplacementMap[] = {
+      {"TYPED_TEST_CASE", "TYPED_TEST_SUITE"},
+      {"TYPED_TEST_CASE_P", "TYPED_TEST_SUITE_P"},
+      {"REGISTER_TYPED_TEST_CASE_P", "REGISTER_TYPED_TEST_SUITE_P"},
+      {"INSTANTIATE_TYPED_TEST_CASE_P", "INSTANTIATE_TYPED_TEST_SUITE_P"},
+      {"INSTANTIATE_TEST_CASE_P", "INSTANTIATE_TEST_SUITE_P"},
+  };
+
+  for (auto &Mapping : ReplacementMap) {
+    if (MacroName == Mapping.first)
+      return Mapping.second;
+  }
+
+  return llvm::None;
+}
+
+namespace {
+
+class UpgradeGoogletestCasePPCallback : public PPCallbacks {
+public:
+  UpgradeGoogletestCasePPCallback(UpgradeGoogletestCaseCheck *Check,
+                                  Preprocessor *PP)
+      : ReplacementFound(false), Check(Check), PP(PP) {}
+
+  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+                    SourceRange Range, const MacroArgs *) override {
+    macroUsed(MacroNameTok, MD, Range.getBegin(), CheckAction::Rename);
+  }
+
+  void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
+                      const MacroDirective *Undef) override {
+    if (Undef != nullptr)
+      macroUsed(MacroNameTok, MD, Undef->getLocation(), CheckAction::Warn);
+  }
+
+  void MacroDefined(const Token &MacroNameTok,
+                    const MacroDirective *MD) override {
+    if (!ReplacementFound && MD != nullptr) {
+      // We check if the newly defined macro is one of the target replacements.
+      // This ensures that the check creates warnings only if it is including a
+      // recent enough version of Google Test.
+      llvm::StringRef FileName = PP->getSourceManager().getFilename(
+          MD->getMacroInfo()->getDefinitionLoc());
+      ReplacementFound = FileName.endswith("gtest/gtest-typed-test.h") &&
+                         PP->getSpelling(MacroNameTok) == "TYPED_TEST_SUITE";
+    }
+  }
+
+  void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+               SourceRange Range) override {
+    macroUsed(MacroNameTok, MD, Range.getBegin(), CheckAction::Warn);
+  }
+
+  void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+             const MacroDefinition &MD) override {
+    macroUsed(MacroNameTok, MD, Loc, CheckAction::Warn);
+  }
+
+  void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+              const MacroDefinition &MD) override {
+    macroUsed(MacroNameTok, MD, Loc, CheckAction::Warn);
+  }
+
+private:
+  enum class CheckAction { Warn, Rename };
+
+  void macroUsed(const clang::Token &MacroNameTok, const MacroDefinition &MD,
+                 SourceLocation Loc, CheckAction Action) {
+    if (!ReplacementFound)
+      return;
+
+    std::string Name = PP->getSpelling(MacroNameTok);
+
+    llvm::Optional<llvm::StringRef> Replacement = getNewMacroName(Name);
+    if (!Replacement)
+      return;
+
+    llvm::StringRef FileName = PP->getSourceManager().getFilename(
+        MD.getMacroInfo()->getDefinitionLoc());
+    if (!FileName.endswith("gtest/gtest-typed-test.h"))
+      return;
+
+    DiagnosticBuilder Diag = Check->diag(Loc, RenameCaseToSuiteMessage);
+
+    if (Action == CheckAction::Rename)
+      Diag << FixItHint::CreateReplacement(
+          CharSourceRange::getTokenRange(Loc, Loc), *Replacement);
+  }
+
+  bool ReplacementFound;
+  UpgradeGoogletestCaseCheck *Check;
+  Preprocessor *PP;
+};
+
+} // namespace
+
+void UpgradeGoogletestCaseCheck::registerPPCallbacks(const SourceManager &,
+                                                     Preprocessor *PP,
+                                                     Preprocessor *) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  PP->addPPCallbacks(
+      llvm::make_unique<UpgradeGoogletestCasePPCallback>(this, PP));
+}
+
+void UpgradeGoogletestCaseCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto LocationFilter =
+      unless(isExpansionInFileMatching("gtest/gtest(-typed-test)?\\.h$"));
+
+  // Matchers for the member functions that are being renamed. In each matched
+  // Google Test class, we check for the existence of one new method name. This
+  // makes sure the check gives warnings only if the included version of Google
+  // Test is recent enough.
+  auto Methods =
+      cxxMethodDecl(
+          anyOf(
+              cxxMethodDecl(
+                  hasAnyName("SetUpTestCase", "TearDownTestCase"),
+                  ofClass(
+                      cxxRecordDecl(isSameOrDerivedFrom(cxxRecordDecl(
+                                        hasName("::testing::Test"),
+                                        hasMethod(hasName("SetUpTestSuite")))))
+                          .bind("class"))),
+              cxxMethodDecl(
+                  hasName("test_case_name"),
+                  ofClass(
+                      cxxRecordDecl(isSameOrDerivedFrom(cxxRecordDecl(
+                                        hasName("::testing::TestInfo"),
+                                        hasMethod(hasName("test_suite_name")))))
+                          .bind("class"))),
+              cxxMethodDecl(
+                  hasAnyName("OnTestCaseStart", "OnTestCaseEnd"),
+                  ofClass(cxxRecordDecl(
+                              isSameOrDerivedFrom(cxxRecordDecl(
+                                  hasName("::testing::TestEventListener"),
+                                  hasMethod(hasName("OnTestSuiteStart")))))
+                              .bind("class"))),
+              cxxMethodDecl(
+                  hasAnyName("current_test_case", "successful_test_case_count",
+                             "failed_test_case_count", "total_test_case_count",
+                             "test_case_to_run_count", "GetTestCase"),
+                  ofClass(cxxRecordDecl(
+                              isSameOrDerivedFrom(cxxRecordDecl(
+                                  hasName("::testing::UnitTest"),
+                                  hasMethod(hasName("current_test_suite")))))
+                              .bind("class")))))
+          .bind("method");
+
+  Finder->addMatcher(expr(anyOf(callExpr(callee(Methods)).bind("call"),
+                                declRefExpr(to(Methods)).bind("ref")),
+                          LocationFilter),
+                     this);
+
+  Finder->addMatcher(
+      usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(Methods)), LocationFilter)
+          .bind("using"),
+      this);
+
+  Finder->addMatcher(cxxMethodDecl(Methods, LocationFilter), this);
+
+  // Matchers for `TestCase` -> `TestSuite`. The fact that `TestCase` is an
+  // alias and not a class declaration ensures we only match with a recent
+  // enough version of Google Test.
+  auto TestCaseTypeAlias =
+      typeAliasDecl(hasName("::testing::TestCase")).bind("test-case");
+  Finder->addMatcher(
+      typeLoc(loc(qualType(typedefType(hasDeclaration(TestCaseTypeAlias)))),
+              unless(hasAncestor(decl(isImplicit()))), LocationFilter)
+          .bind("typeloc"),
+      this);
+  Finder->addMatcher(
+      usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(TestCaseTypeAlias)))
+          .bind("using"),
+      this);
+}
+
+static llvm::StringRef getNewMethodName(llvm::StringRef CurrentName) {
+  std::pair<llvm::StringRef, llvm::StringRef> ReplacementMap[] = {
+      {"SetUpTestCase", "SetUpTestSuite"},
+      {"TearDownTestCase", "TearDownTestSuite"},
+      {"test_case_name", "test_suite_name"},
+      {"OnTestCaseStart", "OnTestSuiteStart"},
+      {"OnTestCaseEnd", "OnTestSuiteEnd"},
+      {"current_test_case", "current_test_suite"},
+      {"successful_test_case_count", "successful_test_suite_count"},
+      {"failed_test_case_count", "failed_test_suite_count"},
+      {"total_test_case_count", "total_test_suite_count"},
+      {"test_case_to_run_count", "test_suite_to_run_count"},
+      {"GetTestCase", "GetTestSuite"}};
+
+  for (auto &Mapping : ReplacementMap) {
+    if (CurrentName == Mapping.first)
+      return Mapping.second;
+  }
+
+  llvm_unreachable("Unexpected function name");
+}
+
+template <typename NodeType>
+static bool isInInstantiation(const NodeType &Node,
+                              const MatchFinder::MatchResult &Result) {
+  return !match(isInTemplateInstantiation(), Node, *Result.Context).empty();
+}
+
+template <typename NodeType>
+static bool isInTemplate(const NodeType &Node,
+                         const MatchFinder::MatchResult &Result) {
+  internal::Matcher<NodeType> IsInsideTemplate =
+      hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl())));
+  return !match(IsInsideTemplate, Node, *Result.Context).empty();
+}
+
+static bool
+derivedTypeHasReplacementMethod(const MatchFinder::MatchResult &Result,
+                                llvm::StringRef ReplacementMethod) {
+  const auto *Class = Result.Nodes.getNodeAs<CXXRecordDecl>("class");
+  return !match(cxxRecordDecl(
+                    unless(isExpansionInFileMatching(
+                        "gtest/gtest(-typed-test)?\\.h$")),
+                    hasMethod(cxxMethodDecl(hasName(ReplacementMethod)))),
+                *Class, *Result.Context)
+              .empty();
+}
+
+static CharSourceRange
+getAliasNameRange(const MatchFinder::MatchResult &Result) {
+  if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) {
+    return CharSourceRange::getTokenRange(
+        Using->getNameInfo().getSourceRange());
+  }
+  return CharSourceRange::getTokenRange(
+      Result.Nodes.getNodeAs<TypeLoc>("typeloc")->getSourceRange());
+}
+
+void UpgradeGoogletestCaseCheck::check(const MatchFinder::MatchResult &Result) {
+  llvm::StringRef ReplacementText;
+  CharSourceRange ReplacementRange;
+  if (const auto *Method = Result.Nodes.getNodeAs<CXXMethodDecl>("method")) {
+    ReplacementText = getNewMethodName(Method->getName());
+
+    bool IsInInstantiation;
+    bool IsInTemplate;
+    bool AddFix = true;
+    if (const auto *Call = Result.Nodes.getNodeAs<CXXMemberCallExpr>("call")) {
+      const auto *Callee = llvm::cast<MemberExpr>(Call->getCallee());
+      ReplacementRange = CharSourceRange::getTokenRange(Callee->getMemberLoc(),
+                                                        Callee->getMemberLoc());
+      IsInInstantiation = isInInstantiation(*Call, Result);
+      IsInTemplate = isInTemplate<Stmt>(*Call, Result);
+    } else if (const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("ref")) {
+      ReplacementRange =
+          CharSourceRange::getTokenRange(Ref->getNameInfo().getSourceRange());
+      IsInInstantiation = isInInstantiation(*Ref, Result);
+      IsInTemplate = isInTemplate<Stmt>(*Ref, Result);
+    } else if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) {
+      ReplacementRange =
+          CharSourceRange::getTokenRange(Using->getNameInfo().getSourceRange());
+      IsInInstantiation = isInInstantiation(*Using, Result);
+      IsInTemplate = isInTemplate<Decl>(*Using, Result);
+    } else {
+      // This branch means we have matched a function declaration / definition
+      // either for a function from googletest or for a function in a derived
+      // class.
+
+      ReplacementRange = CharSourceRange::getTokenRange(
+          Method->getNameInfo().getSourceRange());
+      IsInInstantiation = isInInstantiation(*Method, Result);
+      IsInTemplate = isInTemplate<Decl>(*Method, Result);
+
+      // If the type of the matched method is strictly derived from a googletest
+      // type and has both the old and new member function names, then we cannot
+      // safely rename (or delete) the old name version.
+      AddFix = !derivedTypeHasReplacementMethod(Result, ReplacementText);
+    }
+
+    if (IsInInstantiation) {
+      if (MatchedTemplateLocations.count(
+              ReplacementRange.getBegin().getRawEncoding()) == 0) {
+        // For each location matched in a template instantiation, we check if
+        // the location can also be found in `MatchedTemplateLocations`. If it
+        // is not found, that means the expression did not create a match
+        // without the instantiation and depends on template parameters. A
+        // manual fix is probably required so we provide only a warning.
+        diag(ReplacementRange.getBegin(), RenameCaseToSuiteMessage);
+      }
+      return;
+    }
+
+    if (IsInTemplate) {
+      // We gather source locations from template matches not in template
+      // instantiations for future matches.
+      MatchedTemplateLocations.insert(
+          ReplacementRange.getBegin().getRawEncoding());
+    }
+
+    if (!AddFix) {
+      diag(ReplacementRange.getBegin(), RenameCaseToSuiteMessage);
+      return;
+    }
+  } else {
+    // This is a match for `TestCase` to `TestSuite` refactoring.
+    assert(Result.Nodes.getNodeAs<TypeAliasDecl>("test-case") != nullptr);
+    ReplacementText = "TestSuite";
+    ReplacementRange = getAliasNameRange(Result);
+
+    // We do not need to keep track of template instantiations for this branch,
+    // because we are matching a `TypeLoc` for the alias declaration. Templates
+    // will only be instantiated with the true type name, `TestSuite`.
+  }
+
+  DiagnosticBuilder Diag =
+      diag(ReplacementRange.getBegin(), RenameCaseToSuiteMessage);
+
+  ReplacementRange = Lexer::makeFileCharRange(
+      ReplacementRange, *Result.SourceManager, Result.Context->getLangOpts());
+  if (ReplacementRange.isInvalid())
+    // An invalid source range likely means we are inside a macro body. A manual
+    // fix is likely needed so we do not create a fix-it hint.
+    return;
+
+  Diag << FixItHint::CreateReplacement(ReplacementRange, ReplacementText);
+}
+
+} // namespace google
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
+++ clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
@@ -27,6 +27,7 @@
 #include "OverloadedUnaryAndCheck.h"
 #include "TodoCommentCheck.h"
 #include "UnnamedNamespaceInHeaderCheck.h"
+#include "UpgradeGoogletestCaseCheck.h"
 #include "UsingNamespaceDirectiveCheck.h"
 
 using namespace clang::ast_matchers;
@@ -79,6 +80,8 @@
     CheckFactories
         .registerCheck<clang::tidy::readability::NamespaceCommentCheck>(
             "google-readability-namespace-comments");
+    CheckFactories.registerCheck<UpgradeGoogletestCaseCheck>(
+        "google-upgrade-googletest-case");
   }
 
   ClangTidyOptions getModuleOptions() override {
Index: clang-tools-extra/clang-tidy/google/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/google/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/google/CMakeLists.txt
@@ -17,6 +17,7 @@
   OverloadedUnaryAndCheck.cpp
   TodoCommentCheck.cpp
   UnnamedNamespaceInHeaderCheck.cpp
+  UpgradeGoogletestCaseCheck.cpp
   UsingNamespaceDirectiveCheck.cpp
 
   LINK_LIBS
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to