diff --git a/src/collectors/find_calls.cpp b/src/collectors/find_calls.cpp index 4c1a124..b9512b3 100644 --- a/src/collectors/find_calls.cpp +++ b/src/collectors/find_calls.cpp @@ -7,43 +7,47 @@ namespace clangmetatool { using namespace clang::ast_matchers; - class AnnotateCall1 - : public clang::ast_matchers::MatchFinder::MatchCallback { - private: - clang::CompilerInstance *ci; - FindCallsData *data; - public: - AnnotateCall1 - (clang::CompilerInstance* ci, - FindCallsData *data) - :ci(ci), data(data) {} - - virtual void - run(const clang::ast_matchers::MatchFinder::MatchResult &r) - override { - - const clang::CallExpr *c = - r.Nodes.getNodeAs("call"); - - const clang::FunctionDecl *f = - r.Nodes.getNodeAs("context"); - - const clang::DeclRefExpr *e = - r.Nodes.getNodeAs("ref"); - - data->call_context.insert - (std::pair - (f,c)); - - data->call_ref.insert - (std::pair - (c,e)); - - } + namespace { - }; + class AnnotateCall1 + : public clang::ast_matchers::MatchFinder::MatchCallback { + private: + clang::CompilerInstance *ci; + FindCallsData *data; + public: + AnnotateCall1 + (clang::CompilerInstance* ci, + FindCallsData *data) + :ci(ci), data(data) {} + + virtual void + run(const clang::ast_matchers::MatchFinder::MatchResult &r) + override { + + const clang::CallExpr *c = + r.Nodes.getNodeAs("call"); + + const clang::FunctionDecl *f = + r.Nodes.getNodeAs("context"); + + const clang::DeclRefExpr *e = + r.Nodes.getNodeAs("ref"); + + data->call_context.insert + (std::pair + (f,c)); + + data->call_ref.insert + (std::pair + (c,e)); + + } + + }; + + } // namespace anonymous class FindCallsImpl { private: diff --git a/src/collectors/find_cxx_member_calls.cpp b/src/collectors/find_cxx_member_calls.cpp index c80865d..e946148 100644 --- a/src/collectors/find_cxx_member_calls.cpp +++ b/src/collectors/find_cxx_member_calls.cpp @@ -10,34 +10,38 @@ namespace clangmetatool { using namespace clang::ast_matchers; - class AnnotateCall1 - : public clang::ast_matchers::MatchFinder::MatchCallback { - private: - clang::CompilerInstance *ci; - FindCXXMemberCallsData *data; - public: - AnnotateCall1 - (clang::CompilerInstance* ci, - FindCXXMemberCallsData *data) - :ci(ci), data(data) {} - - virtual void - run(const clang::ast_matchers::MatchFinder::MatchResult &r) - override { - - const auto c = - r.Nodes.getNodeAs("call"); - - const auto f = - r.Nodes.getNodeAs("context"); - - data->insert - (std::pair - (f,c)); - } - - }; + namespace { + + class AnnotateCall1 + : public clang::ast_matchers::MatchFinder::MatchCallback { + private: + clang::CompilerInstance *ci; + FindCXXMemberCallsData *data; + public: + AnnotateCall1 + (clang::CompilerInstance* ci, + FindCXXMemberCallsData *data) + :ci(ci), data(data) {} + + virtual void + run(const clang::ast_matchers::MatchFinder::MatchResult &r) + override { + + const auto c = + r.Nodes.getNodeAs("call"); + + const auto f = + r.Nodes.getNodeAs("context"); + + data->insert + (std::pair + (f,c)); + } + + }; + + } // namespace anonymous class FindCXXMemberCallsImpl { private: diff --git a/t/025-find-mixed-calls.t.cpp b/t/025-find-mixed-calls.t.cpp new file mode 100644 index 0000000..df82d7b --- /dev/null +++ b/t/025-find-mixed-calls.t.cpp @@ -0,0 +1,117 @@ +#include "clangmetatool-testconfig.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +class MyTool { +private: + clang::CompilerInstance* ci; + + std::string func = std::string("foo"); + + std::string cNC = std::string("NakedClass"); + std::string nNCfoo = std::string("foo"); + clangmetatool::collectors::FindCXXMemberCalls fcNCfoo; + std::string nNCbar = std::string("bar"); + clangmetatool::collectors::FindCXXMemberCalls fcNCbar; + + std::string cBC = std::string("suit::BusinessClass"); + std::string nBCbook = std::string("book"); + clangmetatool::collectors::FindCXXMemberCalls fcBCbook; + std::string nBCdiatribe = std::string("diatribe"); + clangmetatool::collectors::FindCXXMemberCalls fcBCdiatribe; + + std::string nHurdur = std::string("hurdur"); + clangmetatool::collectors::FindCalls fcHurdur; +public: + + MyTool(clang::CompilerInstance* ci, clang::ast_matchers::MatchFinder *f) + : ci(ci) + , fcNCfoo(ci, f, cNC, nNCfoo) + , fcNCbar(ci, f, cNC, nNCbar) + , fcBCbook(ci, f, cBC, nBCbook) + , fcBCdiatribe(ci, f, cBC, nBCdiatribe) + , fcHurdur(ci, f, nHurdur) + {} + + void validateMemberFind(clangmetatool::collectors::FindCXXMemberCalls& fc, + const std::string& c, const std::string n) { + const auto data = fc.getData(); + + ASSERT_EQ(1, data->size()); + + auto found = data->begin(); + + EXPECT_EQ(func, found->first->getNameInfo().getAsString()); + EXPECT_EQ(c, found->second->getRecordDecl()->getQualifiedNameAsString()); + EXPECT_EQ(n, found->second->getMethodDecl()->getNameAsString()); + } + + void postProcessing + (std::map &replacementsMap) { + validateMemberFind(fcNCfoo, cNC, nNCfoo); + validateMemberFind(fcNCbar, cNC, nNCbar); + validateMemberFind(fcBCbook, cBC, nBCbook); + validateMemberFind(fcBCdiatribe, cBC, nBCdiatribe); + + auto data = fcHurdur.getData(); + ASSERT_EQ(1, data->call_context.size()); + const auto& item = *data->call_context.begin(); + EXPECT_EQ(func, item.first->getNameAsString()); + EXPECT_EQ(nHurdur, item.second->getDirectCallee()->getNameAsString()); + } +}; + +TEST(use_meta_tool, factory) { + llvm::cl::OptionCategory MyToolCategory("my-tool options"); + + int argc = 4; + const char* argv[] = { + "foo", + CMAKE_SOURCE_DIR "/t/data/025-find-mixed-calls/foo.cpp", + "--", + "-xc++" + }; + + clang::tooling::CommonOptionsParser + optionsParser + ( argc, argv, + MyToolCategory ); + clang::tooling::RefactoringTool tool + ( optionsParser.getCompilations(), + optionsParser.getSourcePathList()); + + clangmetatool::MetaToolFactory< clangmetatool::MetaTool > + raf(tool.getReplacements()); + + int r = tool.runAndSave(&raf); + ASSERT_EQ(0, r); +} + + +// ---------------------------------------------------------------------------- +// Copyright 2018 Bloomberg Finance L.P. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/t/CMakeLists.txt b/t/CMakeLists.txt index 960afb3..1e5bc0b 100644 --- a/t/CMakeLists.txt +++ b/t/CMakeLists.txt @@ -32,6 +32,7 @@ foreach( 022-looping-integer-propagation 023-multi-function-integer-propagation 024-find-cxx-member-calls + 025-find-mixed-calls ) add_executable(${TEST}.t ${TEST}.t.cpp) diff --git a/t/data/025-find-mixed-calls/foo.cpp b/t/data/025-find-mixed-calls/foo.cpp new file mode 100644 index 0000000..bbebb3d --- /dev/null +++ b/t/data/025-find-mixed-calls/foo.cpp @@ -0,0 +1,29 @@ +class NakedClass { +public: + char foo(); + char bar(int* yo); +}; + +char hurdur(int*, char*, unsigned*); + +namespace suit { + +class BusinessClass { +public: + unsigned long book(); + unsigned long long diatribe(char** words) const; +}; + +} // namespace suit + +int foo(NakedClass* nakedC, suit::BusinessClass& businessC) { + nakedC->foo(); + businessC.book(); + + businessC.diatribe(0); + nakedC->bar(0); + + hurdur(0, 0, 0); + + return 777; +};