forked from OSchip/llvm-project
[change-namespace] consider typedef/using alias decls in the moved namespace.
Summary: If a TypeLoc refers to a type alias defined in the moved namespace, we do not need to update its specifier since the type alias decl will be moved along with the type reference. Reviewers: hokein Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D26592 llvm-svn: 286873
This commit is contained in:
parent
10e59fac3e
commit
3215886b7a
|
@ -621,8 +621,27 @@ void ChangeNamespaceTool::fixTypeLoc(
|
|||
const auto *FromDecl = Result.Nodes.getNodeAs<NamedDecl>("from_decl");
|
||||
// `hasDeclaration` gives underlying declaration, but if the type is
|
||||
// a typedef type, we need to use the typedef type instead.
|
||||
if (auto *Typedef = Type.getType()->getAs<TypedefType>())
|
||||
if (auto *Typedef = Type.getType()->getAs<TypedefType>()) {
|
||||
FromDecl = Typedef->getDecl();
|
||||
auto IsInMovedNs = [&](const NamedDecl *D) {
|
||||
if (!llvm::StringRef(D->getQualifiedNameAsString())
|
||||
.startswith(OldNamespace + "::"))
|
||||
return false;
|
||||
auto ExpansionLoc =
|
||||
Result.SourceManager->getExpansionLoc(D->getLocStart());
|
||||
if (ExpansionLoc.isInvalid())
|
||||
return false;
|
||||
llvm::StringRef Filename =
|
||||
Result.SourceManager->getFilename(ExpansionLoc);
|
||||
llvm::Regex RE(FilePattern);
|
||||
return RE.match(Filename);
|
||||
};
|
||||
// Don't fix the \p Type if it refers to a type alias decl in the moved
|
||||
// namespace since the alias decl will be moved along with the type
|
||||
// reference.
|
||||
if (IsInMovedNs(FromDecl))
|
||||
return;
|
||||
}
|
||||
|
||||
const Decl *DeclCtx = Result.Nodes.getNodeAs<Decl>("dc");
|
||||
assert(DeclCtx && "Empty decl context.");
|
||||
|
|
|
@ -822,22 +822,22 @@ TEST_F(ChangeNamespaceTest, UsingShadowDeclInFunction) {
|
|||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, UsingShadowDeclInClass) {
|
||||
std::string Code = "namespace na { class C_A {};\n }\n"
|
||||
std::string Code = "namespace na { class C_A {}; }\n"
|
||||
"namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"void f() {\n"
|
||||
" using na::CA;\n"
|
||||
" CA ca;\n"
|
||||
" using ::na::C_A;\n"
|
||||
" C_A ca;\n"
|
||||
"}\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
std::string Expected = "namespace na { class C_A {};\n }\n"
|
||||
std::string Expected = "namespace na { class C_A {}; }\n"
|
||||
"\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"void f() {\n"
|
||||
" using na::CA;\n"
|
||||
" CA ca;\n"
|
||||
" using ::na::C_A;\n"
|
||||
" C_A ca;\n"
|
||||
"}\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
|
@ -941,6 +941,70 @@ TEST_F(ChangeNamespaceTest, UsingDeclInTheParentOfOldNamespace) {
|
|||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, UsingAliasDecl) {
|
||||
std::string Code =
|
||||
"namespace nx { namespace ny { class X {}; } }\n"
|
||||
"namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"using Y = nx::ny::X;\n"
|
||||
"void f() { Y y; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace nx { namespace ny { class X {}; } }\n"
|
||||
"\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"using Y = nx::ny::X;\n"
|
||||
"void f() { Y y; }\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, UsingAliasDeclInGlobal) {
|
||||
std::string Code =
|
||||
"namespace nx { namespace ny { class X {}; } }\n"
|
||||
"using Y = nx::ny::X;\n"
|
||||
"namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"void f() { Y y; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace nx { namespace ny { class X {}; } }\n"
|
||||
"using Y = nx::ny::X;\n"
|
||||
"\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"void f() { Y y; }\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ChangeNamespaceTest, TypedefAliasDecl) {
|
||||
std::string Code =
|
||||
"namespace nx { namespace ny { class X {}; } }\n"
|
||||
"namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"typedef nx::ny::X Y;\n"
|
||||
"void f() { Y y; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace nx { namespace ny { class X {}; } }\n"
|
||||
"\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"typedef nx::ny::X Y;\n"
|
||||
"void f() { Y y; }\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace change_namespace
|
||||
} // namespace clang
|
||||
|
|
Loading…
Reference in New Issue