Author: ioeric Date: Thu Sep 22 06:54:00 2016 New Revision: 282146 URL: http://llvm.org/viewvc/llvm-project?rev=282146&view=rev Log: [change-namespace] fix qualifier of function references.
Reviewers: hokein Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D24803 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=282146&r1=282145&r2=282146&view=diff ============================================================================== --- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original) +++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Thu Sep 22 06:54:00 2016 @@ -231,7 +231,6 @@ ChangeNamespaceTool::ChangeNamespaceTool } // FIXME: handle the following symbols: -// - Function references. // - Variable references. void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) { // Match old namespace blocks. @@ -283,6 +282,22 @@ void ChangeNamespaceTool::registerMatche hasDeclaration(DeclMatcher.bind("from_decl")))))) .bind("nested_specifier_loc"), this); + + // Handle function. + // Only handle functions that are defined in a namespace excluding static + // methods (qualified by nested specifier) and functions defined in the global + // namespace. + // Note that the matcher does not exclude calls to out-of-line static method + // definitions, so we need to exclude them in the callback handler. + auto FuncMatcher = functionDecl( + hasParent(namespaceDecl()), + unless(anyOf(IsInMovedNs, hasAncestor(namespaceDecl(isAnonymous())), + hasAncestor(cxxRecordDecl())))); + Finder->addMatcher( + decl(forEachDescendant(callExpr(callee(FuncMatcher)).bind("call")), + IsInMovedNs) + .bind("dc"), + this); } void ChangeNamespaceTool::run( @@ -301,11 +316,26 @@ void ChangeNamespaceTool::run( SourceLocation Start = Specifier->getBeginLoc(); SourceLocation End = EndLocationForType(Specifier->getTypeLoc()); fixTypeLoc(Result, Start, End, Specifier->getTypeLoc()); - } else { - const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type"); - assert(TLoc != nullptr && "Expecting callback for TypeLoc"); + } else if (const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type")) { fixTypeLoc(Result, startLocationForType(*TLoc), EndLocationForType(*TLoc), *TLoc); + } else { + const auto* Call = Result.Nodes.getNodeAs<clang::CallExpr>("call"); + assert(Call != nullptr &&"Expecting callback for CallExpr."); + const clang::FunctionDecl* Func = Call->getDirectCallee(); + assert(Func != nullptr); + // Ignore out-of-line static methods since they will be handled by nested + // name specifiers. + if (Func->getCanonicalDecl()->getStorageClass() == + clang::StorageClass::SC_Static && + Func->isOutOfLine()) + return; + std::string Name = Func->getQualifiedNameAsString(); + const clang::Decl *Context = Result.Nodes.getNodeAs<clang::Decl>("dc"); + assert(Context && "Empty decl context."); + clang::SourceRange CalleeRange = Call->getCallee()->getSourceRange(); + replaceQualifiedSymbolInDeclContext(Result, Context, CalleeRange.getBegin(), + CalleeRange.getEnd(), Name); } } 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=282146&r1=282145&r2=282146&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original) +++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Thu Sep 22 06:54:00 2016 @@ -314,6 +314,43 @@ TEST_F(ChangeNamespaceTest, TypeInNested EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } +TEST_F(ChangeNamespaceTest, FixFunctionNameSpecifiers) { + std::string Code = + "namespace na {\n" + "class A {\n" + "public:\n" + " static void f() {}\n" + " static void g();\n" + "};\n" + "void A::g() {}" + "void a_f() {}\n" + "static void static_f() {}\n" + "namespace nb {\n" + "void f() { a_f(); static_f(); A::f(); }\n" + "void g() { f(); A::g(); }\n" + "} // namespace nb\n" + "} // namespace na\n"; + std::string Expected = + "namespace na {\n" + "class A {\n" + "public:\n" + " static void f() {}\n" + " static void g();\n" + "};\n" + "void A::g() {}" + "void a_f() {}\n" + "static void static_f() {}\n" + "\n" + "} // namespace na\n" + "namespace x {\n" + "namespace y {\n" + "void f() { na::a_f(); na::static_f(); na::A::f(); }\n" + "void g() { f(); na::A::g(); }\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