diff options
-rw-r--r-- | compilerplugins/clang/test/unusedindex.cxx | 23 | ||||
-rw-r--r-- | compilerplugins/clang/unusedindex.cxx | 86 | ||||
-rw-r--r-- | solenv/CompilerTest_compilerplugins_clang.mk | 1 |
3 files changed, 110 insertions, 0 deletions
diff --git a/compilerplugins/clang/test/unusedindex.cxx b/compilerplugins/clang/test/unusedindex.cxx new file mode 100644 index 000000000000..69ad7000b38c --- /dev/null +++ b/compilerplugins/clang/test/unusedindex.cxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <vector> + +void func1() +{ + std::vector<int> v1; + int n = 0; + + for (int i = 0; i < 10; ++i) // expected-error {{loop variable not used [loplugin:unusedindex]}} + n += 1; + for (int i = 0; i < 10; ++i) + n += i; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unusedindex.cxx b/compilerplugins/clang/unusedindex.cxx new file mode 100644 index 000000000000..96c343820a6b --- /dev/null +++ b/compilerplugins/clang/unusedindex.cxx @@ -0,0 +1,86 @@ + +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <string> +#include <iostream> +#include <unordered_set> + +#include "plugin.hxx" +#include "check.hxx" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/* + Mike Kaganski found a bug where the code was looping over a block and + not using the index var, and the loop was unnecessary. + So he wanted to have a look for other places like that. +*/ +namespace +{ +class UnusedIndex : public RecursiveASTVisitor<UnusedIndex>, public loplugin::Plugin +{ +public: + explicit UnusedIndex(loplugin::InstantiationData const& data) + : Plugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool TraverseForStmt(ForStmt* stmt); + bool VisitDeclRefExpr(DeclRefExpr const* stmt); + +private: + VarDecl const* mLoopVarDecl = nullptr; + std::unordered_set<VarDecl const*> mFoundSet; +}; + +bool UnusedIndex::TraverseForStmt(ForStmt* stmt) +{ + if (ignoreLocation(stmt)) + return true; + auto savedCopy = mLoopVarDecl; + + mLoopVarDecl = nullptr; + if (stmt->getInit()) + { + auto declStmt = dyn_cast<DeclStmt>(stmt->getInit()); + if (declStmt && declStmt->isSingleDecl()) + { + auto varDecl = dyn_cast<VarDecl>(declStmt->getSingleDecl()); + if (varDecl) + mLoopVarDecl = varDecl; + } + } + + // deliberately ignore the other parts of the for stmt, except for the body + auto ret = RecursiveASTVisitor::TraverseStmt(stmt->getBody()); + + if (mLoopVarDecl && mFoundSet.erase(mLoopVarDecl) == 0) + report(DiagnosticsEngine::Warning, "loop variable not used", mLoopVarDecl->getLocStart()) + << mLoopVarDecl->getSourceRange(); + mLoopVarDecl = savedCopy; + return ret; +} + +bool UnusedIndex::VisitDeclRefExpr(DeclRefExpr const* stmt) +{ + auto varDecl = dyn_cast<VarDecl>(stmt->getDecl()); + if (!varDecl) + return true; + if (mLoopVarDecl && mLoopVarDecl == varDecl) + mFoundSet.insert(varDecl); + return true; +} + +loplugin::Plugin::Registration<UnusedIndex> X("unusedindex", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/solenv/CompilerTest_compilerplugins_clang.mk b/solenv/CompilerTest_compilerplugins_clang.mk index 4a98ef996091..41990fab90f4 100644 --- a/solenv/CompilerTest_compilerplugins_clang.mk +++ b/solenv/CompilerTest_compilerplugins_clang.mk @@ -48,6 +48,7 @@ $(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \ compilerplugins/clang/test/unnecessaryoverride-dtor \ compilerplugins/clang/test/unnecessaryparen \ compilerplugins/clang/test/unoany \ + compilerplugins/clang/test/unusedindex \ compilerplugins/clang/test/unusedvariablecheck \ compilerplugins/clang/test/useuniqueptr \ compilerplugins/clang/test/vclwidgets \ |