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 c1219b8781cf59e78bd5f0222e3d24001095913e

clean up method parameters
replace pointers by const references
consistently reordered method parameters
Author: Raphael Knaus
Author date (UTC): 2018-01-15 21:00
Committer name: Raphael Knaus
Committer date (UTC): 2018-01-15 21:10
Parent(s): ce605202319bd868f79712915ff23205aa05e624
Signing key:
Tree: 360b78ea655d8a2af6ab3579c7d1897beb25fb84
File Lines added Lines deleted
src/Finder.cpp 20 20
src/FuncInfo.cpp 10 10
src/FuncInfo.hpp 5 5
src/RefInfo.cpp 6 6
src/RefInfo.hpp 1 1
File src/Finder.cpp changed (mode: 100644) (index 23175f8..ebec09e)
26 26 #include <clang/AST/Decl.h> #include <clang/AST/Decl.h>
27 27 #include <clang/ASTMatchers/ASTMatchFinder.h> #include <clang/ASTMatchers/ASTMatchFinder.h>
28 28 #include <clang/ASTMatchers/ASTMatchers.h> #include <clang/ASTMatchers/ASTMatchers.h>
29 #include <clang/Basic/SourceManager.h>
29 30
30 31 #include "FuncInfo.hpp" #include "FuncInfo.hpp"
31 32
 
... ... class MatchHelper : public MatchFinder::MatchCallback {
41 42
42 43 public: public:
43 44 MatchHelper(Funcs &funcs); MatchHelper(Funcs &funcs);
44
45 45 void run(const Result &result) override; void run(const Result &result) override;
46 46
47 47 private: private:
48 Funcs::iterator registerFunc(const Result &result,
49 const FunctionDecl *func) const;
50
51 void registerRef(const Result &result, const DeclRefExpr *ref) const;
48 Funcs::iterator registerFunc(const FunctionDecl &func,
49 const SourceManager &sm) const;
50 void registerRef(const DeclRefExpr &ref,
51 const SourceManager &sm) const;
52 52
53 53 Funcs &funcs; Funcs &funcs;
54 54 }; };
 
