xaizek / unused-funcs (License: GPLv2+) (since 2018-12-07)
Clang-based standalone tool that detects unused external functions in a set of source files.
Commit 0777cb152b66e2c37fe33b7253d93757833ff4cb

Move matchers to a separate file
Mainly to get cleaner main file.
Author: xaizek
Author date (UTC): 2014-04-06 09:20
Committer name: xaizek
Committer date (UTC): 2014-04-06 09:58
Parent(s): 67998d6be8629f48508935b8af7fdc64cd79f1d8
Signing key:
Tree: d7e3aa3acd9fe299fb58c3ffeb56c75577f03eb5
File Lines added Lines deleted
CMakeLists.txt 1 1
Finder.cpp 140 0
Finder.hpp 50 0
unused-funcs.cpp 3 71
File CMakeLists.txt changed (mode: 100644) (index e35d7a2..b353eec)
1 1 set(LLVM_LINK_COMPONENTS support) set(LLVM_LINK_COMPONENTS support)
2 2 set(LLVM_USED_LIBS clangTooling clangBasic clangAST) set(LLVM_USED_LIBS clangTooling clangBasic clangAST)
3 3
4 add_clang_executable(unused-funcs unused-funcs.cpp)
4 add_clang_executable(unused-funcs unused-funcs.cpp Finder.cpp)
5 5 target_link_libraries(unused-funcs clangTooling clangBasic clangASTMatchers) target_link_libraries(unused-funcs clangTooling clangBasic clangASTMatchers)
File Finder.cpp added (mode: 100644) (index 0000000..4b224b1)
1 /*
2 * unused-funcs
3 *
4 * Copyright (C) 2014 xaizek.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "Finder.hpp"
22
23 #include <iostream>
24
25 #include <clang/Basic/SourceLocation.h>
26 #include <clang/Basic/SourceManager.h>
27
28 #include <clang/ASTMatchers/ASTMatchFinder.h>
29
30 using namespace clang::ast_matchers;
31
32 static DeclarationMatcher funcDecl = functionDecl().bind("func");
33 static StatementMatcher invocation = callExpr().bind("call");
34
35 namespace
36 {
37
38 class MatchHelper : public MatchFinder::MatchCallback
39 {
40 typedef MatchFinder::MatchResult Result;
41
42 public:
43 virtual void run(const Result &result);
44
45 private:
46 void printOut(const Result &result, const clang::CallExpr *call) const;
47
48 void printOut(const Result &result, const clang::FunctionDecl *func) const;
49 };
50
51 void
52 MatchHelper::run(const Result &result)
53 {
54 typedef clang::FunctionDecl Func;
55 typedef clang::CallExpr Call;
56
57 if (const Func *func = result.Nodes.getNodeAs<Func>("func")) {
58 if (func->isExternallyVisible()) {
59 printOut(result, func);
60 }
61 } else if (const Call *call = result.Nodes.getNodeAs<Call>("call")) {
62 printOut(result, call);
63 }
64 }
65
66 void
67 MatchHelper::printOut(const Result &result,
68 const clang::CallExpr *call) const
69 {
70 clang::FullSourceLoc fullLoc(call->getLocStart(), *result.SourceManager);
71
72 const std::string &fileName = result.SourceManager->getFilename(fullLoc);
73 const unsigned int lineNum = fullLoc.getSpellingLineNumber();
74
75 std::cout << fileName
76 << ":"
77 << lineNum
78 << ":call of "
79 << call->getDirectCallee()->getNameAsString()
80 << '\n';
81 }
82
83 void
84 MatchHelper::printOut(const Result &result,
85 const clang::FunctionDecl *func) const
86 {
87 clang::FullSourceLoc fullLoc(func->getLocStart(), *result.SourceManager);
88
89 const std::string &fileName = result.SourceManager->getFilename(fullLoc);
90 const unsigned int lineNum = fullLoc.getSpellingLineNumber();
91
92 std::cout << fileName
93 << ":"
94 << lineNum
95 << ":declaration of "
96 << func->getNameAsString()
97 << '\n';
98 }
99
100 }
101
102 class Finder::Impl
103 {
104 public:
105 Impl();
106
107 public:
108 MatchFinder & getMatchFinder();
109
110 private:
111 MatchHelper helper;
112 MatchFinder matchFinder;
113 };
114
115 Finder::Impl::Impl()
116 {
117 matchFinder.addMatcher(funcDecl, &helper);
118 matchFinder.addMatcher(invocation, &helper);
119 }
120
121 Finder::MatchFinder &
122 Finder::Impl::getMatchFinder()
123 {
124 return matchFinder;
125 }
126
127 Finder::Finder()
128 :impl(new Impl())
129 {
130 }
131
132 Finder::~Finder()
133 {
134 }
135
136 Finder::MatchFinder &
137 Finder::getMatchFinder()
138 {
139 return impl->getMatchFinder();
140 }
File Finder.hpp added (mode: 100644) (index 0000000..6a3e3ee)
1 /*
2 * unused-funcs
3 *
4 * Copyright (C) 2014 xaizek.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #ifndef UNUSED_FUNCS__FINDER_HPP__
22 #define UNUSED_FUNCS__FINDER_HPP__
23
24 #include <memory>
25
26 #include <clang/ASTMatchers/ASTMatchFinder.h>
27
28 class Finder
29 {
30 typedef clang::ast_matchers::MatchFinder MatchFinder;
31
32 public:
33 Finder();
34 ~Finder();
35
36 public:
37 MatchFinder & getMatchFinder();
38
39 private:
40 // these operations are forbidden
41 Finder(const Finder &rhs);
42 Finder & operator=(const Finder &rhs);
43
44 private:
45 class Impl;
46
47 const std::auto_ptr<Impl> impl;
48 };
49
50 #endif // UNUSED_FUNCS__FINDER_HPP__
File unused-funcs.cpp changed (mode: 100644) (index 0bc7973..8017e1b)
18 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 19 */ */
20 20
21 #include <iostream>
22
23 21 #include <llvm/Support/CommandLine.h> #include <llvm/Support/CommandLine.h>
24 22
25 #include <clang/ASTMatchers/ASTMatchFinder.h>
26 #include <clang/ASTMatchers/ASTMatchers.h>
27
28 23 #include <clang/Tooling/CommonOptionsParser.h> #include <clang/Tooling/CommonOptionsParser.h>
29 24 #include <clang/Tooling/Tooling.h> #include <clang/Tooling/Tooling.h>
30 25
31 #include <clang/Basic/SourceLocation.h>
32 #include <clang/Basic/SourceManager.h>
26 #include "Finder.hpp"
33 27
34 using namespace clang;
35 using namespace clang::ast_matchers;
36 28 using namespace clang::tooling; using namespace clang::tooling;
37 29
38 30 static llvm::cl::OptionCategory toolCategory("unused-funcs options"); static llvm::cl::OptionCategory toolCategory("unused-funcs options");
39 31
40 32 static llvm::cl::extrahelp commonHelp(CommonOptionsParser::HelpMessage); static llvm::cl::extrahelp commonHelp(CommonOptionsParser::HelpMessage);
41 33
42 static DeclarationMatcher funcDecl = functionDecl().bind("func");
43 static StatementMatcher invocation = callExpr().bind("call");
44
45 class MatchHelper : public MatchFinder::MatchCallback
46 {
47 public:
48 virtual void run(const MatchFinder::MatchResult &result)
49 {
50 using namespace clang;
51
52 typedef FunctionDecl Func;
53 typedef CallExpr Call;
54
55 if (const Func *func = result.Nodes.getNodeAs<Func>("func")) {
56 if (func->isExternallyVisible()) {
57 printOut(result, func);
58 }
59 } else if (const Call *call = result.Nodes.getNodeAs<Call>("call")) {
60 printOut(result, call);
61 }
62 }
63
64 private:
65 void printOut(const MatchFinder::MatchResult &result,
66 const CallExpr *call) const
67 {
68 FullSourceLoc fullLoc(call->getLocStart(), *result.SourceManager);
69
70 const std::string &fileName = result.SourceManager->getFilename(fullLoc);
71 const unsigned int lineNum = fullLoc.getSpellingLineNumber();
72
73 std::cout << fileName
74 << ":"
75 << lineNum
76 << ":call of "
77 << call->getDirectCallee()->getNameAsString()
78 << '\n';
79 }
80
81 void printOut(const MatchFinder::MatchResult &result,
82 const FunctionDecl *func) const
83 {
84 FullSourceLoc fullLoc(func->getLocStart(), *result.SourceManager);
85
86 const std::string &fileName = result.SourceManager->getFilename(fullLoc);
87 const unsigned int lineNum = fullLoc.getSpellingLineNumber();
88
89 std::cout << fileName
90 << ":"
91 << lineNum
92 << ":declaration of "
93 << func->getNameAsString()
94 << '\n';
95 }
96 };
97
98 34 int int
99 35 main(int argc, const char *argv[]) main(int argc, const char *argv[])
100 36 { {
 
... ... main(int argc, const char *argv[])
102 38 ClangTool tool(optionsParser.getCompilations(), ClangTool tool(optionsParser.getCompilations(),
103 39 optionsParser.getSourcePathList()); optionsParser.getSourcePathList());
104 40
105 MatchHelper helper;
106
107 MatchFinder finder;
108 finder.addMatcher(funcDecl, &helper);
109 finder.addMatcher(invocation, &helper);
41 Finder finder;
110 42
111 return tool.run(newFrontendActionFactory(&finder));
43 return tool.run(newFrontendActionFactory(&finder.getMatchFinder()));
112 44 } }
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/unused-funcs

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/unused-funcs

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master