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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits