1 | //===-- MemberwiseConstructorTests.cpp ------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "TweakTesting.h" |
10 | #include "gmock/gmock-matchers.h" |
11 | #include "gmock/gmock.h" |
12 | #include "gtest/gtest.h" |
13 | |
14 | namespace clang { |
15 | namespace clangd { |
16 | namespace { |
17 | using testing::AllOf; |
18 | using testing::Eq; |
19 | using testing::HasSubstr; |
20 | using testing::Not; |
21 | |
22 | TWEAK_TEST(MemberwiseConstructor); |
23 | |
24 | TEST_F(MemberwiseConstructorTest, Availability) { |
25 | EXPECT_AVAILABLE("^struct ^S ^{ int x, y; };" ); |
26 | // Verify no crashes on incomplete member fields. |
27 | EXPECT_UNAVAILABLE("/*error-ok*/class Forward; class ^A { Forward f;}" ); |
28 | EXPECT_UNAVAILABLE("struct S { ^int ^x, y; }; struct ^S;" ); |
29 | EXPECT_UNAVAILABLE("struct ^S {};" ); |
30 | EXPECT_UNAVAILABLE("union ^S { int x; };" ); |
31 | EXPECT_UNAVAILABLE("struct ^S { int x = 0; };" ); |
32 | EXPECT_UNAVAILABLE("struct ^S { struct { int x; }; };" ); |
33 | EXPECT_UNAVAILABLE("struct ^{ int x; } e;" ); |
34 | } |
35 | |
36 | TEST_F(MemberwiseConstructorTest, Edits) { |
37 | Header = R"cpp( |
38 | struct Move { |
39 | Move(Move&&) = default; |
40 | Move(const Move&) = delete; |
41 | }; |
42 | struct Copy { |
43 | Copy(Copy&&) = delete; |
44 | Copy(const Copy&); |
45 | }; |
46 | )cpp" ; |
47 | EXPECT_EQ(apply("struct ^S{Move M; Copy C; int I; int J=4;};" ), |
48 | "struct S{" |
49 | "S(Move M, const Copy &C, int I) : M(std::move(M)), C(C), I(I) {}\n" |
50 | "Move M; Copy C; int I; int J=4;};" ); |
51 | } |
52 | |
53 | TEST_F(MemberwiseConstructorTest, FieldTreatment) { |
54 | Header = R"cpp( |
55 | struct MoveOnly { |
56 | MoveOnly(MoveOnly&&) = default; |
57 | MoveOnly(const MoveOnly&) = delete; |
58 | }; |
59 | struct CopyOnly { |
60 | CopyOnly(CopyOnly&&) = delete; |
61 | CopyOnly(const CopyOnly&); |
62 | }; |
63 | struct CopyTrivial { |
64 | CopyTrivial(CopyTrivial&&) = default; |
65 | CopyTrivial(const CopyTrivial&) = default; |
66 | }; |
67 | struct Immovable { |
68 | Immovable(Immovable&&) = delete; |
69 | Immovable(const Immovable&) = delete; |
70 | }; |
71 | template <typename T> |
72 | struct Traits { using Type = typename T::Type; }; |
73 | using IntAlias = int; |
74 | )cpp" ; |
75 | |
76 | auto Fail = Eq(x: "unavailable" ); |
77 | auto Move = HasSubstr(substring: ": Member(std::move(Member))" ); |
78 | auto CopyRef = AllOf(matchers: HasSubstr(substring: "S(const " ), matchers: HasSubstr(substring: ": Member(Member)" )); |
79 | auto Copy = AllOf(matchers: Not(m: HasSubstr(substring: "S(const " )), matchers: HasSubstr(substring: ": Member(Member)" )); |
80 | auto With = [](llvm::StringRef Type) { |
81 | return ("struct ^S { " + Type + " Member; };" ).str(); |
82 | }; |
83 | |
84 | EXPECT_THAT(apply(With("Immovable" )), Fail); |
85 | EXPECT_THAT(apply(With("MoveOnly" )), Move); |
86 | EXPECT_THAT(apply(With("CopyOnly" )), CopyRef); |
87 | EXPECT_THAT(apply(With("CopyTrivial" )), Copy); |
88 | EXPECT_THAT(apply(With("int" )), Copy); |
89 | EXPECT_THAT(apply(With("IntAlias" )), Copy); |
90 | EXPECT_THAT(apply(With("Immovable*" )), Copy); |
91 | EXPECT_THAT(apply(With("Immovable&" )), Copy); |
92 | |
93 | EXPECT_THAT(apply("template <typename T>" + With("T" )), Move); |
94 | EXPECT_THAT(apply("template <typename T>" + With("typename Traits<T>::Type" )), |
95 | Move); |
96 | EXPECT_THAT(apply("template <typename T>" + With("T*" )), Copy); |
97 | } |
98 | |
99 | } // namespace |
100 | } // namespace clangd |
101 | } // namespace clang |
102 | |