0
0
mirror of https://github.com/llvm/llvm-project.git synced 2025-04-21 15:56:53 +00:00

Remove clang-rename ()

clang-rename has largely been superseded by clangd and this project
hasn't received much attention in many years. Further, our
documentation on it still claims it's in very early stages of
development despite being ~10 years old. One of the primary people
driving the tool has mentioned that they don't believe there is a
reason to continue to support it unless it's still being actively
used (https://reviews.llvm.org/D148439#4303202) and I've found no
evidence to suggest that is the case.

Original RFC:
https://discourse.llvm.org/t/rfc-time-to-deprecate-remove-clang-rename/70707
This commit is contained in:
Aaron Ballman 2024-09-18 08:25:58 -04:00 committed by GitHub
parent 6b6e2106f9
commit 40c45b6b43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
64 changed files with 3 additions and 3520 deletions

@ -23,7 +23,7 @@ D: clang-tidy
N: Manuel Klimek
E: klimek@google.com
D: clang-rename, all parts of clang-tools-extra not covered by someone else
D: all parts of clang-tools-extra not covered by someone else
N: Sam McCall
E: sammccall@google.com

@ -87,9 +87,6 @@ Improvements to clang-doc
Improvements to clang-query
---------------------------
Improvements to clang-rename
----------------------------
The improvements are...
Improvements to clang-tidy

@ -1,168 +0,0 @@
============
Clang-Rename
============
.. contents::
See also:
.. toctree::
:maxdepth: 1
:program:`clang-rename` is a C++ refactoring tool. Its purpose is to perform
efficient renaming actions in large-scale projects such as renaming classes,
functions, variables, arguments, namespaces etc.
The tool is in a very early development stage, so you might encounter bugs and
crashes. Submitting reports with information about how to reproduce the issue
to `the LLVM bugtracker <https://bugs.llvm.org>`_ will definitely help the
project. If you have any ideas or suggestions, you might want to put a feature
request there.
Using Clang-Rename
==================
:program:`clang-rename` is a `LibTooling
<https://clang.llvm.org/docs/LibTooling.html>`_-based tool, and it's easier to
work with if you set up a compile command database for your project (for an
example of how to do this see `How To Setup Tooling For LLVM
<https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>`_). You can also
specify compilation options on the command line after `--`:
.. code-block:: console
$ clang-rename -offset=42 -new-name=foo test.cpp -- -Imy_project/include -DMY_DEFINES ...
To get an offset of a symbol in a file run
.. code-block:: console
$ grep -FUbo 'foo' file.cpp
The tool currently supports renaming actions inside a single translation unit
only. It is planned to extend the tool's functionality to support multi-TU
renaming actions in the future.
:program:`clang-rename` also aims to be easily integrated into popular text
editors, such as Vim and Emacs, and improve the workflow of users.
Although a command line interface exists, it is highly recommended to use the
text editor interface instead for better experience.
You can also identify one or more symbols to be renamed by giving the fully
qualified name:
.. code-block:: console
$ clang-rename -qualified-name=foo -new-name=bar test.cpp
Renaming multiple symbols at once is supported, too. However,
:program:`clang-rename` doesn't accept both `-offset` and `-qualified-name` at
the same time. So, you can either specify multiple `-offset` or
`-qualified-name`.
.. code-block:: console
$ clang-rename -offset=42 -new-name=bar1 -offset=150 -new-name=bar2 test.cpp
or
.. code-block:: console
$ clang-rename -qualified-name=foo1 -new-name=bar1 -qualified-name=foo2 -new-name=bar2 test.cpp
Alternatively, {offset | qualified-name} / new-name pairs can be put into a YAML
file:
.. code-block:: yaml
---
- Offset: 42
NewName: bar1
- Offset: 150
NewName: bar2
...
or
.. code-block:: yaml
---
- QualifiedName: foo1
NewName: bar1
- QualifiedName: foo2
NewName: bar2
...
That way you can avoid spelling out all the names as command line arguments:
.. code-block:: console
$ clang-rename -input=test.yaml test.cpp
:program:`clang-rename` offers the following options:
.. code-block:: console
$ clang-rename --help
USAGE: clang-rename [subcommand] [options] <source0> [... <sourceN>]
OPTIONS:
Generic Options:
-help - Display available options (-help-hidden for more)
-help-list - Display list of available options (-help-list-hidden for more)
-version - Display the version of this program
clang-rename common options:
-export-fixes=<filename> - YAML file to store suggested fixes in.
-extra-arg=<string> - Additional argument to append to the compiler command line
Can be used several times.
-extra-arg-before=<string> - Additional argument to prepend to the compiler command line
Can be used several times.
-force - Ignore nonexistent qualified names.
-i - Overwrite edited <file>s.
-input=<string> - YAML file to load oldname-newname pairs from.
-new-name=<string> - The new name to change the symbol to.
-offset=<uint> - Locates the symbol by offset as opposed to <line>:<column>.
-p <string> - Build path
-pl - Print the locations affected by renaming to stderr.
-pn - Print the found symbol's name prior to renaming to stderr.
-qualified-name=<string> - The fully qualified name of the symbol.
Vim Integration
===============
You can call :program:`clang-rename` directly from Vim! To set up
:program:`clang-rename` integration for Vim see
`clang/tools/clang-rename/clang-rename.py
<https://github.com/llvm/llvm-project/blob/main/clang/tools/clang-rename/clang-rename.py>`_.
Please note that **you have to save all buffers, in which the replacement will
happen before running the tool**.
Once installed, you can point your cursor to symbols you want to rename, press
`<leader>cr` and type new desired name. The `<leader> key
<http://vim.wikia.com/wiki/Mapping_keys_in_Vim_-_Tutorial_(Part_3)#Map_leader>`_
is a reference to a specific key defined by the mapleader variable and is bound
to backslash by default.
Emacs Integration
=================
You can also use :program:`clang-rename` while using Emacs! To set up
:program:`clang-rename` integration for Emacs see
`clang-rename/tool/clang-rename.el
<https://github.com/llvm/llvm-project/blob/main/clang/tools/clang-rename/clang-rename.el>`_.
Once installed, you can point your cursor to symbols you want to rename, press
`M-X`, type `clang-rename` and new desired name.
Please note that **you have to save all buffers, in which the replacement will
happen before running the tool**.

@ -19,7 +19,6 @@ Contents
clang-include-fixer
modularize
pp-trace
clang-rename
clangd <https://clangd.llvm.org/>
clang-doc

@ -28,9 +28,6 @@ configure_lit_site_cfg(
)
set(CLANG_TOOLS_TEST_DEPS
# For the clang-apply-replacements test that uses clang-rename.
clang-rename
# For the clang-doc tests that emit bitcode files.
llvm-bcanalyzer

@ -1,11 +0,0 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/fixes
// RUN: cat %s > %t.cpp
// RUN: clang-rename -offset=254 -new-name=Bar -export-fixes=%t/fixes/clang-rename.yaml %t.cpp --
// RUN: clang-apply-replacements %t
// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
class Foo {}; // CHECK: class Bar {};
// Use grep -FUbo 'Foo' <file> to get the correct offset of Cla when changing
// this file.

@ -809,11 +809,6 @@ tree in terms of conformance to :doc:`ClangFormat` as of: March 06, 2022 17:32:2
- `4`
- `0`
- :good:`100%`
* - clang/tools/clang-rename
- `1`
- `1`
- `0`
- :good:`100%`
* - clang/tools/clang-repl
- `1`
- `1`

@ -39,6 +39,8 @@ code bases.
- The ``le32`` and ``le64`` targets have been removed.
- The ``clang-rename`` tool has been removed.
C/C++ Language Potentially Breaking Changes
-------------------------------------------

@ -608,7 +608,6 @@ clang/tools/clang-refactor/ClangRefactor.cpp
clang/tools/clang-refactor/TestSupport.cpp
clang/tools/clang-refactor/TestSupport.h
clang/tools/clang-refactor/ToolRefactoringResultConsumer.h
clang/tools/clang-rename/ClangRename.cpp
clang/tools/clang-repl/ClangRepl.cpp
clang/tools/clang-scan-deps/ClangScanDeps.cpp
clang/tools/clang-shlib/clang-shlib.cpp

@ -72,7 +72,6 @@ list(APPEND CLANG_TEST_DEPS
clang-tblgen
clang-offload-bundler
clang-import-test
clang-rename
clang-refactor
clang-diff
clang-installapi

@ -1,21 +0,0 @@
class Foo /* Test 1 */ {}; // CHECK: class Bar /* Test 1 */ {};
template <typename T>
void func() {}
template <typename T>
class Baz {};
int main() {
func<Foo>(); // CHECK: func<Bar>();
Baz<Foo> /* Test 2 */ obj; // CHECK: Baz<Bar> /* Test 2 */ obj;
return 0;
}
// Test 1.
// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=215 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,10 +0,0 @@
class Foo { // CHECK: class Bar {
};
int main() {
Foo *Pointer = 0; // CHECK: Bar *Pointer = 0;
return 0;
}
// Test 1.
// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s

@ -1,14 +0,0 @@
class Foo /* Test 1 */ { // CHECK: class Bar /* Test 1 */ {
public:
void foo(int x);
};
void Foo::foo(int x) /* Test 2 */ {} // CHECK: void Bar::foo(int x) /* Test 2 */ {}
// Test 1.
// RUN: clang-rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=109 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,11 +0,0 @@
class Foo1 /* Offset 1 */ { // CHECK: class Bar1 /* Offset 1 */ {
};
class Foo2 /* Offset 2 */ { // CHECK: class Bar2 /* Offset 2 */ {
};
// Test 1.
// RUN: clang-rename -offset=6 -new-name=Bar1 -offset=76 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,8 +0,0 @@
class Foo1 { // CHECK: class Bar1
};
class Foo2 { // CHECK: class Bar2
};
// Test 1.
// RUN: clang-rename -qualified-name=Foo1 -new-name=Bar1 -qualified-name=Foo2 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s

@ -1,47 +0,0 @@
struct A {
virtual void foo() {} /* Test 1 */ // CHECK: virtual void bar() {}
};
struct B : A {
void foo() override {} /* Test 2 */ // CHECK: void bar() override {}
};
struct C : B {
void foo() override {} /* Test 3 */ // CHECK: void bar() override {}
};
struct D : B {
void foo() override {} /* Test 4 */ // CHECK: void bar() override {}
};
struct E : D {
void foo() override {} /* Test 5 */ // CHECK: void bar() override {}
};
int main() {
A a;
a.foo(); // CHECK: a.bar();
B b;
b.foo(); // CHECK: b.bar();
C c;
c.foo(); // CHECK: c.bar();
D d;
d.foo(); // CHECK: d.bar();
E e;
e.foo(); // CHECK: e.bar();
return 0;
}
// Test 1.
// RUN: clang-rename -offset=26 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=109 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=201 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 4.
// RUN: clang-rename -offset=293 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 5.
// RUN: clang-rename -offset=385 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'foo.*' <file>

@ -1,63 +0,0 @@
// Forward declaration.
class Foo; /* Test 1 */ // CHECK: class Bar; /* Test 1 */
class Baz {
virtual int getValue() const = 0;
};
class Foo : public Baz { /* Test 2 */// CHECK: class Bar : public Baz {
public:
Foo(int value = 0) : x(value) {} // CHECK: Bar(int value = 0) : x(value) {}
Foo &operator++(int) { // CHECK: Bar &operator++(int) {
x++;
return *this;
}
bool operator<(Foo const &rhs) { // CHECK: bool operator<(Bar const &rhs) {
return this->x < rhs.x;
}
int getValue() const {
return 0;
}
private:
int x;
};
int main() {
Foo *Pointer = 0; // CHECK: Bar *Pointer = 0;
Foo Variable = Foo(10); // CHECK: Bar Variable = Bar(10);
for (Foo it; it < Variable; it++) { // CHECK: for (Bar it; it < Variable; it++) {
}
const Foo *C = new Foo(); // CHECK: const Bar *C = new Bar();
const_cast<Foo *>(C)->getValue(); // CHECK: const_cast<Bar *>(C)->getValue();
Foo foo; // CHECK: Bar foo;
const Baz &BazReference = foo;
const Baz *BazPointer = &foo;
dynamic_cast<const Foo &>(BazReference).getValue(); /* Test 3 */ // CHECK: dynamic_cast<const Bar &>(BazReference).getValue();
dynamic_cast<const Foo *>(BazPointer)->getValue(); /* Test 4 */ // CHECK: dynamic_cast<const Bar *>(BazPointer)->getValue();
reinterpret_cast<const Foo *>(BazPointer)->getValue(); /* Test 5 */ // CHECK: reinterpret_cast<const Bar *>(BazPointer)->getValue();
static_cast<const Foo &>(BazReference).getValue(); /* Test 6 */ // CHECK: static_cast<const Bar &>(BazReference).getValue();
static_cast<const Foo *>(BazPointer)->getValue(); /* Test 7 */ // CHECK: static_cast<const Bar *>(BazPointer)->getValue();
return 0;
}
// Test 1.
// RUN: clang-rename -offset=30 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=155 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=1133 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
// Test 4.
// RUN: clang-rename -offset=1266 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
// Test 5.
// RUN: clang-rename -offset=1402 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
// Test 6.
// RUN: clang-rename -offset=1533 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
// Test 7.
// RUN: clang-rename -offset=1665 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,14 +0,0 @@
class Foo { // CHECK: class Bar {
public:
Foo(); /* Test 1 */ // CHECK: Bar();
};
Foo::Foo() /* Test 2 */ {} // CHECK: Bar::Bar() /* Test 2 */ {}
// Test 1.
// RUN: clang-rename -offset=62 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=116 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,17 +0,0 @@
class Baz {};
class Qux {
Baz Foo; /* Test 1 */ // CHECK: Baz Bar;
public:
Qux();
};
Qux::Qux() : Foo() /* Test 2 */ {} // CHECK: Qux::Qux() : Bar() /* Test 2 */ {}
// Test 1.
// RUN: clang-rename -offset=33 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=118 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,24 +0,0 @@
class C {
public:
static int Foo; /* Test 1 */ // CHECK: static int Bar;
};
int foo(int x) { return 0; }
#define MACRO(a) foo(a)
int main() {
C::Foo = 1; /* Test 2 */ // CHECK: C::Bar = 1;
MACRO(C::Foo); // CHECK: MACRO(C::Bar);
int y = C::Foo; /* Test 3 */ // CHECK: int y = C::Bar;
return 0;
}
// Test 1.
// RUN: clang-rename -offset=31 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=152 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=271 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,8 +0,0 @@
class B /* Test 1 */ { // CHECK: class B2 /* Test 1 */ {
};
class D : public B /* Test 1 */ { // CHECK: class D : public B2 /* Test 1 */ {
};
// Test 1.
// RUN: clang-rename -force -qualified-name B -new-name B2 -qualified-name E -new-name E2 %s -- | sed 's,//.*,,' | FileCheck %s

@ -1,4 +0,0 @@
class Foo; // CHECK: class Bar;
Foo *f(); // CHECK: Bar *f();
// RUN: clang-rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s

@ -1,20 +0,0 @@
#define moo foo // CHECK: #define moo macro_function
int foo() /* Test 1 */ { // CHECK: int macro_function() /* Test 1 */ {
return 42;
}
void boo(int value) {}
void qoo() {
foo(); // CHECK: macro_function();
boo(foo()); // CHECK: boo(macro_function());
moo();
boo(moo());
}
// Test 1.
// RUN: clang-rename -offset=68 -new-name=macro_function %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'foo.*' <file>

@ -1,13 +0,0 @@
class A { virtual void foo(); /* Test 1 */ }; // CHECK: class A { virtual void bar();
class B : public A { void foo(); /* Test 2 */ }; // CHECK: class B : public A { void bar();
class C : public B { void foo(); /* Test 3 */ }; // CHECK: class C : public B { void bar();
// Test 1.
// RUN: clang-rename -offset=23 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=116 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=209 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'foo.*' <file>

@ -1,19 +0,0 @@
template <typename T>
void Foo(T t); // CHECK: void Bar(T t);
template <>
void Foo(int a); // CHECK: void Bar(int a);
void test() {
Foo<double>(1); // CHECK: Bar<double>(1);
}
// Test 1.
// RUN: clang-rename -offset=28 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=81 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=137 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,12 +0,0 @@
void foo() {
}
class Foo { // CHECK: class Bar
};
int main() {
Foo *Pointer = 0; // CHECK: Bar *Pointer = 0;
return 0;
}
// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s

@ -1,10 +0,0 @@
#include "Inputs/HeaderWithSymbol.h"
int main() {
return 0; // CHECK: {{^ return 0;}}
}
// Test 1.
// The file IncludeHeaderWithSymbol.cpp doesn't contain the symbol Foo
// and is expected to be written to stdout without modifications
// RUN: clang-rename -qualified-name=Foo -new-name=Bar %s -- | FileCheck %s

@ -1,6 +0,0 @@
---
- Offset: 6
NewName: Bar1
- Offset: 44
NewName: Bar2
...

@ -1,6 +0,0 @@
---
- QualifiedName: Foo1
NewName: Bar1
- QualifiedName: Foo2
NewName: Bar2
...

@ -1,2 +0,0 @@
// RUN: not clang-rename -new-name=class -offset=133 %s 2>&1 | FileCheck %s
// CHECK: ERROR: new name is not a valid identifier in C++17.

@ -1,9 +0,0 @@
#include "Inputs/HeaderWithSymbol.h"
#define FOO int bar;
FOO
int foo;
// RUN: not clang-rename -new-name=qux -offset=259 %s -- 2>&1 | FileCheck %s
// CHECK-NOT: CHECK
// CHECK: error: SourceLocation in file {{.*}}InvalidOffset.cpp at offset 259 is invalid

@ -1,4 +0,0 @@
struct S {
};
// RUN: clang-rename -force -qualified-name S2 -new-name=T %s --

@ -1,22 +0,0 @@
class Baz {
public:
int Foo; /* Test 1 */ // CHECK: int Bar;
};
int qux(int x) { return 0; }
#define MACRO(a) qux(a)
int main() {
Baz baz;
baz.Foo = 1; /* Test 2 */ // CHECK: baz.Bar = 1;
MACRO(baz.Foo); // CHECK: MACRO(baz.Bar);
int y = baz.Foo; // CHECK: int y = baz.Bar;
}
// Test 1.
// RUN: clang-rename -offset=26 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=155 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,13 +0,0 @@
namespace gcc /* Test 1 */ { // CHECK: namespace clang /* Test 1 */ {
int x;
}
void boo() {
gcc::x = 42; // CHECK: clang::x = 42;
}
// Test 1.
// RUN: clang-rename -offset=10 -new-name=clang %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,4 +0,0 @@
// Check for an error while -new-name argument has not been passed to
// clang-rename.
// RUN: not clang-rename -offset=133 %s 2>&1 | FileCheck %s
// CHECK: clang-rename: -new-name must be specified.

@ -1,2 +0,0 @@
// RUN: not clang-rename -offset=0 -new-name=bar non-existing-file 2>&1 | FileCheck %s
// CHECK: clang-rename: non-existing-file does not exist.

@ -1,42 +0,0 @@
template <typename T>
class Foo { /* Test 1 */ // CHECK: class Bar { /* Test 1 */
public:
T foo(T arg, T& ref, T* ptr) {
T value;
int number = 42;
value = (T)number;
value = static_cast<T>(number);
return value;
}
static void foo(T value) {}
T member;
};
template <typename T>
void func() {
Foo<T> obj; /* Test 2 */ // CHECK: Bar<T> obj;
obj.member = T();
Foo<T>::foo(); // CHECK: Bar<T>::foo();
}
int main() {
Foo<int> i; /* Test 3 */ // CHECK: Bar<int> i;
i.member = 0;
Foo<int>::foo(0); // CHECK: Bar<int>::foo(0);
Foo<bool> b; // CHECK: Bar<bool> b;
b.member = false;
Foo<bool>::foo(false); // CHECK: Bar<bool>::foo(false);
return 0;
}
// Test 1.
// RUN: clang-rename -offset=29 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=324 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=463 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,10 +0,0 @@
class Foo { // CHECK: class Bar {
public:
template <typename T>
Foo(); // CHECK: Bar();
template <typename T>
Foo(Foo &); // CHECK: Bar(Bar &);
};
// RUN: clang-rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s

@ -1,24 +0,0 @@
template <typename T /* Test 1 */> // CHECK: template <typename U /* Test 1 */>
class Foo {
T foo(T arg, T& ref, T* /* Test 2 */ ptr) { // CHECK: U foo(U arg, U& ref, U* /* Test 2 */ ptr) {
T value; // CHECK: U value;
int number = 42;
value = (T)number; // CHECK: value = (U)number;
value = static_cast<T /* Test 3 */>(number); // CHECK: value = static_cast<U /* Test 3 */>(number);
return value;
}
static void foo(T value) {} // CHECK: static void foo(U value) {}
T member; // CHECK: U member;
};
// Test 1.
// RUN: clang-rename -offset=19 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=126 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=392 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'T.*' <file>

@ -1,27 +0,0 @@
template <typename T>
class A {
public:
void foo() /* Test 1 */ {} // CHECK: void bar() /* Test 1 */ {}
};
int main(int argc, char **argv) {
A<int> a;
A<double> b;
A<float> c;
a.foo(); /* Test 2 */ // CHECK: a.bar(); /* Test 2 */
b.foo(); /* Test 3 */ // CHECK: b.bar(); /* Test 3 */
c.foo(); /* Test 4 */ // CHECK: c.bar(); /* Test 4 */
return 0;
}
// Test 1.
// RUN: clang-rename -offset=48 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=191 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=255 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 4.
// RUN: clang-rename -offset=319 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'foo.*' <file>

@ -1,8 +0,0 @@
namespace std {
class basic_string {};
typedef basic_string string;
} // namespace std
std::string foo(); // // CHECK: std::new_string foo();
// RUN: clang-rename -offset=93 -new-name=new_string %s -- | sed 's,//.*,,' | FileCheck %s

@ -1,26 +0,0 @@
class Foo { /* Test 1 */ // CHECK: class Bar {
public:
Foo() {} // CHECK: Bar() {}
};
class Baz {
public:
operator Foo() /* Test 2 */ const { // CHECK: operator Bar() /* Test 2 */ const {
Foo foo; // CHECK: Bar foo;
return foo;
}
};
int main() {
Baz boo;
Foo foo = static_cast<Foo>(boo); // CHECK: Bar foo = static_cast<Bar>(boo);
return 0;
}
// Test 1.
// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=164 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,33 +0,0 @@
#define NAMESPACE namespace A
NAMESPACE {
int Foo; /* Test 1 */ // CHECK: int Bar;
}
int Foo; // CHECK: int Foo;
int Qux = Foo; // CHECK: int Qux = Foo;
int Baz = A::Foo; /* Test 2 */ // CHECK: Baz = A::Bar;
void fun() {
struct {
int Foo; // CHECK: int Foo;
} b = {100};
int Foo = 100; // CHECK: int Foo = 100;
Baz = Foo; // CHECK: Baz = Foo;
{
extern int Foo; // CHECK: extern int Foo;
Baz = Foo; // CHECK: Baz = Foo;
Foo = A::Foo /* Test 3 */ + Baz; // CHECK: Foo = A::Bar /* Test 3 */ + Baz;
A::Foo /* Test 4 */ = b.Foo; // CHECK: A::Bar /* Test 4 */ = b.Foo;
}
Foo = b.Foo; // Foo = b.Foo;
}
// Test 1.
// RUN: clang-rename -offset=46 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=234 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=641 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 4.
// RUN: clang-rename -offset=716 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,21 +0,0 @@
#define Baz Foo // CHECK: #define Baz Bar
void foo(int value) {}
void macro() {
int Foo; /* Test 1 */ // CHECK: int Bar;
Foo = 42; /* Test 2 */ // CHECK: Bar = 42;
Baz -= 0;
foo(Foo); /* Test 3 */ // CHECK: foo(Bar);
foo(Baz);
}
// Test 1.
// RUN: clang-rename -offset=88 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=129 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=191 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,32 +0,0 @@
template <typename T, int U>
bool Foo = true; // CHECK: bool Bar = true;
// explicit template specialization
template <>
bool Foo<int, 0> = false; // CHECK: bool Bar<int, 0> = false;
// partial template specialization
template <typename T>
bool Foo<T, 1> = false; // bool Bar<x, 1> = false;
void k() {
// ref to the explicit template specialization
Foo<int, 0>; // CHECK: Bar<int, 0>;
// ref to the primary template.
Foo<double, 2>; // CHECK: Bar<double, 2>;
}
// Test 1.
// RUN: clang-rename -offset=34 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -offset=128 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 3.
// RUN: clang-rename -offset=248 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 4.
// RUN: clang-rename -offset=357 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// Test 5.
// RUN: clang-rename -offset=431 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s
// To find offsets after modifying the file, use:
// grep -Ubo 'Foo.*' <file>

@ -1,10 +0,0 @@
class Foo1 { // CHECK: class Bar1
};
class Foo2 { // CHECK: class Bar2
};
// Test 1.
// RUN: clang-rename -input %S/Inputs/OffsetToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s
// Test 2.
// RUN: clang-rename -input %S/Inputs/QualifiedNameToNewName.yaml %s -- | sed 's,//.*,,' | FileCheck %s

@ -19,7 +19,6 @@ endif()
add_clang_subdirectory(c-index-test)
add_clang_subdirectory(clang-rename)
add_clang_subdirectory(clang-refactor)
# For MinGW we only enable shared library if LLVM_LINK_LLVM_DYLIB=ON.
# Without that option resulting library is too close to 2^16 DLL exports limit.

@ -1,26 +0,0 @@
set(LLVM_LINK_COMPONENTS
Option
Support
)
add_clang_tool(clang-rename
ClangRename.cpp
)
clang_target_link_libraries(clang-rename
PRIVATE
clangBasic
clangFrontend
clangRewrite
clangSerialization
clangTooling
clangToolingCore
clangToolingRefactoring
)
install(FILES clang-rename.py
DESTINATION "${CMAKE_INSTALL_DATADIR}/clang"
COMPONENT clang-rename)
install(FILES clang-rename.el
DESTINATION "${CMAKE_INSTALL_DATADIR}/clang"
COMPONENT clang-rename)

@ -1,242 +0,0 @@
//===--- tools/extra/clang-rename/ClangRename.cpp - Clang rename tool -----===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements a clang-rename tool that automatically finds and
/// renames symbols in C++ code.
///
//===----------------------------------------------------------------------===//
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h"
#include "clang/Tooling/ReplacementsYaml.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
#include <system_error>
using namespace llvm;
using namespace clang;
/// An oldname -> newname rename.
struct RenameAllInfo {
unsigned Offset = 0;
std::string QualifiedName;
std::string NewName;
};
LLVM_YAML_IS_SEQUENCE_VECTOR(RenameAllInfo)
namespace llvm {
namespace yaml {
/// Specialized MappingTraits to describe how a RenameAllInfo is
/// (de)serialized.
template <> struct MappingTraits<RenameAllInfo> {
static void mapping(IO &IO, RenameAllInfo &Info) {
IO.mapOptional("Offset", Info.Offset);
IO.mapOptional("QualifiedName", Info.QualifiedName);
IO.mapRequired("NewName", Info.NewName);
}
};
} // end namespace yaml
} // end namespace llvm
static cl::OptionCategory ClangRenameOptions("clang-rename common options");
static cl::list<unsigned> SymbolOffsets(
"offset",
cl::desc("Locates the symbol by offset as opposed to <line>:<column>."),
cl::cat(ClangRenameOptions));
static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited <file>s."),
cl::cat(ClangRenameOptions));
static cl::list<std::string>
QualifiedNames("qualified-name",
cl::desc("The fully qualified name of the symbol."),
cl::cat(ClangRenameOptions));
static cl::list<std::string>
NewNames("new-name", cl::desc("The new name to change the symbol to."),
cl::cat(ClangRenameOptions));
static cl::opt<bool> PrintName(
"pn",
cl::desc("Print the found symbol's name prior to renaming to stderr."),
cl::cat(ClangRenameOptions));
static cl::opt<bool> PrintLocations(
"pl", cl::desc("Print the locations affected by renaming to stderr."),
cl::cat(ClangRenameOptions));
static cl::opt<std::string>
ExportFixes("export-fixes",
cl::desc("YAML file to store suggested fixes in."),
cl::value_desc("filename"), cl::cat(ClangRenameOptions));
static cl::opt<std::string>
Input("input", cl::desc("YAML file to load oldname-newname pairs from."),
cl::Optional, cl::cat(ClangRenameOptions));
static cl::opt<bool> Force("force",
cl::desc("Ignore nonexistent qualified names."),
cl::cat(ClangRenameOptions));
int main(int argc, const char **argv) {
auto ExpectedParser =
tooling::CommonOptionsParser::create(argc, argv, ClangRenameOptions);
if (!ExpectedParser) {
llvm::errs() << ExpectedParser.takeError();
return 1;
}
tooling::CommonOptionsParser &OP = ExpectedParser.get();
if (!Input.empty()) {
// Populate QualifiedNames and NewNames from a YAML file.
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
llvm::MemoryBuffer::getFile(Input);
if (!Buffer) {
errs() << "clang-rename: failed to read " << Input << ": "
<< Buffer.getError().message() << "\n";
return 1;
}
std::vector<RenameAllInfo> Infos;
llvm::yaml::Input YAML(Buffer.get()->getBuffer());
YAML >> Infos;
for (const auto &Info : Infos) {
if (!Info.QualifiedName.empty())
QualifiedNames.push_back(Info.QualifiedName);
else
SymbolOffsets.push_back(Info.Offset);
NewNames.push_back(Info.NewName);
}
}
// Check the arguments for correctness.
if (NewNames.empty()) {
errs() << "clang-rename: -new-name must be specified.\n\n";
return 1;
}
if (SymbolOffsets.empty() == QualifiedNames.empty()) {
errs() << "clang-rename: -offset and -qualified-name can't be present at "
"the same time.\n";
return 1;
}
// Check if NewNames is a valid identifier in C++17.
LangOptions Options;
Options.CPlusPlus = true;
Options.CPlusPlus17 = true;
IdentifierTable Table(Options);
for (const auto &NewName : NewNames) {
auto NewNameTokKind = Table.get(NewName).getTokenID();
if (!tok::isAnyIdentifier(NewNameTokKind)) {
errs() << "ERROR: new name is not a valid identifier in C++17.\n\n";
return 1;
}
}
if (SymbolOffsets.size() + QualifiedNames.size() != NewNames.size()) {
errs() << "clang-rename: number of symbol offsets(" << SymbolOffsets.size()
<< ") + number of qualified names (" << QualifiedNames.size()
<< ") must be equal to number of new names(" << NewNames.size()
<< ").\n\n";
cl::PrintHelpMessage();
return 1;
}
auto Files = OP.getSourcePathList();
tooling::RefactoringTool Tool(OP.getCompilations(), Files);
tooling::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames, Force);
Tool.run(tooling::newFrontendActionFactory(&FindingAction).get());
const std::vector<std::vector<std::string>> &USRList =
FindingAction.getUSRList();
const std::vector<std::string> &PrevNames = FindingAction.getUSRSpellings();
if (PrintName) {
for (const auto &PrevName : PrevNames) {
outs() << "clang-rename found name: " << PrevName << '\n';
}
}
if (FindingAction.errorOccurred()) {
// Diagnostics are already issued at this point.
return 1;
}
// Perform the renaming.
tooling::RenamingAction RenameAction(NewNames, PrevNames, USRList,
Tool.getReplacements(), PrintLocations);
std::unique_ptr<tooling::FrontendActionFactory> Factory =
tooling::newFrontendActionFactory(&RenameAction);
int ExitCode;
if (Inplace) {
ExitCode = Tool.runAndSave(Factory.get());
} else {
ExitCode = Tool.run(Factory.get());
if (!ExportFixes.empty()) {
std::error_code EC;
llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::OF_None);
if (EC) {
llvm::errs() << "Error opening output file: " << EC.message() << '\n';
return 1;
}
// Export replacements.
tooling::TranslationUnitReplacements TUR;
const auto &FileToReplacements = Tool.getReplacements();
for (const auto &Entry : FileToReplacements)
TUR.Replacements.insert(TUR.Replacements.end(), Entry.second.begin(),
Entry.second.end());
yaml::Output YAML(OS);
YAML << TUR;
OS.close();
return 0;
}
// Write every file to stdout. Right now we just barf the files without any
// indication of which files start where, other than that we print the files
// in the same order we see them.
LangOptions DefaultLangOptions;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
&DiagnosticPrinter, false);
auto &FileMgr = Tool.getFiles();
SourceManager Sources(Diagnostics, FileMgr);
Rewriter Rewrite(Sources, DefaultLangOptions);
Tool.applyAllReplacements(Rewrite);
for (const auto &File : Files) {
auto Entry = FileMgr.getOptionalFileRef(File);
if (!Entry) {
errs() << "clang-rename: " << File << " does not exist.\n";
return 1;
}
const auto ID = Sources.getOrCreateFileID(*Entry, SrcMgr::C_User);
Rewrite.getEditBuffer(ID).write(outs());
}
}
return ExitCode;
}

