summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2013-07-02 13:32:51 +0200
committerLuboš Luňák <l.lunak@suse.cz>2013-08-05 15:10:40 +0200
commit015d9327354bdd6a7495285eb35105c08e536a45 (patch)
treeacda27b5753e0606c9ebc5d200ce8905f20602ee /compilerplugins
parent1e0feb5cf916fada5dc2db66a358649624ece578 (diff)
'generic' compiler plugin to modify calls to a specific function
Change-Id: I60756d9054dfa5c55aeae8ddc904ddf6d67d2088
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/store/changefunctioncalls.cxx84
1 files changed, 84 insertions, 0 deletions
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