[clang-tools-extra] r290176 - [change-namespace] do not fix calls to overloaded operator functions.
Eric Liu via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 20 06:39:04 PST 2016
Author: ioeric
Date: Tue Dec 20 08:39:04 2016
New Revision: 290176
URL: http://llvm.org/viewvc/llvm-project?rev=290176&view=rev
Log:
[change-namespace] do not fix calls to overloaded operator functions.
Summary: Also make sure one function reference is only processed once.
Reviewers: hokein
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D27982
Modified:
clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
clang-tools-extra/trunk/change-namespace/ChangeNamespace.h
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=290176&r1=290175&r2=290176&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Tue Dec 20 08:39:04 2016
@@ -481,6 +481,11 @@ void ChangeNamespaceTool::run(
llvm::cast<NamedDecl>(Var), VarRef);
} else if (const auto *FuncRef =
Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
+ // If this reference has been processed as a function call, we do not
+ // process it again.
+ if (ProcessedFuncRefs.count(FuncRef))
+ return;
+ ProcessedFuncRefs.insert(FuncRef);
const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
assert(Func);
const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
@@ -490,8 +495,16 @@ void ChangeNamespaceTool::run(
} else {
const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
assert(Call != nullptr && "Expecting callback for CallExpr.");
+ const auto *CalleeFuncRef =
+ llvm::cast<DeclRefExpr>(Call->getCallee()->IgnoreImplicit());
+ ProcessedFuncRefs.insert(CalleeFuncRef);
const FunctionDecl *Func = Call->getDirectCallee();
assert(Func != nullptr);
+ // FIXME: ignore overloaded operators. This would miss cases where operators
+ // are called by qualified names (i.e. "ns::operator <"). Ignore such
+ // cases for now.
+ if (Func->isOverloadedOperator())
+ return;
// Ignore out-of-line static methods since they will be handled by nested
// name specifiers.
if (Func->getCanonicalDecl()->getStorageClass() ==
Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.h?rev=290176&r1=290175&r2=290176&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.h (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.h Tue Dec 20 08:39:04 2016
@@ -157,6 +157,10 @@ private:
// TypeLocs of CXXCtorInitializer. Types of CXXCtorInitializers do not need to
// be fixed.
llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;
+ // Since a DeclRefExpr for a function call can be matched twice (one as
+ // CallExpr and one as DeclRefExpr), we record all DeclRefExpr's that have
+ // been processed so that we don't handle them twice.
+ llvm::SmallPtrSet<const clang::DeclRefExpr*, 16> ProcessedFuncRefs;
};
} // namespace change_namespace
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=290176&r1=290175&r2=290176&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Tue Dec 20 08:39:04 2016
@@ -575,6 +575,47 @@ TEST_F(ChangeNamespaceTest, FixFunctionN
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
}
+TEST_F(ChangeNamespaceTest, FixOverloadedOperatorFunctionNameSpecifiers) {
+ std::string Code =
+ "namespace na {\n"
+ "class A {\n"
+ "public:\n"
+ " int x;\n"
+ " bool operator==(const A &RHS) const { return x == RHS.x; }\n"
+ "};\n"
+ "bool operator<(const A &LHS, const A &RHS) { return LHS.x == RHS.x; }\n"
+ "namespace nb {\n"
+ "bool f() {\n"
+ " A x, y;\n"
+ " auto f = operator<;\n"
+ " return (x == y) && (x < y) && (operator<(x, y));\n"
+ "}\n"
+ "} // namespace nb\n"
+ "} // namespace na\n";
+ std::string Expected =
+ "namespace na {\n"
+ "class A {\n"
+ "public:\n"
+ " int x;\n"
+ " bool operator==(const A &RHS) const { return x == RHS.x; }\n"
+ "};\n"
+ "bool operator<(const A &LHS, const A &RHS) { return LHS.x == RHS.x; }\n"
+ "\n"
+ "} // namespace na\n"
+ "namespace x {\n"
+ "namespace y {\n"
+ "bool f() {\n"
+ " ::na::A x, y;\n"
+ " auto f = ::na::operator<;\n"
+ // FIXME: function calls to overloaded operators are not fixed now even if
+ // they are referenced by qualified names.
+ " return (x == y) && (x < y) && (operator<(x,y));\n"
+ "}\n"
+ "} // namespace y\n"
+ "} // namespace x\n";
+ EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
+}
+
TEST_F(ChangeNamespaceTest, FixNonCallingFunctionReferences) {
std::string Code = "namespace na {\n"
"class A {\n"
More information about the cfe-commits
mailing list