Skip to content

Commit

Permalink
[change-namespace] fix qualifier of function references.
Browse files Browse the repository at this point in the history
Reviewers: hokein

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D24803

llvm-svn: 282146
  • Loading branch information
Eric Liu committed Sep 22, 2016
1 parent 2146a0a commit 12068d8
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 4 deletions.
38 changes: 34 additions & 4 deletions clang-tools-extra/change-namespace/ChangeNamespace.cpp
Expand Up @@ -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.
Expand Down Expand Up @@ -283,6 +282,22 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
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(
Expand All @@ -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);
}
}

Expand Down
Expand Up @@ -314,6 +314,43 @@ TEST_F(ChangeNamespaceTest, TypeInNestedNameSpecifier) {
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

0 comments on commit 12068d8

Please sign in to comment.