[clang-tools-extra] r286873 - [change-namespace] consider typedef/using alias decls in the moved namespace.
Eric Liu via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 14 11:37:55 PST 2016
Author: ioeric
Date: Mon Nov 14 13:37:55 2016
New Revision: 286873
URL: http://llvm.org/viewvc/llvm-project?rev=286873&view=rev
Log:
[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
Modified:
clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp?rev=286873&r1=286872&r2=286873&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Mon Nov 14 13:37:55 2016
@@ -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.");
Modified: clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp?rev=286873&r1=286872&r2=286873&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Mon Nov 14 13:37:55 2016
@@ -822,22 +822,22 @@ TEST_F(ChangeNamespaceTest, UsingShadowD
}
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, UsingDeclInT
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
More information about the cfe-commits
mailing list