From 015d9327354bdd6a7495285eb35105c08e536a45 Mon Sep 17 00:00:00 2001 From: Luboš Luňák Date: Tue, 2 Jul 2013 13:32:51 +0200 Subject: 'generic' compiler plugin to modify calls to a specific function Change-Id: I60756d9054dfa5c55aeae8ddc904ddf6d67d2088 --- .../clang/store/changefunctioncalls.cxx | 84 ++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 compilerplugins/clang/store/changefunctioncalls.cxx (limited to 'compilerplugins') diff --git a/compilerplugins/clang/store/changefunctioncalls.cxx b/compilerplugins/clang/store/changefunctioncalls.cxx new file mode 100644 index 000000000000..2d0ae91e702c --- /dev/null +++ b/compilerplugins/clang/store/changefunctioncalls.cxx @@ -0,0 +1,84 @@ +/* + * 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 +- etc. +*/ + +#include "plugin.hxx" + +namespace loplugin +{ + +class ChangeFunctionCalls + : public RecursiveASTVisitor< ChangeFunctionCalls > + , public RewritePlugin + { + public: + explicit ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter ); + virtual void run() override; + bool VisitCallExpr( const CallExpr* call ); + }; + +ChangeFunctionCalls::ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter ) + : RewritePlugin( compiler, rewriter ) + { + } + +void ChangeFunctionCalls::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool ChangeFunctionCalls::VisitCallExpr( const CallExpr* call ) + { + if( ignoreLocation( call )) + return true; + if( const FunctionDecl* func = call->getDirectCallee()) + { + // Optimize, getQualifiedNameAsString() is reportedly expensive, + // 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" )) + { + string qualifiedName = func->getQualifiedNameAsString(); + if( qualifiedName == "bar" ) + { + // 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 -- cgit