@ -1,80 +0,0 @@
;;; clang-rename.el --- Renames every occurrence of a symbol found at <offset>. -*- lexical-binding: t; -*-
;; Version: 0.1.0
;; Keywords: tools, c
;;; Commentary:
;; To install clang-rename.el make sure the directory of this file is in your
;; `load-path' and add
;;
;; (require 'clang-rename)
;;
;; to your .emacs configuration.
;;; Code:
(defgroup clang-rename nil
"Integration with clang-rename"
:group 'c)
(defcustom clang-rename-binary "clang-rename"
"Path to clang-rename executable."
:type '(file :must-match t)
:group 'clang-rename)
;;;###autoload
(defun clang-rename (new-name)
"Rename all instances of the symbol at point to NEW-NAME using clang-rename."
(interactive "sEnter a new name: ")
(save-some-buffers :all)
;; clang-rename should not be combined with other operations when undoing.
(undo-boundary)
(let ((output-buffer (get-buffer-create "*clang-rename*")))
(with-current-buffer output-buffer (erase-buffer))
(let ((exit-code (call-process
clang-rename-binary nil output-buffer nil
(format "-offset=%d"
;; clang-rename wants file (byte) offsets, not
;; buffer (character) positions.
(clang-rename--bufferpos-to-filepos
;; Emacs treats one character after a symbol as
;; part of the symbol, but clang-rename doesnt.
;; Use the beginning of the current symbol, if
;; available, to resolve the inconsistency.
(or (car (bounds-of-thing-at-point 'symbol))
(point))
'exact))
(format "-new-name=%s" new-name)
"-i" (buffer-file-name))))
(if (and (integerp exit-code) (zerop exit-code))
;; Success; revert current buffer so it gets the modifications.
(progn
(kill-buffer output-buffer)
(revert-buffer :ignore-auto :noconfirm :preserve-modes))
;; Failure; append exit code to output buffer and display it.
(let ((message (clang-rename--format-message
"clang-rename failed with %s %s"
(if (integerp exit-code) "exit status" "signal")
exit-code)))
(with-current-buffer output-buffer
(insert ?\n message ?\n))
(message "%s" message)
(display-buffer output-buffer))))))
(defalias 'clang-rename--bufferpos-to-filepos
(if (fboundp 'bufferpos-to-filepos)
'bufferpos-to-filepos
;; Emacs 24 doesnt have bufferpos-to-filepos, simulate it using
;; position-bytes.
(lambda (position &optional _quality _coding-system)
(1- (position-bytes position)))))
;; format-message is new in Emacs 25.1. Provide a fallback for older
;; versions.
(defalias 'clang-rename--format-message
(if (fboundp 'format-message) 'format-message 'format))
(provide 'clang-rename)
;;; clang-rename.el ends here

@ -1,70 +0,0 @@
"""
Minimal clang-rename integration with Vim.
Before installing make sure one of the following is satisfied:
* clang-rename is in your PATH
* `g:clang_rename_path` in ~/.vimrc points to valid clang-rename executable
* `binary` in clang-rename.py points to valid to clang-rename executable
To install, simply put this into your ~/.vimrc for python2 support
noremap <leader>cr :pyf <path-to>/clang-rename.py<cr>
For python3 use the following command (note the change from :pyf to :py3f)
noremap <leader>cr :py3f <path-to>/clang-rename.py<cr>
IMPORTANT NOTE: Before running the tool, make sure you saved the file.
All you have to do now is to place a cursor on a variable/function/class which
you would like to rename and press '<leader>cr'. You will be prompted for a new
name if the cursor points to a valid symbol.
"""
from __future__ import absolute_import, division, print_function
import vim
import subprocess
import sys
def main():
binary = "clang-rename"
if vim.eval('exists("g:clang_rename_path")') == "1":
binary = vim.eval("g:clang_rename_path")
# Get arguments for clang-rename binary.
offset = int(vim.eval('line2byte(line("."))+col(".")')) - 2
if offset < 0:
print(
"Couldn't determine cursor position. Is your file empty?", file=sys.stderr
)
return
filename = vim.current.buffer.name
new_name_request_message = "type new name:"
new_name = vim.eval("input('{}\n')".format(new_name_request_message))
# Call clang-rename.
command = [
binary,
filename,
"-i",
"-offset",
str(offset),
"-new-name",
str(new_name),
]
# FIXME: make it possible to run the tool on unsaved file.
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if stderr:
print(stderr)
# Reload all buffers in Vim.
vim.command("checktime")
if __name__ == "__main__":
main()

@ -48,7 +48,6 @@ if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD)
add_subdirectory(libclang)
endif()
add_subdirectory(DirectoryWatcher)
add_subdirectory(Rename)
add_subdirectory(Index)
add_subdirectory(InstallAPI)
add_subdirectory(Serialization)

@ -1,29 +0,0 @@
set(LLVM_LINK_COMPONENTS
FrontendOpenMP
support
)
# We'd like clang/unittests/Tooling/RewriterTestContext.h in the test.
include_directories(${CLANG_SOURCE_DIR})
add_clang_unittest(ClangRenameTests
RenameClassTest.cpp
RenameEnumTest.cpp
RenameAliasTest.cpp
RenameMemberTest.cpp
RenameFunctionTest.cpp
)
clang_target_link_libraries(ClangRenameTests
PRIVATE
clangAST
clangASTMatchers
clangBasic
clangFormat
clangFrontend
clangRewrite
clangSerialization
clangTooling
clangToolingCore
clangToolingRefactoring
)

@ -1,116 +0,0 @@
//===-- ClangRenameTests.cpp - clang-rename unit tests --------------------===//
//
// 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_UNITTESTS_RENAME_CLANGRENAMETEST_H
#define LLVM_CLANG_UNITTESTS_RENAME_CLANGRENAMETEST_H
#include "unittests/Tooling/RewriterTestContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"
#include <memory>
#include <string>
#include <vector>
namespace clang {
namespace clang_rename {
namespace test {
struct Case {
std::string Before;
std::string After;
std::string OldName;
std::string NewName;
};
class ClangRenameTest : public testing::Test,
public testing::WithParamInterface<Case> {
protected:
void AppendToHeader(StringRef Code) { HeaderContent += Code.str(); }
std::string runClangRenameOnCode(llvm::StringRef Code,
llvm::StringRef OldName,
llvm::StringRef NewName) {
std::string NewCode;
llvm::raw_string_ostream(NewCode) << llvm::format(
"#include \"%s\"\n%s", HeaderName.c_str(), Code.str().c_str());
tooling::FileContentMappings FileContents = {{HeaderName, HeaderContent},
{CCName, NewCode}};
clang::RewriterTestContext Context;
Context.createInMemoryFile(HeaderName, HeaderContent);
clang::FileID InputFileID = Context.createInMemoryFile(CCName, NewCode);
tooling::USRFindingAction FindingAction({}, {std::string(OldName)}, false);
std::unique_ptr<tooling::FrontendActionFactory> USRFindingActionFactory =
tooling::newFrontendActionFactory(&FindingAction);
if (!tooling::runToolOnCodeWithArgs(
USRFindingActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
"clang-rename", std::make_shared<PCHContainerOperations>(),
FileContents))
return "";
const std::vector<std::vector<std::string>> &USRList =
FindingAction.getUSRList();
std::vector<std::string> NewNames = {std::string(NewName)};
std::map<std::string, tooling::Replacements> FileToReplacements;
tooling::QualifiedRenamingAction RenameAction(NewNames, USRList,
FileToReplacements);
auto RenameActionFactory = tooling::newFrontendActionFactory(&RenameAction);
if (!tooling::runToolOnCodeWithArgs(
RenameActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
"clang-rename", std::make_shared<PCHContainerOperations>(),
FileContents))
return "";
formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
return Context.getRewrittenText(InputFileID);
}
void CompareSnippets(StringRef Expected, StringRef Actual) {
std::string ExpectedCode;
llvm::raw_string_ostream(ExpectedCode) << llvm::format(
"#include \"%s\"\n%s", HeaderName.c_str(), Expected.str().c_str());
EXPECT_EQ(format(ExpectedCode), format(Actual));
}
std::string format(llvm::StringRef Code) {
tooling::Replacements Replaces = format::reformat(
format::getLLVMStyle(), Code, {tooling::Range(0, Code.size())});
auto ChangedCode = tooling::applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(ChangedCode));
if (!ChangedCode) {
llvm::errs() << llvm::toString(ChangedCode.takeError());
return "";
}
return *ChangedCode;
}
std::string HeaderContent;
std::string HeaderName = "header.h";
std::string CCName = "input.cc";
};
} // namespace test
} // namespace clang_rename
} // namesdpace clang
#endif

@ -1,303 +0,0 @@
//===-- RenameAliasTest.cpp - unit tests for renaming alias ---------------===//
//
// 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 "ClangRenameTest.h"
namespace clang {
namespace clang_rename {
namespace test {
namespace {
class RenameAliasTest : public ClangRenameTest {
public:
RenameAliasTest() {
AppendToHeader(R"(
#define MACRO(x) x
namespace some_ns {
class A {
public:
void foo() {}
struct Nested {
enum NestedEnum {
E1, E2,
};
};
};
} // namespace some_ns
namespace a {
typedef some_ns::A TA;
using UA = some_ns::A;
} // namespace a
namespace b {
typedef some_ns::A TA;
using UA = some_ns::A;
}
template <typename T> class ptr {};
template <typename T>
using TPtr = ptr<int>;
)");
}
};
INSTANTIATE_TEST_SUITE_P(
RenameAliasTests, RenameAliasTest,
testing::ValuesIn(std::vector<Case>({
// basic functions
{"void f(a::TA a1) {}", "void f(b::TB a1) {}", "a::TA", "b::TB"},
{"void f(a::UA a1) {}", "void f(b::UB a1) {}", "a::UA", "b::UB"},
{"void f(a::TA* a1) {}", "void f(b::TB* a1) {}", "a::TA", "b::TB"},
{"void f(a::TA** a1) {}", "void f(b::TB** a1) {}", "a::TA", "b::TB"},
{"a::TA f() { return a::TA(); }", "b::TB f() { return b::TB(); }",
"a::TA", "b::TB"},
{"a::TA f() { return a::UA(); }", "b::TB f() { return a::UA(); }",
"a::TA", "b::TB"},
{"a::TA f() { return a::UA(); }", "a::TA f() { return b::UB(); }",
"a::UA", "b::UB"},
{"void f() { a::TA a; }", "void f() { b::TB a; }", "a::TA", "b::TB"},
{"void f(const a::TA& a1) {}", "void f(const b::TB& a1) {}", "a::TA",
"b::TB"},
{"void f(const a::UA& a1) {}", "void f(const b::UB& a1) {}", "a::UA",
"b::UB"},
{"void f(const a::TA* a1) {}", "void f(const b::TB* a1) {}", "a::TA",
"b::TB"},
{"namespace a { void f(TA a1) {} }",
"namespace a { void f(b::TB a1) {} }", "a::TA", "b::TB"},
{"void f(MACRO(a::TA) a1) {}", "void f(MACRO(b::TB) a1) {}", "a::TA",
"b::TB"},
{"void f(MACRO(a::TA a1)) {}", "void f(MACRO(b::TB a1)) {}", "a::TA",
"b::TB"},
// shorten/add namespace.
{"namespace b { void f(a::UA a1) {} }",
"namespace b {void f(UB a1) {} }", "a::UA", "b::UB"},
{"namespace a { void f(UA a1) {} }",
"namespace a {void f(b::UB a1) {} }", "a::UA", "b::UB"},
// use namespace and typedefs
{"struct S { using T = a::TA; T a_; };",
"struct S { using T = b::TB; T a_; };", "a::TA", "b::TB"},
{"using T = a::TA; T gA;", "using T = b::TB; T gA;", "a::TA", "b::TB"},
{"using T = a::UA; T gA;", "using T = b::UB; T gA;", "a::UA", "b::UB"},
{"typedef a::TA T; T gA;", "typedef b::TB T; T gA;", "a::TA", "b::TB"},
{"typedef a::UA T; T gA;", "typedef b::UB T; T gA;", "a::UA", "b::UB"},
{"typedef MACRO(a::TA) T; T gA;", "typedef MACRO(b::TB) T; T gA;",
"a::TA", "b::TB"},
// types in using shadows.
{"using a::TA; TA gA;", "using b::TB; b::TB gA;", "a::TA", "b::TB"},
{"using a::UA; UA gA;", "using b::UB; b::UB gA;", "a::UA", "b::UB"},
// struct members and other oddities
{"struct S : public a::TA {};", "struct S : public b::TB {};", "a::TA",
"b::TB"},
{"struct S : public a::UA {};", "struct S : public b::UB {};", "a::UA",
"b::UB"},
{"struct F { void f(a::TA a1) {} };",
"struct F { void f(b::TB a1) {} };", "a::TA", "b::TB"},
{"struct F { a::TA a_; };", "struct F { b::TB a_; };", "a::TA",
"b::TB"},
{"struct F { ptr<a::TA> a_; };", "struct F { ptr<b::TB> a_; };",
"a::TA", "b::TB"},
{"struct F { ptr<a::UA> a_; };", "struct F { ptr<b::UB> a_; };",
"a::UA", "b::UB"},
// types in nested name specifiers
{"void f() { a::TA::Nested ne; }", "void f() { b::TB::Nested ne; }",
"a::TA", "b::TB"},
{"void f() { a::UA::Nested ne; }", "void f() { b::UB::Nested ne; }",
"a::UA", "b::UB"},
{"void f() { a::TA::Nested::NestedEnum e; }",
"void f() { b::TB::Nested::NestedEnum e; }", "a::TA", "b::TB"},
{"void f() { auto e = a::TA::Nested::NestedEnum::E1; }",
"void f() { auto e = b::TB::Nested::NestedEnum::E1; }", "a::TA",
"b::TB"},
{"void f() { auto e = a::TA::Nested::E1; }",
"void f() { auto e = b::TB::Nested::E1; }", "a::TA", "b::TB"},
// templates
{"template <typename T> struct Foo { T t; }; void f() { Foo<a::TA> "
"foo; }",
"template <typename T> struct Foo { T t; }; void f() { Foo<b::TB> "
"foo; }",
"a::TA", "b::TB"},
{"template <typename T> struct Foo { a::TA a; };",
"template <typename T> struct Foo { b::TB a; };", "a::TA", "b::TB"},
{"template <typename T> void f(T t) {} void g() { f<a::TA>(a::TA()); }",
"template <typename T> void f(T t) {} void g() { f<b::TB>(b::TB()); }",
"a::TA", "b::TB"},
{"template <typename T> void f(T t) {} void g() { f<a::UA>(a::UA()); }",
"template <typename T> void f(T t) {} void g() { f<b::UB>(b::UB()); }",
"a::UA", "b::UB"},
{"template <typename T> int f() { return 1; } template <> int "
"f<a::TA>() { return 2; } int g() { return f<a::TA>(); }",
"template <typename T> int f() { return 1; } template <> int "
"f<b::TB>() { return 2; } int g() { return f<b::TB>(); }",
"a::TA", "b::TB"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<a::TA>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<b::TB>(); }",
"a::TA", "b::TB"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<a::UA>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<b::UB>(); }",
"a::UA", "b::UB"},
// The following two templates are distilled from regressions found in
// unique_ptr<> and type_traits.h
{"template <typename T> struct outer { typedef T type; type Baz(); }; "
"outer<a::TA> g_A;",
"template <typename T> struct outer { typedef T type; type Baz(); }; "
"outer<b::TB> g_A;",
"a::TA", "b::TB"},
{"template <typename T> struct nested { typedef T type; }; template "
"<typename T> struct outer { typename nested<T>::type Foo(); }; "
"outer<a::TA> g_A;",
"template <typename T> struct nested { typedef T type; }; template "
"<typename T> struct outer { typename nested<T>::type Foo(); }; "
"outer<b::TB> g_A;",
"a::TA", "b::TB"},
// macros
{"#define FOO(T, t) T t\nvoid f() { FOO(a::TA, a1); FOO(a::TA, a2); }",
"#define FOO(T, t) T t\nvoid f() { FOO(b::TB, a1); FOO(b::TB, a2); }",
"a::TA", "b::TB"},
{"#define FOO(n) a::TA n\nvoid f() { FOO(a1); FOO(a2); }",
"#define FOO(n) b::TB n\nvoid f() { FOO(a1); FOO(a2); }", "a::TA",
"b::TB"},
{"#define FOO(n) a::UA n\nvoid f() { FOO(a1); FOO(a2); }",
"#define FOO(n) b::UB n\nvoid f() { FOO(a1); FOO(a2); }", "a::UA",
"b::UB"},
// Pointer to member functions
{"auto gA = &a::TA::foo;", "auto gA = &b::TB::foo;", "a::TA", "b::TB"},
{"using a::TA; auto gA = &TA::foo;",
"using b::TB; auto gA = &b::TB::foo;", "a::TA", "b::TB"},
{"typedef a::TA T; auto gA = &T::foo;",
"typedef b::TB T; auto gA = &T::foo;", "a::TA", "b::TB"},
{"auto gA = &MACRO(a::TA)::foo;", "auto gA = &MACRO(b::TB)::foo;",
"a::TA", "b::TB"},
// templated using alias.
{"void f(TPtr<int> p) {}", "void f(NewTPtr<int> p) {}", "TPtr",
"NewTPtr"},
{"void f(::TPtr<int> p) {}", "void f(::NewTPtr<int> p) {}", "TPtr",
"NewTPtr"},
})));
TEST_P(RenameAliasTest, RenameAlias) {
auto Param = GetParam();
assert(!Param.OldName.empty());
assert(!Param.NewName.empty());
std::string Actual =
runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
CompareSnippets(Param.After, Actual);
}
TEST_F(RenameAliasTest, RenameTypedefDefinitions) {
std::string Before = R"(
class X {};
typedef X TOld;
)";
std::string Expected = R"(
class X {};
typedef X TNew;
)";
std::string After = runClangRenameOnCode(Before, "TOld", "TNew");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, RenameUsingAliasDefinitions) {
std::string Before = R"(
class X {};
using UOld = X;
)";
std::string Expected = R"(
class X {};
using UNew = X;
)";
std::string After = runClangRenameOnCode(Before, "UOld", "UNew");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, RenameTemplatedAliasDefinitions) {
std::string Before = R"(
template <typename T>
class X { T t; };
template <typename T>
using Old = X<T>;
)";
std::string Expected = R"(
template <typename T>
class X { T t; };
template <typename T>
using New = X<T>;
)";
std::string After = runClangRenameOnCode(Before, "Old", "New");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, RenameAliasesInNamespaces) {
std::string Before = R"(
namespace x { class X {}; }
namespace ns {
using UOld = x::X;
}
)";
std::string Expected = R"(
namespace x { class X {}; }
namespace ns {
using UNew = x::X;
}
)";
std::string After = runClangRenameOnCode(Before, "ns::UOld", "ns::UNew");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, AliasesInMacros) {
std::string Before = R"(
namespace x { class Old {}; }
namespace ns {
#define REF(alias) alias alias_var;
#define ALIAS(old) \
using old##Alias = x::old; \
REF(old##Alias);
ALIAS(Old);
OldAlias old_alias;
}
)";
std::string Expected = R"(
namespace x { class Old {}; }
namespace ns {
#define REF(alias) alias alias_var;
#define ALIAS(old) \
using old##Alias = x::old; \
REF(old##Alias);
ALIAS(Old);
NewAlias old_alias;
}
)";
std::string After =
runClangRenameOnCode(Before, "ns::OldAlias", "ns::NewAlias");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang

@ -1,820 +0,0 @@
//===-- RenameClassTest.cpp - unit tests for renaming classes -------------===//
//
// 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 "ClangRenameTest.h"
namespace clang {
namespace clang_rename {
namespace test {
namespace {
class RenameClassTest : public ClangRenameTest {
public:
RenameClassTest() {
AppendToHeader(R"(
namespace a {
class Foo {
public:
struct Nested {
enum NestedEnum {E1, E2};
};
void func() {}
static int Constant;
};
class Goo {
public:
struct Nested {
enum NestedEnum {E1, E2};
};
};
int Foo::Constant = 1;
} // namespace a
namespace b {
class Foo {};
} // namespace b
#define MACRO(x) x
template<typename T> class ptr {};
)");
}
};
INSTANTIATE_TEST_SUITE_P(
RenameClassTests, RenameClassTest,
testing::ValuesIn(std::vector<Case>({
// basic classes
{"a::Foo f;", "b::Bar f;", "", ""},
{"::a::Foo f;", "::b::Bar f;", "", ""},
{"void f(a::Foo f) {}", "void f(b::Bar f) {}", "", ""},
{"void f(a::Foo *f) {}", "void f(b::Bar *f) {}", "", ""},
{"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }",
"", ""},
{"namespace a {a::Foo f() { return Foo(); }}",
"namespace a {b::Bar f() { return b::Bar(); }}", "", ""},
{"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}", "", ""},
{"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}", "", ""},
{"namespace a { void f(Foo a1) {} }",
"namespace a { void f(b::Bar a1) {} }", "", ""},
{"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}", "", ""},
{"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}", "", ""},
{"a::Foo::Nested ns;", "b::Bar::Nested ns;", "", ""},
{"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;", "", ""},
{"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested",
"a::Foo::Nested2"},
// use namespace and typedefs
{"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;", "", ""},
{"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}",
"", ""},
{"using a::Foo; namespace x { Foo gA; }",
"using b::Bar; namespace x { Bar gA; }", "", ""},
{"struct S { using T = a::Foo; T a_; };",
"struct S { using T = b::Bar; T a_; };", "", ""},
{"using T = a::Foo; T gA;", "using T = b::Bar; T gA;", "", ""},
{"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;", "", ""},
{"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;", "",
""},
// struct members and other oddities
{"struct S : public a::Foo {};", "struct S : public b::Bar {};", "",
""},
{"struct F { void f(a::Foo a1) {} };",
"struct F { void f(b::Bar a1) {} };", "", ""},
{"struct F { a::Foo a_; };", "struct F { b::Bar a_; };", "", ""},
{"struct F { ptr<a::Foo> a_; };", "struct F { ptr<b::Bar> a_; };", "",
""},
{"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }",
"", ""},
{"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }",
"", ""},
{"void f() { a::Foo::Nested::NestedEnum e; }",
"void f() { b::Bar::Nested::NestedEnum e; }", "", ""},
{"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }",
"void f() { auto e = b::Bar::Nested::NestedEnum::E1; }", "", ""},
{"void f() { auto e = a::Foo::Nested::E1; }",
"void f() { auto e = b::Bar::Nested::E1; }", "", ""},
// templates
{"template <typename T> struct Foo { T t; };\n"
"void f() { Foo<a::Foo> foo; }",
"template <typename T> struct Foo { T t; };\n"
"void f() { Foo<b::Bar> foo; }",
"", ""},
{"template <typename T> struct Foo { a::Foo a; };",
"template <typename T> struct Foo { b::Bar a; };", "", ""},
{"template <typename T> void f(T t) {}\n"
"void g() { f<a::Foo>(a::Foo()); }",
"template <typename T> void f(T t) {}\n"
"void g() { f<b::Bar>(b::Bar()); }",
"", ""},
{"template <typename T> int f() { return 1; }\n"
"template <> int f<a::Foo>() { return 2; }\n"
"int g() { return f<a::Foo>(); }",
"template <typename T> int f() { return 1; }\n"
"template <> int f<b::Bar>() { return 2; }\n"
"int g() { return f<b::Bar>(); }",
"", ""},
{"struct Foo { template <typename T> T foo(); };\n"
"void g() { Foo f; auto a = f.template foo<a::Foo>(); }",
"struct Foo { template <typename T> T foo(); };\n"
"void g() { Foo f; auto a = f.template foo<b::Bar>(); }",
"", ""},
// The following two templates are distilled from regressions found in
// unique_ptr<> and type_traits.h
{"template <typename T> struct outer {\n"
" typedef T type;\n"
" type Baz();\n"
" };\n"
" outer<a::Foo> g_A;",
"template <typename T> struct outer {\n"
" typedef T type;\n"
" type Baz();\n"
" };\n"
" outer<b::Bar> g_A;",
"", ""},
{"template <typename T> struct nested { typedef T type; };\n"
"template <typename T> struct outer { typename nested<T>::type Foo(); "
"};\n"
"outer<a::Foo> g_A;",
"template <typename T> struct nested { typedef T type; };\n"
"template <typename T> struct outer { typename nested<T>::type Foo(); "
"};\n"
"outer<b::Bar> g_A;",
"", ""},
// macros
{"#define FOO(T, t) T t\n"
"void f() { FOO(a::Foo, a1); FOO(a::Foo, a2); }",
"#define FOO(T, t) T t\n"
"void f() { FOO(b::Bar, a1); FOO(b::Bar, a2); }",
"", ""},
{"#define FOO(n) a::Foo n\n"
" void f() { FOO(a1); FOO(a2); }",
"#define FOO(n) b::Bar n\n"
" void f() { FOO(a1); FOO(a2); }",
"", ""},
// Pointer to member functions
{"auto gA = &a::Foo::func;", "auto gA = &b::Bar::func;", "", ""},
{"using a::Foo; auto gA = &Foo::func;",
"using b::Bar; auto gA = &b::Bar::func;", "", ""},
{"using a::Foo; namespace x { auto gA = &Foo::func; }",
"using b::Bar; namespace x { auto gA = &Bar::func; }", "", ""},
{"typedef a::Foo T; auto gA = &T::func;",
"typedef b::Bar T; auto gA = &T::func;", "", ""},
{"auto gA = &MACRO(a::Foo)::func;", "auto gA = &MACRO(b::Bar)::func;",
"", ""},
// Short match inside a namespace
{"namespace a { void f(Foo a1) {} }",
"namespace a { void f(b::Bar a1) {} }", "", ""},
// Correct match.
{"using a::Foo; struct F { ptr<Foo> a_; };",
"using b::Bar; struct F { ptr<Bar> a_; };", "", ""},
// avoid false positives
{"void f(b::Foo a) {}", "void f(b::Foo a) {}", "", ""},
{"namespace b { void f(Foo a) {} }", "namespace b { void f(Foo a) {} }",
"", ""},
// friends, everyone needs friends.
{"class Foo { int i; friend class a::Foo; };",
"class Foo { int i; friend class b::Bar; };", "", ""},
})) );
TEST_P(RenameClassTest, RenameClasses) {
auto Param = GetParam();
std::string OldName = Param.OldName.empty() ? "a::Foo" : Param.OldName;
std::string NewName = Param.NewName.empty() ? "b::Bar" : Param.NewName;
std::string Actual = runClangRenameOnCode(Param.Before, OldName, NewName);
CompareSnippets(Param.After, Actual);
}
class NamespaceDetectionTest : public ClangRenameTest {
protected:
NamespaceDetectionTest() {
AppendToHeader(R"(
class Old {};
namespace o1 {
class Old {};
namespace o2 {
class Old {};
namespace o3 {
class Old {};
} // namespace o3
} // namespace o2
} // namespace o1
)");
}
};
INSTANTIATE_TEST_SUITE_P(
RenameClassTest, NamespaceDetectionTest,
::testing::ValuesIn(std::vector<Case>({
// Test old and new namespace overlap.
{"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
"namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
"o1::o2::o3::Old", "o1::o2::o3::New"},
{"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
"namespace o1 { namespace o2 { namespace o3 { n3::New moo; } } }",
"o1::o2::o3::Old", "o1::o2::n3::New"},
{"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
"namespace o1 { namespace o2 { namespace o3 { n2::n3::New moo; } } }",
"o1::o2::o3::Old", "o1::n2::n3::New"},
{"namespace o1 { namespace o2 { Old moo; } }",
"namespace o1 { namespace o2 { New moo; } }", "::o1::o2::Old",
"::o1::o2::New"},
{"namespace o1 { namespace o2 { Old moo; } }",
"namespace o1 { namespace o2 { n2::New moo; } }", "::o1::o2::Old",
"::o1::n2::New"},
{"namespace o1 { namespace o2 { Old moo; } }",
"namespace o1 { namespace o2 { ::n1::n2::New moo; } }",
"::o1::o2::Old", "::n1::n2::New"},
{"namespace o1 { namespace o2 { Old moo; } }",
"namespace o1 { namespace o2 { n1::n2::New moo; } }", "::o1::o2::Old",
"n1::n2::New"},
// Test old and new namespace with differing depths.
{"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
"namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
"o1::o2::o3::Old", "::o1::New"},
{"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
"namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
"o1::o2::o3::Old", "::o1::o2::New"},
{"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
"namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
"o1::o2::o3::Old", "o1::New"},
{"namespace o1 { namespace o2 { namespace o3 { Old moo; } } }",
"namespace o1 { namespace o2 { namespace o3 { New moo; } } }",
"o1::o2::o3::Old", "o1::o2::New"},
{"Old moo;", "o1::New moo;", "::Old", "o1::New"},
{"Old moo;", "o1::New moo;", "Old", "o1::New"},
{"namespace o1 { ::Old moo; }", "namespace o1 { New moo; }", "Old",
"o1::New"},
{"namespace o1 { namespace o2 { Old moo; } }",
"namespace o1 { namespace o2 { ::New moo; } }", "::o1::o2::Old",
"::New"},
{"namespace o1 { namespace o2 { Old moo; } }",
"namespace o1 { namespace o2 { New moo; } }", "::o1::o2::Old", "New"},
// Test moving into the new namespace at different levels.
{"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
"namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old",
"::n1::n2::New"},
{"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
"namespace n1 { namespace n2 { New moo; } }", "::o1::o2::Old",
"n1::n2::New"},
{"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
"namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old",
"::n1::o2::New"},
{"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
"namespace n1 { namespace n2 { o2::New moo; } }", "::o1::o2::Old",
"n1::o2::New"},
{"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
"namespace n1 { namespace n2 { ::o1::o2::New moo; } }",
"::o1::o2::Old", "::o1::o2::New"},
{"namespace n1 { namespace n2 { o1::o2::Old moo; } }",
"namespace n1 { namespace n2 { o1::o2::New moo; } }", "::o1::o2::Old",
"o1::o2::New"},
// Test friends declarations.
{"class Foo { friend class o1::Old; };",
"class Foo { friend class o1::New; };", "o1::Old", "o1::New"},
{"class Foo { int i; friend class o1::Old; };",
"class Foo { int i; friend class ::o1::New; };", "::o1::Old",
"::o1::New"},
{"namespace o1 { class Foo { int i; friend class Old; }; }",
"namespace o1 { class Foo { int i; friend class New; }; }", "o1::Old",
"o1::New"},
{"namespace o1 { class Foo { int i; friend class Old; }; }",
"namespace o1 { class Foo { int i; friend class New; }; }",
"::o1::Old", "::o1::New"},
})) );
TEST_P(NamespaceDetectionTest, RenameClasses) {
auto Param = GetParam();
std::string Actual =
runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
CompareSnippets(Param.After, Actual);
}
class TemplatedClassRenameTest : public ClangRenameTest {
protected:
TemplatedClassRenameTest() {
AppendToHeader(R"(
template <typename T> struct Old {
T t_;
T f() { return T(); };
static T s(T t) { return t; }
};
namespace ns {
template <typename T> struct Old {
T t_;
T f() { return T(); };
static T s(T t) { return t; }
};
} // namespace ns
namespace o1 {
namespace o2 {
namespace o3 {
template <typename T> struct Old {
T t_;
T f() { return T(); };
static T s(T t) { return t; }
};
} // namespace o3
} // namespace o2
} // namespace o1
)");
}
};
INSTANTIATE_TEST_SUITE_P(
RenameClassTests, TemplatedClassRenameTest,
::testing::ValuesIn(std::vector<Case>({
{"Old<int> gI; Old<bool> gB;", "New<int> gI; New<bool> gB;", "Old",
"New"},
{"ns::Old<int> gI; ns::Old<bool> gB;",
"ns::New<int> gI; ns::New<bool> gB;", "ns::Old", "ns::New"},
{"auto gI = &Old<int>::f; auto gB = &Old<bool>::f;",
"auto gI = &New<int>::f; auto gB = &New<bool>::f;", "Old", "New"},
{"auto gI = &ns::Old<int>::f;", "auto gI = &ns::New<int>::f;",
"ns::Old", "ns::New"},
{"int gI = Old<int>::s(0); bool gB = Old<bool>::s(false);",
"int gI = New<int>::s(0); bool gB = New<bool>::s(false);", "Old",
"New"},
{"int gI = ns::Old<int>::s(0); bool gB = ns::Old<bool>::s(false);",
"int gI = ns::New<int>::s(0); bool gB = ns::New<bool>::s(false);",
"ns::Old", "ns::New"},
{"struct S { Old<int*> o_; };", "struct S { New<int*> o_; };", "Old",
"New"},
{"struct S { ns::Old<int*> o_; };", "struct S { ns::New<int*> o_; };",
"ns::Old", "ns::New"},
{"auto a = reinterpret_cast<Old<int>*>(new Old<int>);",
"auto a = reinterpret_cast<New<int>*>(new New<int>);", "Old", "New"},
{"auto a = reinterpret_cast<ns::Old<int>*>(new ns::Old<int>);",
"auto a = reinterpret_cast<ns::New<int>*>(new ns::New<int>);",
"ns::Old", "ns::New"},
{"auto a = reinterpret_cast<const Old<int>*>(new Old<int>);",
"auto a = reinterpret_cast<const New<int>*>(new New<int>);", "Old",
"New"},
{"auto a = reinterpret_cast<const ns::Old<int>*>(new ns::Old<int>);",
"auto a = reinterpret_cast<const ns::New<int>*>(new ns::New<int>);",
"ns::Old", "ns::New"},
{"Old<bool>& foo();", "New<bool>& foo();", "Old", "New"},
{"ns::Old<bool>& foo();", "ns::New<bool>& foo();", "ns::Old",
"ns::New"},
{"o1::o2::o3::Old<bool>& foo();", "o1::o2::o3::New<bool>& foo();",
"o1::o2::o3::Old", "o1::o2::o3::New"},
{"namespace ns { Old<bool>& foo(); }",
"namespace ns { New<bool>& foo(); }", "ns::Old", "ns::New"},
{"const Old<bool>& foo();", "const New<bool>& foo();", "Old", "New"},
{"const ns::Old<bool>& foo();", "const ns::New<bool>& foo();",
"ns::Old", "ns::New"},
// FIXME: figure out why this only works when Moo gets
// specialized at some point.
{"template <typename T> struct Moo { Old<T> o_; }; Moo<int> m;",
"template <typename T> struct Moo { New<T> o_; }; Moo<int> m;", "Old",
"New"},
{"template <typename T> struct Moo { ns::Old<T> o_; }; Moo<int> m;",
"template <typename T> struct Moo { ns::New<T> o_; }; Moo<int> m;",
"ns::Old", "ns::New"},
})) );
TEST_P(TemplatedClassRenameTest, RenameTemplateClasses) {
auto Param = GetParam();
std::string Actual =
runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
CompareSnippets(Param.After, Actual);
}
TEST_F(ClangRenameTest, RenameClassWithOutOfLineMembers) {
std::string Before = R"(
class Old {
public:
Old();
~Old();
Old* next();
private:
Old* next_;
};
Old::Old() {}
Old::~Old() {}
Old* Old::next() { return next_; }
)";
std::string Expected = R"(
class New {
public:
New();
~New();
New* next();
private:
New* next_;
};
New::New() {}
New::~New() {}
New* New::next() { return next_; }
)";
std::string After = runClangRenameOnCode(Before, "Old", "New");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, RenameClassWithInlineMembers) {
std::string Before = R"(
class Old {
public:
Old() {}
~Old() {}
Old* next() { return next_; }
private:
Old* next_;
};
)";
std::string Expected = R"(
class New {
public:
New() {}
~New() {}
New* next() { return next_; }
private:
New* next_;
};
)";
std::string After = runClangRenameOnCode(Before, "Old", "New");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, RenameClassWithNamespaceWithInlineMembers) {
std::string Before = R"(
namespace ns {
class Old {
public:
Old() {}
~Old() {}
Old* next() { return next_; }
private:
Old* next_;
};
} // namespace ns
)";
std::string Expected = R"(
namespace ns {
class New {
public:
New() {}
~New() {}
New* next() { return next_; }
private:
New* next_;
};
} // namespace ns
)";
std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, RenameClassWithNamespaceWithOutOfInlineMembers) {
std::string Before = R"(
namespace ns {
class Old {
public:
Old();
~Old();
Old* next();
private:
Old* next_;
};
Old::Old() {}
Old::~Old() {}
Old* Old::next() { return next_; }
} // namespace ns
)";
std::string Expected = R"(
namespace ns {
class New {
public:
New();
~New();
New* next();
private:
New* next_;
};
New::New() {}
New::~New() {}
New* New::next() { return next_; }
} // namespace ns
)";
std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, RenameClassInInheritedConstructor) {
// `using Base::Base;` will generate an implicit constructor containing usage
// of `::ns::Old` which should not be matched.
std::string Before = R"(
namespace ns {
class Old;
class Old {
int x;
};
class Base {
protected:
Old *moo_;
public:
Base(Old *moo) : moo_(moo) {}
};
class Derived : public Base {
public:
using Base::Base;
};
} // namespace ns
int main() {
::ns::Old foo;
::ns::Derived d(&foo);
return 0;
})";
std::string Expected = R"(
namespace ns {
class New;
class New {
int x;
};
class Base {
protected:
New *moo_;
public:
Base(New *moo) : moo_(moo) {}
};
class Derived : public Base {
public:
using Base::Base;
};
} // namespace ns
int main() {
::ns::New foo;
::ns::Derived d(&foo);
return 0;
})";
std::string After = runClangRenameOnCode(Before, "ns::Old", "ns::New");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, DontRenameReferencesInImplicitFunction) {
std::string Before = R"(
namespace ns {
class Old {
};
} // namespace ns
struct S {
int y;
ns::Old old;
};
void f() {
S s1, s2, s3;
// This causes an implicit assignment operator to be created.
s1 = s2 = s3;
}
)";
std::string Expected = R"(
namespace ns {
class New {
};
} // namespace ns
struct S {
int y;
::new_ns::New old;
};
void f() {
S s1, s2, s3;
// This causes an implicit assignment operator to be created.
s1 = s2 = s3;
}
)";
std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, ReferencesInLambdaFunctionParameters) {
std::string Before = R"(
template <class T>
class function;
template <class R, class... ArgTypes>
class function<R(ArgTypes...)> {
public:
template <typename Functor>
function(Functor f) {}
function() {}
R operator()(ArgTypes...) const {}
};
namespace ns {
class Old {};
void f() {
function<void(Old)> func;
}
} // namespace ns)";
std::string Expected = R"(
template <class T>
class function;
template <class R, class... ArgTypes>
class function<R(ArgTypes...)> {
public:
template <typename Functor>
function(Functor f) {}
function() {}
R operator()(ArgTypes...) const {}
};
namespace ns {
class New {};
void f() {
function<void(::new_ns::New)> func;
}
} // namespace ns)";
std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, DontChangeIfSameName) {
std::string Before = R"(
namespace foo {
class Old {
public:
static void foo() {}
};
}
void f(foo::Old * x) {
foo::Old::foo() ;
}
using foo::Old;)";
std::string Expected = R"(
namespace foo {
class Old {
public:
static void foo() {}
};
}
void f(foo::Old * x) {
foo::Old::foo() ;
}
using foo::Old;)";
std::string After = runClangRenameOnCode(Before, "foo::Old", "foo::Old");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, ChangeIfNewNameWithLeadingDotDot) {
std::string Before = R"(
namespace foo {
class Old {
public:
static void foo() {}
};
}
void f(foo::Old * x) {
foo::Old::foo() ;
}
using foo::Old;)";
std::string Expected = R"(
namespace foo {
class Old {
public:
static void foo() {}
};
}
void f(::foo::Old * x) {
::foo::Old::foo() ;
}
using ::foo::Old;)";
std::string After = runClangRenameOnCode(Before, "foo::Old", "::foo::Old");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, ChangeIfSameNameWithLeadingDotDot) {
std::string Before = R"(
namespace foo {
class Old {
public:
static void foo() {}
};
}
void f(foo::Old * x) {
foo::Old::foo() ;
}
using foo::Old;)";
std::string Expected = R"(
namespace foo {
class Old {
public:
static void foo() {}
};
}
void f(::foo::Old * x) {
::foo::Old::foo() ;
}
using ::foo::Old;)";
std::string After = runClangRenameOnCode(Before, "::foo::Old", "::foo::Old");
CompareSnippets(Expected, After);
}
TEST_F(RenameClassTest, UsingAlias) {
std::string Before = R"(
namespace a { struct A {}; }
namespace foo {
using Alias = a::A;
Alias a;
})";
std::string Expected = R"(
namespace a { struct B {}; }
namespace foo {
using Alias = b::B;
Alias a;
})";
std::string After = runClangRenameOnCode(Before, "a::A", "b::B");
CompareSnippets(Expected, After);
}
TEST_F(ClangRenameTest, FieldDesignatedInitializers) {
std::string Before = R"(
struct S {
int a;
};
void foo() {
S s = { .a = 10 };
s.a = 20;
})";
std::string Expected = R"(
struct S {
int b;
};
void foo() {
S s = { .b = 10 };
s.b = 20;
})";
std::string After = runClangRenameOnCode(Before, "S::a", "S::b");
CompareSnippets(Expected, After);
}
// FIXME: investigate why the test fails when adding a new USR to the USRSet.
TEST_F(ClangRenameTest, DISABLED_NestedTemplates) {
std::string Before = R"(
namespace a { template <typename T> struct A {}; }
a::A<a::A<int>> foo;)";
std::string Expected = R"(
namespace a { template <typename T> struct B {}; }
b::B<b::B<int>> foo;)";
std::string After = runClangRenameOnCode(Before, "a::A", "b::B");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang

@ -1,189 +0,0 @@
#include "ClangRenameTest.h"
namespace clang {
namespace clang_rename {
namespace test {
namespace {
class RenameEnumTest : public ClangRenameTest {
public:
RenameEnumTest() {
AppendToHeader(R"(
#define MACRO(x) x
namespace a {
enum A1 { Red };
enum class A2 { Blue };
struct C {
enum NestedEnum { White };
enum class NestedScopedEnum { Black };
};
namespace d {
enum A3 { Orange };
} // namespace d
enum A4 { Pink };
} // namespace a
enum A5 { Green };)");
}
};
INSTANTIATE_TEST_SUITE_P(
RenameEnumTests, RenameEnumTest,
testing::ValuesIn(std::vector<Case>({
{"void f(a::A2 arg) { a::A2 t = a::A2::Blue; }",
"void f(b::B2 arg) { b::B2 t = b::B2::Blue; }", "a::A2", "b::B2"},
{"void f() { a::A1* t1; }", "void f() { b::B1* t1; }", "a::A1",
"b::B1"},
{"void f() { a::A2* t1; }", "void f() { b::B2* t1; }", "a::A2",
"b::B2"},
{"void f() { enum a::A2 t = a::A2::Blue; }",
"void f() { enum b::B2 t = b::B2::Blue; }", "a::A2", "b::B2"},
{"void f() { enum a::A2 t = a::A2::Blue; }",
"void f() { enum b::B2 t = b::B2::Blue; }", "a::A2", "b::B2"},
{"void f() { a::A1 t = a::Red; }", "void f() { b::B1 t = b::B1::Red; }",
"a::A1", "b::B1"},
{"void f() { a::A1 t = a::A1::Red; }",
"void f() { b::B1 t = b::B1::Red; }", "a::A1", "b::B1"},
{"void f() { auto t = a::Red; }", "void f() { auto t = b::B1::Red; }",
"a::A1", "b::B1"},
{"namespace b { void f() { a::A1 t = a::Red; } }",
"namespace b { void f() { B1 t = B1::Red; } }", "a::A1", "b::B1"},
{"void f() { a::d::A3 t = a::d::Orange; }",
"void f() { a::b::B3 t = a::b::B3::Orange; }", "a::d::A3", "a::b::B3"},
{"namespace a { void f() { a::d::A3 t = a::d::Orange; } }",
"namespace a { void f() { b::B3 t = b::B3::Orange; } }", "a::d::A3",
"a::b::B3"},
{"void f() { A5 t = Green; }", "void f() { B5 t = Green; }", "A5",
"B5"},
// FIXME: the new namespace qualifier should be added to the unscoped
// enum constant.
{"namespace a { void f() { auto t = Green; } }",
"namespace a { void f() { auto t = Green; } }", "a::A1", "b::B1"},
// namespace qualifiers
{"namespace a { void f(A1 a1) {} }",
"namespace a { void f(b::B1 a1) {} }", "a::A1", "b::B1"},
{"namespace a { void f(A2 a2) {} }",
"namespace a { void f(b::B2 a2) {} }", "a::A2", "b::B2"},
{"namespace b { void f(a::A1 a1) {} }",
"namespace b { void f(B1 a1) {} }", "a::A1", "b::B1"},
{"namespace b { void f(a::A2 a2) {} }",
"namespace b { void f(B2 a2) {} }", "a::A2", "b::B2"},
// nested enums
{"void f() { a::C::NestedEnum t = a::C::White; }",
"void f() { a::C::NewNestedEnum t = a::C::NewNestedEnum::White; }",
"a::C::NestedEnum", "a::C::NewNestedEnum"},
{"void f() { a::C::NestedScopedEnum t = a::C::NestedScopedEnum::Black; "
"}",
"void f() { a::C::NewNestedScopedEnum t = "
"a::C::NewNestedScopedEnum::Black; }",
"a::C::NestedScopedEnum", "a::C::NewNestedScopedEnum"},
// macros
{"void f(MACRO(a::A1) a1) {}", "void f(MACRO(b::B1) a1) {}", "a::A1",
"b::B1"},
{"void f(MACRO(a::A2) a2) {}", "void f(MACRO(b::B2) a2) {}", "a::A2",
"b::B2"},
{"#define FOO(T, t) T t\nvoid f() { FOO(a::A1, a1); }",
"#define FOO(T, t) T t\nvoid f() { FOO(b::B1, a1); }", "a::A1",
"b::B1"},
{"#define FOO(T, t) T t\nvoid f() { FOO(a::A2, a2); }",
"#define FOO(T, t) T t\nvoid f() { FOO(b::B2, a2); }", "a::A2",
"b::B2"},
{"#define FOO(n) a::A1 n\nvoid f() { FOO(a1); FOO(a2); }",
"#define FOO(n) b::B1 n\nvoid f() { FOO(a1); FOO(a2); }", "a::A1",
"b::B1"},
// using and type alias
{"using a::A1; A1 gA;", "using b::B1; b::B1 gA;", "a::A1", "b::B1"},
{"using a::A2; A2 gA;", "using b::B2; b::B2 gA;", "a::A2", "b::B2"},
{"struct S { using T = a::A1; T a_; };",
"struct S { using T = b::B1; T a_; };", "a::A1", "b::B1"},
{"using T = a::A1; T gA;", "using T = b::B1; T gA;", "a::A1", "b::B1"},
{"using T = a::A2; T gA;", "using T = b::B2; T gA;", "a::A2", "b::B2"},
{"typedef a::A1 T; T gA;", "typedef b::B1 T; T gA;", "a::A1", "b::B1"},
{"typedef a::A2 T; T gA;", "typedef b::B2 T; T gA;", "a::A2", "b::B2"},
{"typedef MACRO(a::A1) T; T gA;", "typedef MACRO(b::B1) T; T gA;",
"a::A1", "b::B1"},
// templates
{"template<typename T> struct Foo { T t; }; void f() { Foo<a::A1> "
"foo1; }",
"template<typename T> struct Foo { T t; }; void f() { Foo<b::B1> "
"foo1; }",
"a::A1", "b::B1"},
{"template<typename T> struct Foo { T t; }; void f() { Foo<a::A2> "
"foo2; }",
"template<typename T> struct Foo { T t; }; void f() { Foo<b::B2> "
"foo2; }",
"a::A2", "b::B2"},
{"template<typename T> struct Foo { a::A1 a1; };",
"template<typename T> struct Foo { b::B1 a1; };", "a::A1", "b::B1"},
{"template<typename T> struct Foo { a::A2 a2; };",
"template<typename T> struct Foo { b::B2 a2; };", "a::A2", "b::B2"},
{"template<typename T> int f() { return 1; } template<> int f<a::A1>() "
"{ return 2; } int g() { return f<a::A1>(); }",
"template<typename T> int f() { return 1; } template<> int f<b::B1>() "
"{ return 2; } int g() { return f<b::B1>(); }",
"a::A1", "b::B1"},
{"template<typename T> int f() { return 1; } template<> int f<a::A2>() "
"{ return 2; } int g() { return f<a::A2>(); }",
"template<typename T> int f() { return 1; } template<> int f<b::B2>() "
"{ return 2; } int g() { return f<b::B2>(); }",
"a::A2", "b::B2"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<a::A1>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<b::B1>(); }",
"a::A1", "b::B1"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<a::A2>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<b::B2>(); }",
"a::A2", "b::B2"},
})) );
TEST_P(RenameEnumTest, RenameEnums) {
auto Param = GetParam();
assert(!Param.OldName.empty());
assert(!Param.NewName.empty());
std::string Actual =
runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
CompareSnippets(Param.After, Actual);
}
TEST_F(RenameEnumTest, RenameEnumDecl) {
std::string Before = R"(
namespace ns {
enum Old1 { Blue };
}
)";
std::string Expected = R"(
namespace ns {
enum New1 { Blue };
}
)";
std::string After = runClangRenameOnCode(Before, "ns::Old1", "ns::New1");
CompareSnippets(Expected, After);
}
TEST_F(RenameEnumTest, RenameScopedEnumDecl) {
std::string Before = R"(
namespace ns {
enum class Old1 { Blue };
}
)";
std::string Expected = R"(
namespace ns {
enum class New1 { Blue };
}
)";
std::string After = runClangRenameOnCode(Before, "ns::Old1", "ns::New1");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang

@ -1,573 +0,0 @@
//===-- RenameFunctionTest.cpp - unit tests for renaming functions --------===//
//
// 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 "ClangRenameTest.h"
namespace clang {
namespace clang_rename {
namespace test {
namespace {
class RenameFunctionTest : public ClangRenameTest {
public:
RenameFunctionTest() {
AppendToHeader(R"(
struct A {
static bool Foo();
static bool Spam();
};
struct B {
static void Same();
static bool Foo();
static int Eric(int x);
};
void Same(int x);
int Eric(int x);
namespace base {
void Same();
void ToNanoSeconds();
void ToInt64NanoSeconds();
})");
}
};
TEST_F(RenameFunctionTest, RefactorsAFoo) {
std::string Before = R"(
void f() {
A::Foo();
::A::Foo();
})";
std::string Expected = R"(
void f() {
A::Bar();
::A::Bar();
})";
std::string After = runClangRenameOnCode(Before, "A::Foo", "A::Bar");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, RefactorsNonCallingAFoo) {
std::string Before = R"(
bool g(bool (*func)()) {
return func();
}
void f() {
auto *ref1 = A::Foo;
auto *ref2 = ::A::Foo;
g(A::Foo);
})";
std::string Expected = R"(
bool g(bool (*func)()) {
return func();
}
void f() {
auto *ref1 = A::Bar;
auto *ref2 = ::A::Bar;
g(A::Bar);
})";
std::string After = runClangRenameOnCode(Before, "A::Foo", "A::Bar");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, RefactorsEric) {
std::string Before = R"(
void f() {
if (Eric(3)==4) ::Eric(2);
})";
std::string Expected = R"(
void f() {
if (Larry(3)==4) ::Larry(2);
})";
std::string After = runClangRenameOnCode(Before, "Eric", "Larry");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, RefactorsNonCallingEric) {
std::string Before = R"(
int g(int (*func)(int)) {
return func(1);
}
void f() {
auto *ref = ::Eric;
g(Eric);
})";
std::string Expected = R"(
int g(int (*func)(int)) {
return func(1);
}
void f() {
auto *ref = ::Larry;
g(Larry);
})";
std::string After = runClangRenameOnCode(Before, "Eric", "Larry");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, DoesNotRefactorBFoo) {
std::string Before = R"(
void f() {
B::Foo();
})";
std::string After = runClangRenameOnCode(Before, "A::Foo", "A::Bar");
CompareSnippets(Before, After);
}
TEST_F(RenameFunctionTest, DoesNotRefactorBEric) {
std::string Before = R"(
void f() {
B::Eric(2);
})";
std::string After = runClangRenameOnCode(Before, "Eric", "Larry");
CompareSnippets(Before, After);
}
TEST_F(RenameFunctionTest, DoesNotRefactorCEric) {
std::string Before = R"(
namespace C { int Eric(int x); }
void f() {
if (C::Eric(3)==4) ::C::Eric(2);
})";
std::string Expected = R"(
namespace C { int Eric(int x); }
void f() {
if (C::Eric(3)==4) ::C::Eric(2);
})";
std::string After = runClangRenameOnCode(Before, "Eric", "Larry");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, DoesNotRefactorEricInNamespaceC) {
std::string Before = R"(
namespace C {
int Eric(int x);
void f() {
if (Eric(3)==4) Eric(2);
}
} // namespace C)";
std::string After = runClangRenameOnCode(Before, "Eric", "Larry");
CompareSnippets(Before, After);
}
TEST_F(RenameFunctionTest, NamespaceQualified) {
std::string Before = R"(
void f() {
base::ToNanoSeconds();
::base::ToNanoSeconds();
}
void g() {
using base::ToNanoSeconds;
base::ToNanoSeconds();
::base::ToNanoSeconds();
ToNanoSeconds();
}
namespace foo {
namespace base {
void ToNanoSeconds();
void f() {
base::ToNanoSeconds();
}
}
void f() {
::base::ToNanoSeconds();
}
})";
std::string Expected = R"(
void f() {
base::ToInt64NanoSeconds();
::base::ToInt64NanoSeconds();
}
void g() {
using base::ToInt64NanoSeconds;
base::ToInt64NanoSeconds();
::base::ToInt64NanoSeconds();
base::ToInt64NanoSeconds();
}
namespace foo {
namespace base {
void ToNanoSeconds();
void f() {
base::ToNanoSeconds();
}
}
void f() {
::base::ToInt64NanoSeconds();
}
})";
std::string After = runClangRenameOnCode(Before, "base::ToNanoSeconds",
"base::ToInt64NanoSeconds");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, RenameFunctionDecls) {
std::string Before = R"(
namespace na {
void X();
void X() {}
})";
std::string Expected = R"(
namespace na {
void Y();
void Y() {}
})";
std::string After = runClangRenameOnCode(Before, "na::X", "na::Y");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, RenameTemplateFunctions) {
std::string Before = R"(
namespace na {
template<typename T> T X();
}
namespace na { void f() { X<int>(); } }
namespace nb { void g() { na::X <int>(); } }
)";
std::string Expected = R"(
namespace na {
template<typename T> T Y();
}
namespace na { void f() { nb::Y<int>(); } }
namespace nb { void g() { Y<int>(); } }
)";
std::string After = runClangRenameOnCode(Before, "na::X", "nb::Y");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, RenameOutOfLineFunctionDecls) {
std::string Before = R"(
namespace na {
void X();
}
void na::X() {}
)";
std::string Expected = R"(
namespace na {
void Y();
}
void na::Y() {}
)";
std::string After = runClangRenameOnCode(Before, "na::X", "na::Y");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, NewNamespaceWithoutLeadingDotDot) {
std::string Before = R"(
namespace old_ns {
void X();
void X() {}
}
// Assume that the reference is in another file.
void f() { old_ns::X(); }
namespace old_ns { void g() { X(); } }
namespace new_ns { void h() { ::old_ns::X(); } }
)";
std::string Expected = R"(
namespace old_ns {
void Y();
void Y() {}
}
// Assume that the reference is in another file.
void f() { new_ns::Y(); }
namespace old_ns { void g() { new_ns::Y(); } }
namespace new_ns { void h() { Y(); } }
)";
std::string After = runClangRenameOnCode(Before, "::old_ns::X", "new_ns::Y");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, NewNamespaceWithLeadingDotDot) {
std::string Before = R"(
namespace old_ns {
void X();
void X() {}
}
// Assume that the reference is in another file.
void f() { old_ns::X(); }
namespace old_ns { void g() { X(); } }
namespace new_ns { void h() { ::old_ns::X(); } }
)";
std::string Expected = R"(
namespace old_ns {
void Y();
void Y() {}
}
// Assume that the reference is in another file.
void f() { ::new_ns::Y(); }
namespace old_ns { void g() { ::new_ns::Y(); } }
namespace new_ns { void h() { Y(); } }
)";
std::string After =
runClangRenameOnCode(Before, "::old_ns::X", "::new_ns::Y");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, DontRenameSymbolsDefinedInAnonymousNamespace) {
std::string Before = R"(
namespace old_ns {
class X {};
namespace {
void X();
void X() {}
void f() { X(); }
}
}
)";
std::string Expected = R"(
namespace old_ns {
class Y {};
namespace {
void X();
void X() {}
void f() { X(); }
}
}
)";
std::string After =
runClangRenameOnCode(Before, "::old_ns::X", "::old_ns::Y");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, NewNestedNamespace) {
std::string Before = R"(
namespace old_ns {
void X();
void X() {}
}
// Assume that the reference is in another file.
namespace old_ns {
void f() { X(); }
}
)";
std::string Expected = R"(
namespace old_ns {
void X();
void X() {}
}
// Assume that the reference is in another file.
namespace old_ns {
void f() { older_ns::X(); }
}
)";
std::string After =
runClangRenameOnCode(Before, "::old_ns::X", "::old_ns::older_ns::X");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, MoveFromGlobalToNamespaceWithoutLeadingDotDot) {
std::string Before = R"(
void X();
void X() {}
// Assume that the reference is in another file.
namespace some_ns {
void f() { X(); }
}
)";
std::string Expected = R"(
void X();
void X() {}
// Assume that the reference is in another file.
namespace some_ns {
void f() { ns::X(); }
}
)";
std::string After =
runClangRenameOnCode(Before, "::X", "ns::X");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, MoveFromGlobalToNamespaceWithLeadingDotDot) {
std::string Before = R"(
void Y() {}
// Assume that the reference is in another file.
namespace some_ns {
void f() { Y(); }
}
)";
std::string Expected = R"(
void Y() {}
// Assume that the reference is in another file.
namespace some_ns {
void f() { ::ns::Y(); }
}
)";
std::string After =
runClangRenameOnCode(Before, "::Y", "::ns::Y");
CompareSnippets(Expected, After);
}
// FIXME: the rename of overloaded operator is not fully supported yet.
TEST_F(RenameFunctionTest, DISABLED_DoNotRenameOverloadedOperatorCalls) {
std::string Before = R"(
namespace old_ns {
class T { public: int x; };
bool operator==(const T& lhs, const T& rhs) {
return lhs.x == rhs.x;
}
} // namespace old_ns
// Assume that the reference is in another file.
bool f() {
auto eq = old_ns::operator==;
old_ns::T t1, t2;
old_ns::operator==(t1, t2);
return t1 == t2;
}
)";
std::string Expected = R"(
namespace old_ns {
class T { public: int x; };
bool operator==(const T& lhs, const T& rhs) {
return lhs.x == rhs.x;
}
} // namespace old_ns
// Assume that the reference is in another file.
bool f() {
auto eq = new_ns::operator==;
old_ns::T t1, t2;
new_ns::operator==(t1, t2);
return t1 == t2;
}
)";
std::string After =
runClangRenameOnCode(Before, "old_ns::operator==", "new_ns::operator==");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, FunctionRefAsTemplate) {
std::string Before = R"(
void X();
// Assume that the reference is in another file.
namespace some_ns {
template <void (*Func)(void)>
class TIterator {};
template <void (*Func)(void)>
class T {
public:
typedef TIterator<Func> IterType;
using TI = TIterator<Func>;
void g() {
Func();
auto func = Func;
TIterator<Func> iter;
}
};
void f() { T<X> tx; tx.g(); }
} // namespace some_ns
)";
std::string Expected = R"(
void X();
// Assume that the reference is in another file.
namespace some_ns {
template <void (*Func)(void)>
class TIterator {};
template <void (*Func)(void)>
class T {
public:
typedef TIterator<Func> IterType;
using TI = TIterator<Func>;
void g() {
Func();
auto func = Func;
TIterator<Func> iter;
}
};
void f() { T<ns::X> tx; tx.g(); }
} // namespace some_ns
)";
std::string After = runClangRenameOnCode(Before, "::X", "ns::X");
CompareSnippets(Expected, After);
}
TEST_F(RenameFunctionTest, RenameFunctionInUsingDecl) {
std::string Before = R"(
using base::ToNanoSeconds;
namespace old_ns {
using base::ToNanoSeconds;
void f() {
using base::ToNanoSeconds;
}
}
)";
std::string Expected = R"(
using base::ToInt64NanoSeconds;
namespace old_ns {
using base::ToInt64NanoSeconds;
void f() {
using base::ToInt64NanoSeconds;
}
}
)";
std::string After = runClangRenameOnCode(Before, "base::ToNanoSeconds",
"base::ToInt64NanoSeconds");
CompareSnippets(Expected, After);
}
// FIXME: Fix the complex the case where the symbol being renamed is located in
// `std::function<decltype<renamed_symbol>>`.
TEST_F(ClangRenameTest, DISABLED_ReferencesInLambdaFunctionParameters) {
std::string Before = R"(
template <class T>
class function;
template <class R, class... ArgTypes>
class function<R(ArgTypes...)> {
public:
template <typename Functor>
function(Functor f) {}
function() {}
R operator()(ArgTypes...) const {}
};
namespace ns {
void Old() {}
void f() {
function<decltype(Old)> func;
}
} // namespace ns)";
std::string Expected = R"(
template <class T>
class function;
template <class R, class... ArgTypes>
class function<R(ArgTypes...)> {
public:
template <typename Functor>
function(Functor f) {}
function() {}
R operator()(ArgTypes...) const {}
};
namespace ns {
void New() {}
void f() {
function<decltype(::new_ns::New)> func;
}
} // namespace ns)";
std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang

@ -1,228 +0,0 @@
//===-- ClangMemberTests.cpp - unit tests for renaming class members ------===//
//
// 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 "ClangRenameTest.h"
namespace clang {
namespace clang_rename {
namespace test {
namespace {
class RenameMemberTest : public ClangRenameTest {
public:
RenameMemberTest() {
AppendToHeader(R"(
struct NA {
void Foo();
void NotFoo();
static void SFoo();
static void SNotFoo();
int Moo;
};
struct A {
virtual void Foo();
void NotFoo();
static void SFoo();
static void SNotFoo();
int Moo;
int NotMoo;
static int SMoo;
};
struct B : public A {
void Foo() override;
};
template <typename T> struct TA {
T* Foo();
T* NotFoo();
static T* SFoo();
static T* NotSFoo();
};
template <typename T> struct TB : public TA<T> {};
namespace ns {
template <typename T> struct TA {
T* Foo();
T* NotFoo();
static T* SFoo();
static T* NotSFoo();
static int SMoo;
};
template <typename T> struct TB : public TA<T> {};
struct A {
void Foo();
void NotFoo();
static void SFoo();
static void SNotFoo();
};
struct B : public A {};
struct C {
template <class T>
void SFoo(const T& t) {}
template <class T>
void Foo() {}
};
})");
}
};
INSTANTIATE_TEST_SUITE_P(
DISABLED_RenameTemplatedClassStaticVariableTest, RenameMemberTest,
testing::ValuesIn(std::vector<Case>({
// FIXME: support renaming static variables for template classes.
{"void f() { ns::TA<int>::SMoo; }",
"void f() { ns::TA<int>::SMeh; }", "ns::TA::SMoo", "ns::TA::SMeh"},
})) );
INSTANTIATE_TEST_SUITE_P(
RenameMemberTest, RenameMemberTest,
testing::ValuesIn(std::vector<Case>({
// Normal methods and fields.
{"void f() { A a; a.Foo(); }", "void f() { A a; a.Bar(); }", "A::Foo",
"A::Bar"},
{"void f() { ns::A a; a.Foo(); }", "void f() { ns::A a; a.Bar(); }",
"ns::A::Foo", "ns::A::Bar"},
{"void f() { A a; int x = a.Moo; }", "void f() { A a; int x = a.Meh; }",
"A::Moo", "A::Meh"},
{"void f() { B b; b.Foo(); }", "void f() { B b; b.Bar(); }", "B::Foo",
"B::Bar"},
{"void f() { ns::B b; b.Foo(); }", "void f() { ns::B b; b.Bar(); }",
"ns::A::Foo", "ns::A::Bar"},
{"void f() { B b; int x = b.Moo; }", "void f() { B b; int x = b.Meh; }",
"A::Moo", "A::Meh"},
// Static methods.
{"void f() { A::SFoo(); }", "void f() { A::SBar(); }", "A::SFoo",
"A::SBar"},
{"void f() { ns::A::SFoo(); }", "void f() { ns::A::SBar(); }",
"ns::A::SFoo", "ns::A::SBar"},
{"void f() { TA<int>::SFoo(); }", "void f() { TA<int>::SBar(); }",
"TA::SFoo", "TA::SBar"},
{"void f() { ns::TA<int>::SFoo(); }",
"void f() { ns::TA<int>::SBar(); }", "ns::TA::SFoo", "ns::TA::SBar"},
// Static variables.
{"void f() { A::SMoo; }",
"void f() { A::SMeh; }", "A::SMoo", "A::SMeh"},
// Templated methods.
{"void f() { TA<int> a; a.Foo(); }", "void f() { TA<int> a; a.Bar(); }",
"TA::Foo", "TA::Bar"},
{"void f() { ns::TA<int> a; a.Foo(); }",
"void f() { ns::TA<int> a; a.Bar(); }", "ns::TA::Foo", "ns::TA::Bar"},
{"void f() { TB<int> b; b.Foo(); }", "void f() { TB<int> b; b.Bar(); }",
"TA::Foo", "TA::Bar"},
{"void f() { ns::TB<int> b; b.Foo(); }",
"void f() { ns::TB<int> b; b.Bar(); }", "ns::TA::Foo", "ns::TA::Bar"},
{"void f() { ns::C c; int x; c.SFoo(x); }",
"void f() { ns::C c; int x; c.SBar(x); }", "ns::C::SFoo",
"ns::C::SBar"},
{"void f() { ns::C c; c.Foo<int>(); }",
"void f() { ns::C c; c.Bar<int>(); }", "ns::C::Foo", "ns::C::Bar"},
// Pointers to methods.
{"void f() { auto p = &A::Foo; }", "void f() { auto p = &A::Bar; }",
"A::Foo", "A::Bar"},
{"void f() { auto p = &A::SFoo; }", "void f() { auto p = &A::SBar; }",
"A::SFoo", "A::SBar"},
{"void f() { auto p = &B::Foo; }", "void f() { auto p = &B::Bar; }",
"B::Foo", "B::Bar"},
{"void f() { auto p = &ns::A::Foo; }",
"void f() { auto p = &ns::A::Bar; }", "ns::A::Foo", "ns::A::Bar"},
{"void f() { auto p = &ns::A::SFoo; }",
"void f() { auto p = &ns::A::SBar; }", "ns::A::SFoo", "ns::A::SBar"},
{"void f() { auto p = &ns::C::SFoo<int>; }",
"void f() { auto p = &ns::C::SBar<int>; }", "ns::C::SFoo",
"ns::C::SBar"},
// These methods are not declared or overridden in the subclass B, we
// have to use the qualified name with parent class A to identify them.
{"void f() { auto p = &ns::B::Foo; }",
"void f() { auto p = &ns::B::Bar; }", "ns::A::Foo", "ns::B::Bar"},
{"void f() { B::SFoo(); }", "void f() { B::SBar(); }", "A::SFoo",
"B::SBar"},
{"void f() { ns::B::SFoo(); }", "void f() { ns::B::SBar(); }",
"ns::A::SFoo", "ns::B::SBar"},
{"void f() { auto p = &B::SFoo; }", "void f() { auto p = &B::SBar; }",
"A::SFoo", "B::SBar"},
{"void f() { auto p = &ns::B::SFoo; }",
"void f() { auto p = &ns::B::SBar; }", "ns::A::SFoo", "ns::B::SBar"},
{"void f() { TB<int>::SFoo(); }", "void f() { TB<int>::SBar(); }",
"TA::SFoo", "TB::SBar"},
{"void f() { ns::TB<int>::SFoo(); }",
"void f() { ns::TB<int>::SBar(); }", "ns::TA::SFoo", "ns::TB::SBar"},
})) );
TEST_P(RenameMemberTest, RenameMembers) {
auto Param = GetParam();
assert(!Param.OldName.empty());
assert(!Param.NewName.empty());
std::string Actual =
runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
CompareSnippets(Param.After, Actual);
}
TEST_F(RenameMemberTest, RenameMemberInsideClassMethods) {
std::string Before = R"(
struct X {
int Moo;
void Baz() { Moo = 1; }
};)";
std::string Expected = R"(
struct X {
int Meh;
void Baz() { Meh = 1; }
};)";
std::string After = runClangRenameOnCode(Before, "X::Moo", "Y::Meh");
CompareSnippets(Expected, After);
}
TEST_F(RenameMemberTest, RenameMethodInsideClassMethods) {
std::string Before = R"(
struct X {
void Foo() {}
void Baz() { Foo(); }
};)";
std::string Expected = R"(
struct X {
void Bar() {}
void Baz() { Bar(); }
};)";
std::string After = runClangRenameOnCode(Before, "X::Foo", "X::Bar");
CompareSnippets(Expected, After);
}
TEST_F(RenameMemberTest, RenameCtorInitializer) {
std::string Before = R"(
class X {
public:
X();
A a;
A a2;
B b;
};
X::X():a(), b() {}
)";
std::string Expected = R"(
class X {
public:
X();
A bar;
A a2;
B b;
};
X::X():bar(), b() {}
)";
std::string After = runClangRenameOnCode(Before, "X::a", "X::bar");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang

@ -83,7 +83,6 @@ group("test") {
"//clang-tools-extra/unittests",
"//clang/lib/Headers",
"//clang/tools/c-index-test",
"//clang/tools/clang-rename",
"//clang/tools/driver:symlinks",
"//llvm/tools/llvm-bcanalyzer",
"//llvm/utils/FileCheck",

@ -171,7 +171,6 @@ group("test") {
"//clang/tools/clang-installapi",
"//clang/tools/clang-offload-bundler",
"//clang/tools/clang-refactor",
"//clang/tools/clang-rename",
"//clang/tools/clang-repl",
"//clang/tools/clang-scan-deps",
"//clang/tools/diagtool",

@ -1,14 +0,0 @@
executable("clang-rename") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
"//clang/lib/Frontend",
"//clang/lib/Rewrite",
"//clang/lib/Tooling",
"//clang/lib/Tooling/Core",
"//clang/lib/Tooling/Refactoring",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
sources = [ "ClangRename.cpp" ]
}

@ -26,7 +26,6 @@ exports_files([
"tools/clang-format/clang-format.el",
"tools/clang-format/clang-format-test.el",
"tools/clang-format/clang-format.py",
"tools/clang-rename/clang-rename.el",
"tools/extra/clang-include-fixer/tool/clang-include-fixer.el",
"tools/extra/clang-include-fixer/tool/clang-include-fixer-test.el",
])
@ -2590,20 +2589,6 @@ cc_binary(
],
)
cc_binary(
name = "clang-rename",
srcs = glob(["tools/clang-rename/*.cpp"]),
stamp = 0,
deps = [
":basic",
":frontend",
":rewrite",
":tooling",
":tooling_refactoring",
"//llvm:Support",
],
)
cc_binary(
name = "clang-repl",
srcs = glob(["tools/clang-repl/*.cpp"]),