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 
11 namespace clang {
12 namespace clang_rename {
13 namespace test {
14 namespace {
15 
16 class RenameAliasTest : public ClangRenameTest {
17 public:
RenameAliasTest()18   RenameAliasTest() {
19     AppendToHeader(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 
48 INSTANTIATE_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 
TEST_P(RenameAliasTest,RenameAlias)195 TEST_P(RenameAliasTest, RenameAlias) {
196   auto Param = GetParam();
197   assert(!Param.OldName.empty());
198   assert(!Param.NewName.empty());
199   std::string Actual =
200       runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
201   CompareSnippets(Param.After, Actual);
202 }
203 
TEST_F(RenameAliasTest,RenameTypedefDefinitions)204 TEST_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(Before, "TOld", "TNew");
214   CompareSnippets(Expected, After);
215 }
216 
TEST_F(RenameAliasTest,RenameUsingAliasDefinitions)217 TEST_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(Before, "UOld", "UNew");
227   CompareSnippets(Expected, After);
228 }
229 
TEST_F(RenameAliasTest,RenameTemplatedAliasDefinitions)230 TEST_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(Before, "Old", "New");
246   CompareSnippets(Expected, After);
247 }
248 
TEST_F(RenameAliasTest,RenameAliasesInNamespaces)249 TEST_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(Before, "ns::UOld", "ns::UNew");
263   CompareSnippets(Expected, After);
264 }
265 
TEST_F(RenameAliasTest,AliasesInMacros)266 TEST_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(Before, "ns::OldAlias", "ns::NewAlias");
297   CompareSnippets(Expected, After);
298 }
299 
300 } // anonymous namespace
301 } // namespace test
302 } // namespace clang_rename
303 } // namesdpace clang
304