extract some common code for checking if a functions address was taken
Change-Id: I292b4e9bf17c83f83ff43ac4c5870d33092d0c71
This commit is contained in:
parent
5670f65cce
commit
569c7da252
@ -15,6 +15,7 @@
|
|||||||
#include "plugin.hxx"
|
#include "plugin.hxx"
|
||||||
#include "compat.hxx"
|
#include "compat.hxx"
|
||||||
#include "check.hxx"
|
#include "check.hxx"
|
||||||
|
#include "functionaddress.hxx"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find params on methods where the param is only ever passed as a single constant value.
|
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;
|
static std::set<MyCallSiteInfo> callSet;
|
||||||
|
|
||||||
class ConstantParam:
|
class ConstantParam:
|
||||||
public RecursiveASTVisitor<ConstantParam>, public loplugin::Plugin
|
public loplugin::FunctionAddress<ConstantParam>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ConstantParam(InstantiationData const & data): Plugin(data) {}
|
explicit ConstantParam(InstantiationData const & data): loplugin::FunctionAddress<ConstantParam>(data) {}
|
||||||
|
|
||||||
virtual void run() override
|
virtual void run() override
|
||||||
{
|
{
|
||||||
@ -70,6 +71,13 @@ public:
|
|||||||
|
|
||||||
TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
|
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
|
// dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes
|
||||||
// writing to the same logfile
|
// writing to the same logfile
|
||||||
|
|
||||||
@ -87,7 +95,6 @@ public:
|
|||||||
bool shouldVisitImplicitCode () const { return true; }
|
bool shouldVisitImplicitCode () const { return true; }
|
||||||
|
|
||||||
bool VisitCallExpr( const CallExpr* );
|
bool VisitCallExpr( const CallExpr* );
|
||||||
bool VisitDeclRefExpr( const DeclRefExpr* );
|
|
||||||
bool VisitCXXConstructExpr( const CXXConstructExpr* );
|
bool VisitCXXConstructExpr( const CXXConstructExpr* );
|
||||||
private:
|
private:
|
||||||
void addToCallSet(const FunctionDecl* functionDecl, int paramIndex, llvm::StringRef paramName, const std::string& callValue);
|
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;
|
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 )
|
bool ConstantParam::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr )
|
||||||
{
|
{
|
||||||
const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor();
|
const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor();
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "plugin.hxx"
|
#include "plugin.hxx"
|
||||||
#include "compat.hxx"
|
#include "compat.hxx"
|
||||||
#include "check.hxx"
|
#include "check.hxx"
|
||||||
|
#include "functionaddress.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Find pointer and reference params that can be declared const.
|
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:
|
class ConstParams:
|
||||||
public RecursiveASTVisitor<ConstParams>, public loplugin::Plugin
|
public loplugin::FunctionAddress<ConstParams>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ConstParams(InstantiationData const & data): Plugin(data) {}
|
explicit ConstParams(InstantiationData const & data): loplugin::FunctionAddress<ConstParams>(data) {}
|
||||||
|
|
||||||
virtual void run() override {
|
virtual void run() override {
|
||||||
std::string fn( compiler.getSourceManager().getFileEntryForID(
|
std::string fn( compiler.getSourceManager().getFileEntryForID(
|
||||||
@ -63,8 +64,8 @@ public:
|
|||||||
if (paramCannotBeConstSet.find(pParmVarDecl) == paramCannotBeConstSet.end()) {
|
if (paramCannotBeConstSet.find(pParmVarDecl) == paramCannotBeConstSet.end()) {
|
||||||
auto functionDecl = parmToFunction[pParmVarDecl];
|
auto functionDecl = parmToFunction[pParmVarDecl];
|
||||||
auto canonicalDecl = functionDecl->getCanonicalDecl();
|
auto canonicalDecl = functionDecl->getCanonicalDecl();
|
||||||
if (ignoredFunctions_.find(canonicalDecl)
|
if (getFunctionsWithAddressTaken().find(canonicalDecl)
|
||||||
!= ignoredFunctions_.end())
|
!= getFunctionsWithAddressTaken().end())
|
||||||
{
|
{
|
||||||
continue;
|
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 VisitFunctionDecl(const FunctionDecl *);
|
||||||
bool VisitDeclRefExpr(const DeclRefExpr *);
|
bool VisitDeclRefExpr(const DeclRefExpr *);
|
||||||
|
|
||||||
@ -176,8 +97,6 @@ private:
|
|||||||
std::unordered_set<const ParmVarDecl*> interestingParamSet;
|
std::unordered_set<const ParmVarDecl*> interestingParamSet;
|
||||||
std::unordered_map<const ParmVarDecl*, const FunctionDecl*> parmToFunction;
|
std::unordered_map<const ParmVarDecl*, const FunctionDecl*> parmToFunction;
|
||||||
std::unordered_set<const ParmVarDecl*> paramCannotBeConstSet;
|
std::unordered_set<const ParmVarDecl*> paramCannotBeConstSet;
|
||||||
std::unordered_set<FunctionDecl const *> ignoredFunctions_;
|
|
||||||
Expr const * callee_ = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ConstParams::VisitFunctionDecl(const FunctionDecl * functionDecl)
|
bool ConstParams::VisitFunctionDecl(const FunctionDecl * functionDecl)
|
||||||
|
120
compilerplugins/clang/functionaddress.hxx
Normal file
120
compilerplugins/clang/functionaddress.hxx
Normal file
@ -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: */
|
@ -56,11 +56,12 @@ public:
|
|||||||
enum { isPPCallback = false };
|
enum { isPPCallback = false };
|
||||||
// Returns location right after the end of the token that starts at the given location.
|
// Returns location right after the end of the token that starts at the given location.
|
||||||
SourceLocation locationAfterToken( SourceLocation location );
|
SourceLocation locationAfterToken( SourceLocation location );
|
||||||
protected:
|
|
||||||
DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const;
|
|
||||||
bool ignoreLocation( SourceLocation loc );
|
bool ignoreLocation( SourceLocation loc );
|
||||||
bool ignoreLocation( const Decl* decl );
|
bool ignoreLocation( const Decl* decl );
|
||||||
bool ignoreLocation( const Stmt* stmt );
|
bool ignoreLocation( const Stmt* stmt );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const;
|
||||||
CompilerInstance& compiler;
|
CompilerInstance& compiler;
|
||||||
PluginHandler& handler;
|
PluginHandler& handler;
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user