mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-10-10 21:04:56 +00:00
[change-namespace] fix namespace specifier of global variables.
Reviewers: hokein Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D24963 llvm-svn: 282837
This commit is contained in:
parent
de03ff7063
commit
159f0135b1
@ -230,8 +230,6 @@ ChangeNamespaceTool::ChangeNamespaceTool(
|
||||
DiffNewNamespace = joinNamespaces(NewNsSplitted);
|
||||
}
|
||||
|
||||
// FIXME: handle the following symbols:
|
||||
// - Variable references.
|
||||
void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
|
||||
// Match old namespace blocks.
|
||||
std::string FullOldNs = "::" + OldNamespace;
|
||||
@ -303,6 +301,14 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
|
||||
IsInMovedNs, unless(isImplicit()))
|
||||
.bind("dc"),
|
||||
this);
|
||||
|
||||
auto GlobalVarMatcher = varDecl(
|
||||
hasGlobalStorage(), hasParent(namespaceDecl()),
|
||||
unless(anyOf(IsInMovedNs, hasAncestor(namespaceDecl(isAnonymous())))));
|
||||
Finder->addMatcher(declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")),
|
||||
to(GlobalVarMatcher.bind("var_decl")))
|
||||
.bind("var_ref"),
|
||||
this);
|
||||
}
|
||||
|
||||
void ChangeNamespaceTool::run(
|
||||
@ -324,8 +330,19 @@ void ChangeNamespaceTool::run(
|
||||
} else if (const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type")) {
|
||||
fixTypeLoc(Result, startLocationForType(*TLoc), EndLocationForType(*TLoc),
|
||||
*TLoc);
|
||||
} else if (const auto *VarRef = Result.Nodes.getNodeAs<DeclRefExpr>("var_ref")){
|
||||
const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var_decl");
|
||||
assert(Var);
|
||||
if (Var->getCanonicalDecl()->isStaticDataMember())
|
||||
return;
|
||||
std::string Name = Var->getQualifiedNameAsString();
|
||||
const clang::Decl *Context = Result.Nodes.getNodeAs<clang::Decl>("dc");
|
||||
assert(Context && "Empty decl context.");
|
||||
clang::SourceRange VarRefRange = VarRef->getSourceRange();
|
||||
replaceQualifiedSymbolInDeclContext(Result, Context, VarRefRange.getBegin(),
|
||||
VarRefRange.getEnd(), Name);
|
||||
} else {
|
||||
const auto* Call = Result.Nodes.getNodeAs<clang::CallExpr>("call");
|
||||
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);
|
||||
|
@ -447,6 +447,72 @@ TEST_F(ChangeNamespaceTest, FixFunctionNameSpecifiers) {
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, MoveAndFixGlobalVariables) {
|
||||
std::string Code = "namespace na {\n"
|
||||
"int GlobA;\n"
|
||||
"static int GlobAStatic = 0;\n"
|
||||
"namespace nc { int GlobC; }\n"
|
||||
"namespace nb {\n"
|
||||
"int GlobB;\n"
|
||||
"void f() {\n"
|
||||
" int a = GlobA;\n"
|
||||
" int b = GlobAStatic;\n"
|
||||
" int c = nc::GlobC;\n"
|
||||
"}\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace na {\n"
|
||||
"int GlobA;\n"
|
||||
"static int GlobAStatic = 0;\n"
|
||||
"namespace nc { int GlobC; }\n"
|
||||
"\n"
|
||||
"} // namespace na\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"int GlobB;\n"
|
||||
"void f() {\n"
|
||||
" int a = na::GlobA;\n"
|
||||
" int b = na::GlobAStatic;\n"
|
||||
" int c = na::nc::GlobC;\n"
|
||||
"}\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, DoNotFixStaticVariableOfClass) {
|
||||
std::string Code = "namespace na {\n"
|
||||
"class A {\n"
|
||||
"public:\n"
|
||||
"static int A1;\n"
|
||||
"static int A2;\n"
|
||||
"}\n"
|
||||
"static int A::A1 = 0;\n"
|
||||
"namespace nb {\n"
|
||||
"void f() { int a = A::A1; int b = A::A2; }"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace na {\n"
|
||||
"class A {\n"
|
||||
"public:\n"
|
||||
"static int A1;\n"
|
||||
"static int A2;\n"
|
||||
"}\n"
|
||||
"static int A::A1 = 0;\n"
|
||||
"\n"
|
||||
"} // namespace na\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"void f() { int a = na::A::A1; int b = na::A::A2; }"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace change_namespace
|
||||
} // namespace clang
|
||||
|
Loading…
Reference in New Issue
Block a user