... ... void MatchHelper::run(const Result &result) {
61 61 using Ref = DeclRefExpr; using Ref = DeclRefExpr;
62 62
63 63 if (const auto func = result.Nodes.getNodeAs<Func>("func")) { if (const auto func = result.Nodes.getNodeAs<Func>("func")) {
64 static_cast<void>(registerFunc(result, func));
64 static_cast<void>(registerFunc(*func, *result.SourceManager));
65 65 } else if (const auto ref = result.Nodes.getNodeAs<Ref>("ref")) { } else if (const auto ref = result.Nodes.getNodeAs<Ref>("ref")) {
66 registerRef(result, ref);
66 registerRef(*ref, *result.SourceManager);
67 67 } }
68 68 } }
69 69
70 Funcs::iterator MatchHelper::registerFunc(const Result &result,
71 const FunctionDecl *func) const {
72 if (!func->isExternallyVisible() || func->isMain()) {
70 Funcs::iterator MatchHelper::registerFunc(const FunctionDecl &func,
71 const SourceManager &sm) const {
72 if (!func.isExternallyVisible() || func.isMain()) {
73 73 return {}; return {};
74 74 } }
75 75
76 const auto it = funcs.find(func->getNameAsString());
76 const auto name = func.getNameAsString();
77 const auto it = funcs.find(name);
77 78 if (it == funcs.end()) { if (it == funcs.end()) {
78 const auto name = func->getNameAsString();
79 FuncInfo info(func, result.SourceManager);
80 return funcs.insert(std::make_pair(name, info)).first;
79 FuncInfo info(func, sm);
80 return funcs.emplace(name, info).first;
81 81 } }
82 it->second.processDeclaration(func, result.SourceManager);
82 it->second.processDeclaration(func, sm);
83 83 return it; return it;
84 84 } }
85 85
86 void MatchHelper::registerRef(const Result &result,
87 const DeclRefExpr *ref) const {
88 if (const auto func = ref->getDecl()->getAsFunction()) {
89 const auto it = registerFunc(result, func);
86 void MatchHelper::registerRef(const DeclRefExpr &ref,
87 const SourceManager &sm) const {
88 if (const auto func = ref.getDecl()->getAsFunction()) {
89 const auto it = registerFunc(*func, sm);
90 90 if (it != Funcs::iterator()) { if (it != Funcs::iterator()) {
91 it->second.registerRef(ref, result.SourceManager);
91 it->second.registerRef(ref, sm);
92 92 } }
93 93 } }
94 94 } }
File src/FuncInfo.cpp changed (mode: 100644) (index 1aa4dfa..52c6596)
25 25 #include <clang/Basic/SourceLocation.h> #include <clang/Basic/SourceLocation.h>
26 26 #include <clang/Basic/SourceManager.h> #include <clang/Basic/SourceManager.h>
27 27
28 FuncInfo::FuncInfo(const clang::FunctionDecl *func,
29 const clang::SourceManager *sm)
30 : name(func->getNameAsString()) {
28 FuncInfo::FuncInfo(const clang::FunctionDecl &func,
29 const clang::SourceManager &sm)
30 : name(func.getNameAsString()) {
31 31 processDeclaration(func, sm); processDeclaration(func, sm);
32 32 } }
33 33
34 void FuncInfo::processDeclaration(const clang::FunctionDecl *func,
35 const clang::SourceManager *sm) {
36 if (isFullyDeclared() || !func->isThisDeclarationADefinition()) {
34 void FuncInfo::processDeclaration(const clang::FunctionDecl &func,
35 const clang::SourceManager &sm) {
36 if (isFullyDeclared() || !func.isThisDeclarationADefinition()) {
37 37 return; return;
38 38 } }
39 39
40 clang::FullSourceLoc fullLoc(func->getNameInfo().getBeginLoc(), *sm);
41 fileName = sm->getFilename(fullLoc);
40 clang::FullSourceLoc fullLoc(func.getNameInfo().getBeginLoc(), sm);
41 fileName = sm.getFilename(fullLoc);
42 42 lineNum = fullLoc.getSpellingLineNumber(); lineNum = fullLoc.getSpellingLineNumber();
43 43 } }
44 44
45 45 bool FuncInfo::isFullyDeclared() const { return lineNum != 0U; } bool FuncInfo::isFullyDeclared() const { return lineNum != 0U; }
46 46
47 void FuncInfo::registerRef(const clang::DeclRefExpr *ref,
48 const clang::SourceManager *sm) {
47 void FuncInfo::registerRef(const clang::DeclRefExpr &ref,
48 const clang::SourceManager &sm) {
49 49 calls.emplace_back(ref, sm); calls.emplace_back(ref, sm);
50 50 } }
51 51
File src/FuncInfo.hpp changed (mode: 100644) (index b0fbc7f..22e1c3c)
... ... class FuncInfo {
40 40 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const FuncInfo &fi); friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const FuncInfo &fi);
41 41
42 42 public: public:
43 FuncInfo(const clang::FunctionDecl *func, const clang::SourceManager *sm);
43 FuncInfo(const clang::FunctionDecl &func, const clang::SourceManager &sm);
44 44
45 void processDeclaration(const clang::FunctionDecl *func,
46 const clang::SourceManager *sm);
45 void processDeclaration(const clang::FunctionDecl &func,
46 const clang::SourceManager &sm);
47 47 bool isFullyDeclared() const; bool isFullyDeclared() const;
48 void registerRef(const clang::DeclRefExpr *ref,
49 const clang::SourceManager *sm);
48 void registerRef(const clang::DeclRefExpr &ref,
49 const clang::SourceManager &sm);
50 50 bool isUnused() const; bool isUnused() const;
51 51 bool canBeMadeStatic() const; bool canBeMadeStatic() const;
52 52
File src/RefInfo.cpp changed (mode: 100644) (index ad880ba..1d1e2e2)
26 26
27 27
28 28 namespace { namespace {
29 std::string getFilename(const clang::DeclRefExpr *ref,
30 const clang::SourceManager *sm) {
31 clang::FullSourceLoc fullLoc(ref->getExprLoc(), *sm);
32 return sm->getFilename(fullLoc);
29 std::string getFilename(const clang::DeclRefExpr &ref,
30 const clang::SourceManager &sm) {
31 clang::FullSourceLoc fullLoc(ref.getExprLoc(), sm);
32 return sm.getFilename(fullLoc);
33 33 } }
34 34 } // namespace } // namespace
35 35
36 36
37 RefInfo::RefInfo(const clang::DeclRefExpr *ref,
38 const clang::SourceManager *sm)
37 RefInfo::RefInfo(const clang::DeclRefExpr &ref,
38 const clang::SourceManager &sm)
39 39 : fileName(getFilename(ref, sm)) { : fileName(getFilename(ref, sm)) {
40 40 } }
41 41
File src/RefInfo.hpp changed (mode: 100644) (index 979d26c..c7058d0)
... ... class SourceManager;
32 32
33 33 class RefInfo { class RefInfo {
34 34 public: public:
35 RefInfo(const clang::DeclRefExpr *ref, const clang::SourceManager *sm);
35 RefInfo(const clang::DeclRefExpr &ref, const clang::SourceManager &sm);
36 36
37 37 public: public:
38 38 bool isInThisUnit(const std::string &other) const; bool isInThisUnit(const std::string &other) const;
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