1//===-- RenameAliasTest.cpp - unit tests for renaming alias ---------------===//
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 "ClangRenameTest.h"
10
11namespace clang {
12namespace clang_rename {
13namespace test {
14namespace {
15
16class RenameAliasTest : public ClangRenameTest {
17public:
18 RenameAliasTest() {
19 AppendToHeader(Code: R"(
20 #define MACRO(x) x
21 namespace some_ns {
22 class A {
23 public:
24 void foo() {}
25 struct Nested {
26 enum NestedEnum {
27 E1, E2,
28 };
29 };
30 };
31 } // namespace some_ns
32 namespace a {
33 typedef some_ns::A TA;
34 using UA = some_ns::A;
35 } // namespace a
36 namespace b {
37 typedef some_ns::A TA;
38 using UA = some_ns::A;
39 }
40 template <typename T> class ptr {};
41 template <typename T>
42
43 using TPtr = ptr<int>;
44 )");
45 }
46};
47
48INSTANTIATE_TEST_SUITE_P(
49 RenameAliasTests, RenameAliasTest,
50 testing::ValuesIn(std::vector<Case>({
51 // basic functions
52 {"void f(a::TA a1) {}", "void f(b::TB a1) {}", "a::TA", "b::TB"},
53 {"void f(a::UA a1) {}", "void f(b::UB a1) {}", "a::UA", "b::UB"},
54 {"void f(a::TA* a1) {}", "void f(b::TB* a1) {}", "a::TA", "b::TB"},
55 {"void f(a::TA** a1) {}", "void f(b::TB** a1) {}", "a::TA", "b::TB"},
56 {"a::TA f() { return a::TA(); }", "b::TB f() { return b::TB(); }",
57 "a::TA", "b::TB"},
58 {"a::TA f() { return a::UA(); }", "b::TB f() { return a::UA(); }",
59 "a::TA", "b::TB"},
60 {"a::TA f() { return a::UA(); }", "a::TA f() { return b::UB(); }",
61 "a::UA", "b::UB"},
62 {"void f() { a::TA a; }", "void f() { b::TB a; }", "a::TA", "b::TB"},
63 {"void f(const a::TA& a1) {}", "void f(const b::TB& a1) {}", "a::TA",
64 "b::TB"},
65 {"void f(const a::UA& a1) {}", "void f(const b::UB& a1) {}", "a::UA",
66 "b::UB"},
67 {"void f(const a::TA* a1) {}", "void f(const b::TB* a1) {}", "a::TA",
68 "b::TB"},
69 {"namespace a { void f(TA a1) {} }",
70 "namespace a { void f(b::TB a1) {} }", "a::TA", "b::TB"},
71 {"void f(MACRO(a::TA) a1) {}", "void f(MACRO(b::TB) a1) {}", "a::TA",
72 "b::TB"},
73 {"void f(MACRO(a::TA a1)) {}", "void f(MACRO(b::TB a1)) {}", "a::TA",
74 "b::TB"},
75
76 // shorten/add namespace.
77 {"namespace b { void f(a::UA a1) {} }",
78 "namespace b {void f(UB a1) {} }", "a::UA", "b::UB"},
79 {"namespace a { void f(UA a1) {} }",
80 "namespace a {void f(b::UB a1) {} }", "a::UA", "b::UB"},
81
82 // use namespace and typedefs
83 {"struct S { using T = a::TA; T a_; };",
84 "struct S { using T = b::TB; T a_; };", "a::TA", "b::TB"},
85 {"using T = a::TA; T gA;", "using T = b::TB; T gA;", "a::TA", "b::TB"},
86 {"using T = a::UA; T gA;", "using T = b::UB; T gA;", "a::UA", "b::UB"},
87 {"typedef a::TA T; T gA;", "typedef b::TB T; T gA;", "a::TA", "b::TB"},
88 {"typedef a::UA T; T gA;", "typedef b::UB T; T gA;", "a::UA", "b::UB"},
89 {"typedef MACRO(a::TA) T; T gA;", "typedef MACRO(b::TB) T; T gA;",
90 "a::TA", "b::TB"},
91
92 // types in using shadows.
93 {"using a::TA; TA gA;", "using b::TB; b::TB gA;", "a::TA", "b::TB"},
94 {"using a::UA; UA gA;", "using b::UB; b::UB gA;", "a::UA", "b::UB"},
95
96 // struct members and other oddities
97 {"struct S : public a::TA {};", "struct S : public b::TB {};", "a::TA",
98 "b::TB"},
99 {"struct S : public a::UA {};", "struct S : public b::UB {};", "a::UA",
100 "b::UB"},
101 {"struct F { void f(a::TA a1) {} };",
102 "struct F { void f(b::TB a1) {} };", "a::TA", "b::TB"},
103 {"struct F { a::TA a_; };", "struct F { b::TB a_; };", "a::TA",
104 "b::TB"},
105 {"struct F { ptr<a::TA> a_; };", "struct F { ptr<b::TB> a_; };",
106 "a::TA", "b::TB"},
107 {"struct F { ptr<a::UA> a_; };", "struct F { ptr<b::UB> a_; };",
108 "a::UA", "b::UB"},
109
110 // types in nested name specifiers
111 {"void f() { a::TA::Nested ne; }", "void f() { b::TB::Nested ne; }",
112 "a::TA", "b::TB"},
113 {"void f() { a::UA::Nested ne; }", "void f() { b::UB::Nested ne; }",
114 "a::UA", "b::UB"},
115 {"void f() { a::TA::Nested::NestedEnum e; }",
116 "void f() { b::TB::Nested::NestedEnum e; }", "a::TA", "b::TB"},
117 {"void f() { auto e = a::TA::Nested::NestedEnum::E1; }",
118 "void f() { auto e = b::TB::Nested::NestedEnum::E1; }", "a::TA",
119 "b::TB"},
120 {"void f() { auto e = a::TA::Nested::E1; }",
121 "void f() { auto e = b::TB::Nested::E1; }", "a::TA", "b::TB"},
122
123 // templates
124 {"template <typename T> struct Foo { T t; }; void f() { Foo<a::TA> "
125 "foo; }",
126 "template <typename T> struct Foo { T t; }; void f() { Foo<b::TB> "
127 "foo; }",
128 "a::TA", "b::TB"},
129 {"template <typename T> struct Foo { a::TA a; };",
130 "template <typename T> struct Foo { b::TB a; };", "a::TA", "b::TB"},
131 {"template <typename T> void f(T t) {} void g() { f<a::TA>(a::TA()); }",
132 "template <typename T> void f(T t) {} void g() { f<b::TB>(b::TB()); }",
133 "a::TA", "b::TB"},
134 {"template <typename T> void f(T t) {} void g() { f<a::UA>(a::UA()); }",
135 "template <typename T> void f(T t) {} void g() { f<b::UB>(b::UB()); }",
136 "a::UA", "b::UB"},
137 {"template <typename T> int f() { return 1; } template <> int "
138 "f<a::TA>() { return 2; } int g() { return f<a::TA>(); }",
139 "template <typename T> int f() { return 1; } template <> int "
140 "f<b::TB>() { return 2; } int g() { return f<b::TB>(); }",
141 "a::TA", "b::TB"},
142 {"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
143 "auto a = f.template foo<a::TA>(); }",
144 "struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
145 "auto a = f.template foo<b::TB>(); }",
146 "a::TA", "b::TB"},
147 {"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
148 "auto a = f.template foo<a::UA>(); }",
149 "struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
150 "auto a = f.template foo<b::UB>(); }",
151 "a::UA", "b::UB"},
152
153 // The following two templates are distilled from regressions found in
154 // unique_ptr<> and type_traits.h
155 {"template <typename T> struct outer { typedef T type; type Baz(); }; "
156 "outer<a::TA> g_A;",
157 "template <typename T> struct outer { typedef T type; type Baz(); }; "
158 "outer<b::TB> g_A;",
159 "a::TA", "b::TB"},
160 {"template <typename T> struct nested { typedef T type; }; template "
161 "<typename T> struct outer { typename nested<T>::type Foo(); }; "
162 "outer<a::TA> g_A;",
163 "template <typename T> struct nested { typedef T type; }; template "
164 "<typename T> struct outer { typename nested<T>::type Foo(); }; "
165 "outer<b::TB> g_A;",
166 "a::TA", "b::TB"},
167
168 // macros
169 {"#define FOO(T, t) T t\nvoid f() { FOO(a::TA, a1); FOO(a::TA, a2); }",
170 "#define FOO(T, t) T t\nvoid f() { FOO(b::TB, a1); FOO(b::TB, a2); }",
171 "a::TA", "b::TB"},
172 {"#define FOO(n) a::TA n\nvoid f() { FOO(a1); FOO(a2); }",
173 "#define FOO(n) b::TB n\nvoid f() { FOO(a1); FOO(a2); }", "a::TA",
174 "b::TB"},
175 {"#define FOO(n) a::UA n\nvoid f() { FOO(a1); FOO(a2); }",
176 "#define FOO(n) b::UB n\nvoid f() { FOO(a1); FOO(a2); }", "a::UA",
177 "b::UB"},
178
179 // Pointer to member functions
180 {"auto gA = &a::TA::foo;", "auto gA = &b::TB::foo;", "a::TA", "b::TB"},
181 {"using a::TA; auto gA = &TA::foo;",
182 "using b::TB; auto gA = &b::TB::foo;", "a::TA", "b::TB"},
183 {"typedef a::TA T; auto gA = &T::foo;",
184 "typedef b::TB T; auto gA = &T::foo;", "a::TA", "b::TB"},
185 {"auto gA = &MACRO(a::TA)::foo;", "auto gA = &MACRO(b::TB)::foo;",
186 "a::TA", "b::TB"},
187
188 // templated using alias.
189 {"void f(TPtr<int> p) {}", "void f(NewTPtr<int> p) {}", "TPtr",
190 "NewTPtr"},
191 {"void f(::TPtr<int> p) {}", "void f(::NewTPtr<int> p) {}", "TPtr",
192 "NewTPtr"},
193 })));
194
195TEST_P(RenameAliasTest, RenameAlias) {
196 auto Param = GetParam();
197 assert(!Param.OldName.empty());
198 assert(!Param.NewName.empty());
199 std::string Actual =
200 runClangRenameOnCode(Code: Param.Before, OldName: Param.OldName, NewName: Param.NewName);
201 CompareSnippets(Expected: Param.After, Actual);
202}
203
204TEST_F(RenameAliasTest, RenameTypedefDefinitions) {
205 std::string Before = R"(
206 class X {};
207 typedef X TOld;
208 )";
209 std::string Expected = R"(
210 class X {};
211 typedef X TNew;
212 )";
213 std::string After = runClangRenameOnCode(Code: Before, OldName: "TOld", NewName: "TNew");
214 CompareSnippets(Expected, Actual: After);
215}
216
217TEST_F(RenameAliasTest, RenameUsingAliasDefinitions) {
218 std::string Before = R"(
219 class X {};
220 using UOld = X;
221 )";
222 std::string Expected = R"(
223 class X {};
224 using UNew = X;
225 )";
226 std::string After = runClangRenameOnCode(Code: Before, OldName: "UOld", NewName: "UNew");
227 CompareSnippets(Expected, Actual: After);
228}
229
230TEST_F(RenameAliasTest, RenameTemplatedAliasDefinitions) {
231 std::string Before = R"(
232 template <typename T>
233 class X { T t; };
234
235 template <typename T>
236 using Old = X<T>;
237 )";
238 std::string Expected = R"(
239 template <typename T>
240 class X { T t; };
241
242 template <typename T>
243 using New = X<T>;
244 )";
245 std::string After = runClangRenameOnCode(Code: Before, OldName: "Old", NewName: "New");
246 CompareSnippets(Expected, Actual: After);
247}
248
249TEST_F(RenameAliasTest, RenameAliasesInNamespaces) {
250 std::string Before = R"(
251 namespace x { class X {}; }
252 namespace ns {
253 using UOld = x::X;
254 }
255 )";
256 std::string Expected = R"(
257 namespace x { class X {}; }
258 namespace ns {
259 using UNew = x::X;
260 }
261 )";
262 std::string After = runClangRenameOnCode(Code: Before, OldName: "ns::UOld", NewName: "ns::UNew");
263 CompareSnippets(Expected, Actual: After);
264}
265
266TEST_F(RenameAliasTest, AliasesInMacros) {
267 std::string Before = R"(
268 namespace x { class Old {}; }
269 namespace ns {
270 #define REF(alias) alias alias_var;
271
272 #define ALIAS(old) \
273 using old##Alias = x::old; \
274 REF(old##Alias);
275
276 ALIAS(Old);
277
278 OldAlias old_alias;
279 }
280 )";
281 std::string Expected = R"(
282 namespace x { class Old {}; }
283 namespace ns {
284 #define REF(alias) alias alias_var;
285
286 #define ALIAS(old) \
287 using old##Alias = x::old; \
288 REF(old##Alias);
289
290 ALIAS(Old);
291
292 NewAlias old_alias;
293 }
294 )";
295 std::string After =
296 runClangRenameOnCode(Code: Before, OldName: "ns::OldAlias", NewName: "ns::NewAlias");
297 CompareSnippets(Expected, Actual: After);
298}
299
300} // anonymous namespace
301} // namespace test
302} // namespace clang_rename
303} // namesdpace clang
304

source code of clang/unittests/Rename/RenameAliasTest.cpp