91 lines
3.1 KiB
C++
91 lines
3.1 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* Based on LLVM/Clang.
|
|
*
|
|
* This file is distributed under the University of Illinois Open Source
|
|
* License. See LICENSE.TXT for details.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
This is a rewriter.
|
|
|
|
Changes all calls to a specific function (after it's been renamed or its
|
|
arguments have changed).
|
|
|
|
This specific example checks for calls to function 'void bar(unsigned int)'
|
|
and adds '+ 10' to the argument (as plain text, so if the argument is a more
|
|
complex expression, operator precedence may mean the result is actually different).
|
|
|
|
This can be easily adjusted for different modifications to a function:
|
|
- replace CallExpr with CXXOperatorCallExpr or CXXMemberCallExpr
|
|
- check different names or arguments
|
|
- change getDirectCallee() to getCallee()
|
|
- etc.
|
|
*/
|
|
|
|
#include "plugin.hxx"
|
|
#include "check.hxx"
|
|
|
|
namespace loplugin
|
|
{
|
|
|
|
class ChangeFunctionCalls
|
|
: public loplugin::FilteringRewritePlugin< ChangeFunctionCalls >
|
|
{
|
|
public:
|
|
explicit ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter );
|
|
virtual void run() override;
|
|
bool VisitCallExpr( const CallExpr* call );
|
|
};
|
|
|
|
ChangeFunctionCalls::ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter )
|
|
: FilteringRewritePlugin( compiler, rewriter )
|
|
{
|
|
}
|
|
|
|
void ChangeFunctionCalls::run()
|
|
{
|
|
TraverseDecl( compiler.getASTContext().getTranslationUnitDecl());
|
|
}
|
|
|
|
bool ChangeFunctionCalls::VisitCallExpr( const CallExpr* call )
|
|
{
|
|
if( ignoreLocation( call ))
|
|
return true;
|
|
// Using getDirectCallee() here means that we find only calls
|
|
// that call the function directly (i.e. not using a pointer, for example).
|
|
// Use getCallee() to include also those :
|
|
// if( const FunctionDecl* func = dyn_cast_or_null< FunctionDecl >( call->getCalleeDecl()))
|
|
if( const FunctionDecl* func = call->getDirectCallee())
|
|
{
|
|
// so first check fast details like number of arguments or the (unqualified)
|
|
// name before checking the fully qualified name.
|
|
// See FunctionDecl for all the API about the function.
|
|
if( func->getNumParams() == 1 && func->getIdentifier() != NULL
|
|
&& ( func->getName() == "bar" ))
|
|
{
|
|
auto qt = loplugin::DeclCheck(func);
|
|
if( qt.Function("bar").GlobalNamespace() )
|
|
{
|
|
// Further checks about arguments. Check mainly ParmVarDecl, VarDecl,
|
|
// ValueDecl and QualType for Clang API details.
|
|
string arg0 = func->getParamDecl( 0 )->getType().getAsString();
|
|
if( arg0 == "unsigned int" )
|
|
{
|
|
insertTextAfterToken( call->getArg( 0 )->getLocEnd(), " + 10" );
|
|
report( DiagnosticsEngine::Warning, "found", call->getLocStart());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static Plugin::Registration< ChangeFunctionCalls > X( "changefunctioncalls" );
|
|
|
|
} // namespace
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|