diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-10-27 10:54:31 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-10-27 13:55:43 +0200 |
commit | 569c7da252be05366980ae88ce30ef17f6e61d8c (patch) | |
tree | 2506933ed4caae9602d042f1eaddaf7bd73814d0 /compilerplugins | |
parent | 5670f65ccea6c47b17ec010fd15edcee5522086b (diff) |
extract some common code for checking if a functions address was taken
Change-Id: I292b4e9bf17c83f83ff43ac4c5870d33092d0c71
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/constantparam.cxx | 28 | ||||
-rw-r--r-- | compilerplugins/clang/constparams.cxx | 91 | ||||
-rw-r--r-- | compilerplugins/clang/functionaddress.hxx | 120 | ||||
-rw-r--r-- | compilerplugins/clang/plugin.hxx | 5 |
4 files changed, 138 insertions, 106 deletions
diff --git a/compilerplugins/clang/constantparam.cxx b/compilerplugins/clang/constantparam.cxx index 426e86995040..edc99c37699f 100644 --- a/compilerplugins/clang/constantparam.cxx +++ b/compilerplugins/clang/constantparam.cxx @@ -15,6 +15,7 @@ #include "plugin.hxx" #include "compat.hxx" #include "check.hxx" +#include "functionaddress.hxx" /* Find params on methods where the param is only ever passed as a single constant value. @@ -53,10 +54,10 @@ bool operator < (const MyCallSiteInfo &lhs, const MyCallSiteInfo &rhs) static std::set<MyCallSiteInfo> callSet; class ConstantParam: - public RecursiveASTVisitor<ConstantParam>, public loplugin::Plugin + public loplugin::FunctionAddress<ConstantParam> { public: - explicit ConstantParam(InstantiationData const & data): Plugin(data) {} + explicit ConstantParam(InstantiationData const & data): loplugin::FunctionAddress<ConstantParam>(data) {} virtual void run() override { @@ -70,6 +71,13 @@ public: TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + // this catches places that take the address of a method + for (auto functionDecl : getFunctionsWithAddressTaken()) + { + for (unsigned i = 0; i < functionDecl->getNumParams(); ++i) + addToCallSet(functionDecl, i, functionDecl->getParamDecl(i)->getName(), "unknown3"); + } + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes // writing to the same logfile @@ -87,7 +95,6 @@ public: bool shouldVisitImplicitCode () const { return true; } bool VisitCallExpr( const CallExpr* ); - bool VisitDeclRefExpr( const DeclRefExpr* ); bool VisitCXXConstructExpr( const CXXConstructExpr* ); private: void addToCallSet(const FunctionDecl* functionDecl, int paramIndex, llvm::StringRef paramName, const std::string& callValue); @@ -277,21 +284,6 @@ bool ConstantParam::VisitCallExpr(const CallExpr * callExpr) { return true; } -// this catches places that take the address of a method -bool ConstantParam::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) -{ - const Decl* decl = declRefExpr->getDecl(); - const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(decl); - if (!functionDecl) - return true; - functionDecl = functionDecl->getCanonicalDecl(); - for (unsigned i = 0; i < functionDecl->getNumParams(); ++i) - { - addToCallSet(functionDecl, i, functionDecl->getParamDecl(i)->getName(), "unknown3"); - } - return true; -} - bool ConstantParam::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr ) { const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor(); diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx index bf715d16e91a..8396f2dad6ec 100644 --- a/compilerplugins/clang/constparams.cxx +++ b/compilerplugins/clang/constparams.cxx @@ -16,6 +16,7 @@ #include "plugin.hxx" #include "compat.hxx" #include "check.hxx" +#include "functionaddress.hxx" /** Find pointer and reference params that can be declared const. @@ -31,10 +32,10 @@ static bool startswith(const std::string& rStr, const char* pSubStr) { } class ConstParams: - public RecursiveASTVisitor<ConstParams>, public loplugin::Plugin + public loplugin::FunctionAddress<ConstParams> { public: - explicit ConstParams(InstantiationData const & data): Plugin(data) {} + explicit ConstParams(InstantiationData const & data): loplugin::FunctionAddress<ConstParams>(data) {} virtual void run() override { std::string fn( compiler.getSourceManager().getFileEntryForID( @@ -63,8 +64,8 @@ public: if (paramCannotBeConstSet.find(pParmVarDecl) == paramCannotBeConstSet.end()) { auto functionDecl = parmToFunction[pParmVarDecl]; auto canonicalDecl = functionDecl->getCanonicalDecl(); - if (ignoredFunctions_.find(canonicalDecl) - != ignoredFunctions_.end()) + if (getFunctionsWithAddressTaken().find(canonicalDecl) + != getFunctionsWithAddressTaken().end()) { continue; } @@ -86,86 +87,6 @@ public: } } - bool TraverseCallExpr(CallExpr * expr) { - auto const saved = callee_; - callee_ = expr->getCallee(); - auto const ret = RecursiveASTVisitor::TraverseCallExpr(expr); - callee_ = saved; - return ret; - } - - bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr) { - auto const saved = callee_; - callee_ = expr->getCallee(); - auto const ret = RecursiveASTVisitor::TraverseCXXOperatorCallExpr(expr); - callee_ = saved; - return ret; - } - - bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) { - auto const saved = callee_; - callee_ = expr->getCallee(); - auto const ret = RecursiveASTVisitor::TraverseCXXMemberCallExpr(expr); - callee_ = saved; - return ret; - } - - bool TraverseCUDAKernelCallExpr(CUDAKernelCallExpr * expr) { - auto const saved = callee_; - callee_ = expr->getCallee(); - auto const ret = RecursiveASTVisitor::TraverseCUDAKernelCallExpr(expr); - callee_ = saved; - return ret; - } - - bool TraverseUserDefinedLiteral(UserDefinedLiteral * expr) { - auto const saved = callee_; - callee_ = expr->getCallee(); - auto const ret = RecursiveASTVisitor::TraverseUserDefinedLiteral(expr); - callee_ = saved; - return ret; - } - - bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { - if (expr == callee_) { - return true; - } - if (ignoreLocation(expr)) { - return true; - } - if (expr->getCastKind() != CK_FunctionToPointerDecay) { - return true; - } - auto const dre = dyn_cast<DeclRefExpr>( - expr->getSubExpr()->IgnoreParens()); - if (dre == nullptr) { - return true; - } - auto const fd = dyn_cast<FunctionDecl>(dre->getDecl()); - if (fd == nullptr) { - return true; - } - ignoredFunctions_.insert(fd->getCanonicalDecl()); - return true; - } - - bool VisitUnaryAddrOf(UnaryOperator const * expr) { - if (ignoreLocation(expr)) { - return true; - } - auto const dre = dyn_cast<DeclRefExpr>( - expr->getSubExpr()->IgnoreParenImpCasts()); - if (dre == nullptr) { - return true; - } - auto const fd = dyn_cast<FunctionDecl>(dre->getDecl()); - if (fd == nullptr) { - return true; - } - ignoredFunctions_.insert(fd->getCanonicalDecl()); - return true; - } - bool VisitFunctionDecl(const FunctionDecl *); bool VisitDeclRefExpr(const DeclRefExpr *); @@ -176,8 +97,6 @@ private: std::unordered_set<const ParmVarDecl*> interestingParamSet; std::unordered_map<const ParmVarDecl*, const FunctionDecl*> parmToFunction; std::unordered_set<const ParmVarDecl*> paramCannotBeConstSet; - std::unordered_set<FunctionDecl const *> ignoredFunctions_; - Expr const * callee_ = nullptr; }; bool ConstParams::VisitFunctionDecl(const FunctionDecl * functionDecl) diff --git a/compilerplugins/clang/functionaddress.hxx b/compilerplugins/clang/functionaddress.hxx new file mode 100644 index 000000000000..dc34262a50b0 --- /dev/null +++ b/compilerplugins/clang/functionaddress.hxx @@ -0,0 +1,120 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_COMPILERPLUGINS_CLANG_FUNCTIONADDRESS_HXX +#define INCLUDED_COMPILERPLUGINS_CLANG_FUNCTIONADDRESS_HXX + +#include <clang/AST/RecursiveASTVisitor.h> +#include <unordered_set> +#include "plugin.hxx" + +/** + * Common code for checking if the address of a function was taken. + */ +namespace loplugin { + +template<typename Derived> +class FunctionAddress : public RecursiveASTVisitor<Derived>, public loplugin::Plugin +{ +public: + explicit FunctionAddress( const InstantiationData& data ) : loplugin::Plugin(data) {} + + bool TraverseCallExpr(CallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor<Derived>::TraverseCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor<Derived>::TraverseCXXOperatorCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor<Derived>::TraverseCXXMemberCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCUDAKernelCallExpr(CUDAKernelCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor<Derived>::TraverseCUDAKernelCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseUserDefinedLiteral(UserDefinedLiteral * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor<Derived>::TraverseUserDefinedLiteral(expr); + callee_ = saved; + return ret; + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { + if (expr == callee_) { + return true; + } + if (ignoreLocation(expr)) { + return true; + } + if (expr->getCastKind() != CK_FunctionToPointerDecay) { + return true; + } + auto const dre = dyn_cast<DeclRefExpr>( + expr->getSubExpr()->IgnoreParens()); + if (dre == nullptr) { + return true; + } + auto const fd = dyn_cast<FunctionDecl>(dre->getDecl()); + if (fd == nullptr) { + return true; + } + ignoredFunctions_.insert(fd->getCanonicalDecl()); + return true; + } + + bool VisitUnaryAddrOf(UnaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const dre = dyn_cast<DeclRefExpr>( + expr->getSubExpr()->IgnoreParenImpCasts()); + if (dre == nullptr) { + return true; + } + auto const fd = dyn_cast<FunctionDecl>(dre->getDecl()); + if (fd == nullptr) { + return true; + } + ignoredFunctions_.insert(fd->getCanonicalDecl()); + return true; + } + +protected: + std::unordered_set<FunctionDecl const *> const & getFunctionsWithAddressTaken() { return ignoredFunctions_; } + +private: + std::unordered_set<FunctionDecl const *> ignoredFunctions_; + Expr const * callee_ = nullptr; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx index 1f57dfeb0ffa..69349236a42d 100644 --- a/compilerplugins/clang/plugin.hxx +++ b/compilerplugins/clang/plugin.hxx @@ -56,11 +56,12 @@ public: enum { isPPCallback = false }; // Returns location right after the end of the token that starts at the given location. SourceLocation locationAfterToken( SourceLocation location ); -protected: - DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const; bool ignoreLocation( SourceLocation loc ); bool ignoreLocation( const Decl* decl ); bool ignoreLocation( const Stmt* stmt ); + +protected: + DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const; CompilerInstance& compiler; PluginHandler& handler; /** |