diff options
Diffstat (limited to 'compilerplugins/clang/store/changefunctioncalls.cxx')
-rw-r--r-- | compilerplugins/clang/store/changefunctioncalls.cxx | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/compilerplugins/clang/store/changefunctioncalls.cxx b/compilerplugins/clang/store/changefunctioncalls.cxx new file mode 100644 index 000000000..9f5390a21 --- /dev/null +++ b/compilerplugins/clang/store/changefunctioncalls.cxx @@ -0,0 +1,91 @@ +/* -*- 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: */ |