| //===-- OverridePureVirtualsTests.cpp ---------------------------*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "TweakTesting.h" |
| #include "gtest/gtest.h" |
| |
| namespace clang { |
| namespace clangd { |
| namespace { |
| |
| class OverridePureVirtualsTests : public TweakTest { |
| protected: |
| OverridePureVirtualsTests() : TweakTest("OverridePureVirtuals") {} |
| }; |
| |
| TEST_F(OverridePureVirtualsTests, MinimalUnavailable) { |
| EXPECT_UNAVAILABLE("class ^C {};"); |
| } |
| |
| TEST_F(OverridePureVirtualsTests, MinimalAvailable) { |
| EXPECT_AVAILABLE(R"cpp( |
| class B { public: virtual void Foo() = 0; }; |
| class ^C : public B {}; |
| )cpp"); |
| } |
| |
| TEST_F(OverridePureVirtualsTests, UnavailableWhenOverriden) { |
| EXPECT_UNAVAILABLE( |
| R"cpp( |
| class B { |
| public: |
| virtual void foo() = 0; |
| }; |
| |
| class ^D : public B { |
| public: |
| void foo() override; |
| }; |
| )cpp"); |
| } |
| |
| TEST_F(OverridePureVirtualsTests, AvailabilityNoOverride) { |
| EXPECT_AVAILABLE(R"cpp( |
| class Base { |
| public: |
| virtual ~Base() = default; |
| virtual void F1() = 0; |
| virtual void F2() = 0; |
| }; |
| |
| class ^Derived : public Base { |
| public: |
| }; |
| |
| )cpp"); |
| } |
| |
| TEST_F(OverridePureVirtualsTests, AvailabilityPartiallyOverridden) { |
| EXPECT_AVAILABLE(R"cpp( |
| class Base { |
| public: |
| virtual ~Base() = default; |
| virtual void F1() = 0; |
| virtual void F2() = 0; |
| }; |
| |
| class ^Derived : public Base { |
| public: |
| void F1() override; |
| }; |
| )cpp"); |
| } |
| |
| TEST_F(OverridePureVirtualsTests, EmptyDerivedClass) { |
| const char *Before = R"cpp( |
| class Base { |
| public: |
| virtual ~Base() = default; |
| virtual void F1() = 0; |
| virtual void F2(int P1, const int &P2) = 0; |
| }; |
| |
| class ^Derived : public Base {}; |
| )cpp"; |
| const auto *Expected = R"cpp( |
| class Base { |
| public: |
| virtual ~Base() = default; |
| virtual void F1() = 0; |
| virtual void F2(int P1, const int &P2) = 0; |
| }; |
| |
| class Derived : public Base { |
| public: |
| void F1() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `F1` is not implemented."); |
| } |
| |
| void F2(int P1, const int & P2) override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `F2` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, SingleBaseClassPartiallyImplemented) { |
| auto Applied = apply( |
| R"cpp( |
| class Base { |
| public: |
| virtual ~Base() = default; |
| virtual void F1() = 0; |
| virtual void F2() = 0; |
| }; |
| |
| class ^Derived : public Base { |
| public: |
| void F1() override; |
| }; |
| )cpp"); |
| |
| const auto *Expected = R"cpp( |
| class Base { |
| public: |
| virtual ~Base() = default; |
| virtual void F1() = 0; |
| virtual void F2() = 0; |
| }; |
| |
| class Derived : public Base { |
| public: |
| void F2() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `F2` is not implemented."); |
| } |
| |
| void F1() override; |
| }; |
| )cpp"; |
| EXPECT_EQ(Applied, Expected) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, MultipleDirectBaseClasses) { |
| const char *Before = R"cpp( |
| class Base1 { |
| public: |
| virtual void func1() = 0; |
| }; |
| class Base2 { |
| protected: |
| virtual bool func2(char c) const = 0; |
| }; |
| |
| class ^Derived : public Base1, public Base2 {}; |
| )cpp"; |
| const auto *Expected = R"cpp( |
| class Base1 { |
| public: |
| virtual void func1() = 0; |
| }; |
| class Base2 { |
| protected: |
| virtual bool func2(char c) const = 0; |
| }; |
| |
| class Derived : public Base1, public Base2 { |
| public: |
| void func1() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `func1` is not implemented."); |
| } |
| protected: |
| bool func2(char c) const override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `func2` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, UnnamedParametersInBase) { |
| const char *Before = R"cpp( |
| struct S {}; |
| class Base { |
| public: |
| virtual void func(int, const S&, char*) = 0; |
| }; |
| |
| class ^Derived : public Base {}; |
| )cpp"; |
| |
| const auto *Expected = R"cpp( |
| struct S {}; |
| class Base { |
| public: |
| virtual void func(int, const S&, char*) = 0; |
| }; |
| |
| class Derived : public Base { |
| public: |
| void func(int, const S &, char *) override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `func` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, DiamondInheritance) { |
| const char *Before = R"cpp( |
| class Top { |
| public: |
| virtual ~Top() = default; |
| virtual void diamond_func() = 0; |
| }; |
| class Left : virtual public Top {}; |
| class Right : virtual public Top {}; |
| class ^Bottom : public Left, public Right {}; |
| )cpp"; |
| const auto *Expected = R"cpp( |
| class Top { |
| public: |
| virtual ~Top() = default; |
| virtual void diamond_func() = 0; |
| }; |
| class Left : virtual public Top {}; |
| class Right : virtual public Top {}; |
| class Bottom : public Left, public Right { |
| public: |
| void diamond_func() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `diamond_func` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, MixedAccessSpecifiers) { |
| const char *Before = R"cpp( |
| class Base { |
| public: |
| virtual void pub_func() = 0; |
| virtual void pub_func2(char) const = 0; |
| protected: |
| virtual int prot_func(int x) const = 0; |
| }; |
| |
| class ^Derived : public Base { |
| int member; // Existing member |
| public: |
| Derived(int m) : member(m) {} |
| }; |
| )cpp"; |
| const auto *Expected = R"cpp( |
| class Base { |
| public: |
| virtual void pub_func() = 0; |
| virtual void pub_func2(char) const = 0; |
| protected: |
| virtual int prot_func(int x) const = 0; |
| }; |
| |
| class Derived : public Base { |
| int member; // Existing member |
| public: |
| void pub_func() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `pub_func` is not implemented."); |
| } |
| |
| void pub_func2(char) const override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `pub_func2` is not implemented."); |
| } |
| |
| Derived(int m) : member(m) {} |
| |
| protected: |
| int prot_func(int x) const override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `prot_func` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, OutOfOrderMixedAccessSpecifiers) { |
| const char *Before = R"cpp( |
| class Base { |
| public: |
| virtual void pub_func() = 0; |
| virtual void pub_func2(char) const = 0; |
| protected: |
| virtual int prot_func(int x) const = 0; |
| }; |
| |
| class ^Derived : public Base { |
| int member; // Existing member |
| protected: |
| void foo(); |
| public: |
| Derived(int m) : member(m) {} |
| }; |
| )cpp"; |
| const auto *Expected = R"cpp( |
| class Base { |
| public: |
| virtual void pub_func() = 0; |
| virtual void pub_func2(char) const = 0; |
| protected: |
| virtual int prot_func(int x) const = 0; |
| }; |
| |
| class Derived : public Base { |
| int member; // Existing member |
| protected: |
| int prot_func(int x) const override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `prot_func` is not implemented."); |
| } |
| |
| void foo(); |
| public: |
| void pub_func() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `pub_func` is not implemented."); |
| } |
| |
| void pub_func2(char) const override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `pub_func2` is not implemented."); |
| } |
| |
| Derived(int m) : member(m) {} |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, MultiAccessSpecifiersOverride) { |
| constexpr auto Before = R"cpp( |
| class Base { |
| public: |
| virtual void foo() = 0; |
| protected: |
| virtual void bar() = 0; |
| }; |
| |
| class ^Derived : public Base {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class Base { |
| public: |
| virtual void foo() = 0; |
| protected: |
| virtual void bar() = 0; |
| }; |
| |
| class Derived : public Base { |
| public: |
| void foo() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `foo` is not implemented."); |
| } |
| protected: |
| void bar() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `bar` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, AccessSpecifierAlreadyExisting) { |
| const char *Before = R"cpp( |
| class Base { |
| public: |
| virtual void func1() = 0; |
| }; |
| |
| class ^Derived : public Base { |
| public: |
| }; |
| )cpp"; |
| |
| const auto *Expected = R"cpp( |
| class Base { |
| public: |
| virtual void func1() = 0; |
| }; |
| |
| class Derived : public Base { |
| public: |
| void func1() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `func1` is not implemented."); |
| } |
| |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, ConstexprSpecifier) { |
| ExtraArgs.push_back("-std=c++20"); |
| |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| constexpr virtual int getValue() const = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| constexpr virtual int getValue() const = 0; |
| }; |
| |
| class D : public B { |
| public: |
| constexpr int getValue() const override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `getValue` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, ConstevalSpecifier) { |
| ExtraArgs.push_back("-std=c++20"); |
| |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| virtual consteval float calculate() = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| virtual consteval float calculate() = 0; |
| }; |
| |
| class D : public B { |
| public: |
| consteval float calculate() override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `calculate` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, LValueRefQualifier) { |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| virtual void process() & = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| virtual void process() & = 0; |
| }; |
| |
| class D : public B { |
| public: |
| void process() & override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `process` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, RValueRefQualifier) { |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| virtual bool isValid() && = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| virtual bool isValid() && = 0; |
| }; |
| |
| class D : public B { |
| public: |
| bool isValid() && override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `isValid` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, SimpleTrailingReturnType) { |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| virtual auto getStatus() -> bool = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| virtual auto getStatus() -> bool = 0; |
| }; |
| |
| class D : public B { |
| public: |
| auto getStatus() -> bool override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `getStatus` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, ConstexprLValueRefAndTrailingReturn) { |
| ExtraArgs.push_back("-std=c++20"); |
| |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| constexpr virtual auto getData() & -> const char * = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| constexpr virtual auto getData() & -> const char * = 0; |
| }; |
| |
| class D : public B { |
| public: |
| constexpr auto getData() & -> const char * override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `getData` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, ConstevalRValueRefAndTrailingReturn) { |
| ExtraArgs.push_back("-std=c++20"); |
| |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| virtual consteval auto foo() && -> double = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| virtual consteval auto foo() && -> double = 0; |
| }; |
| |
| class D : public B { |
| public: |
| consteval auto foo() && -> double override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `foo` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, CombinedFeaturesWithTrailingReturnTypes) { |
| ExtraArgs.push_back("-std=c++20"); |
| |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| virtual auto f1() & -> int = 0; |
| constexpr virtual auto f2() && -> int = 0; |
| virtual consteval auto f3() -> int = 0; |
| virtual auto f4() const & -> char = 0; |
| constexpr virtual auto f5() const && -> bool = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| virtual auto f1() & -> int = 0; |
| constexpr virtual auto f2() && -> int = 0; |
| virtual consteval auto f3() -> int = 0; |
| virtual auto f4() const & -> char = 0; |
| constexpr virtual auto f5() const && -> bool = 0; |
| }; |
| |
| class D : public B { |
| public: |
| auto f1() & -> int override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `f1` is not implemented."); |
| } |
| |
| constexpr auto f2() && -> int override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `f2` is not implemented."); |
| } |
| |
| consteval auto f3() -> int override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `f3` is not implemented."); |
| } |
| |
| auto f4() const & -> char override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `f4` is not implemented."); |
| } |
| |
| constexpr auto f5() const && -> bool override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `f5` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| TEST_F(OverridePureVirtualsTests, DefaultParameters) { |
| ExtraArgs.push_back("-std=c++20"); |
| |
| constexpr auto Before = R"cpp( |
| class B { |
| public: |
| virtual void foo(int var = 0) = 0; |
| }; |
| |
| class ^D : public B {}; |
| )cpp"; |
| |
| constexpr auto Expected = R"cpp( |
| class B { |
| public: |
| virtual void foo(int var = 0) = 0; |
| }; |
| |
| class D : public B { |
| public: |
| void foo(int var = 0) override { |
| // TODO: Implement this pure virtual method. |
| static_assert(false, "Method `foo` is not implemented."); |
| } |
| }; |
| )cpp"; |
| auto Applied = apply(Before); |
| EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; |
| } |
| |
| } // namespace |
| } // namespace clangd |
| } // namespace clang |