bump product version to 5.0.4.1
[LibreOffice.git] / compilerplugins / clang / store / changefunctioncalls.cxx
blobabc8ce62cebab8cc5d239aa9573d725c4410d247
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * Based on LLVM/Clang.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
13 This is a rewriter.
15 Changes all calls to a specific function (after it's been renamed or its
16 arguments have changed).
18 This specific example checks for calls to function 'void bar(unsigned int)'
19 and adds '+ 10' to the argument (as plain text, so if the argument is a more
20 complex expression, operator precedence may mean the result is actually different).
22 This can be easily adjusted for different modifications to a function:
23 - replace CallExpr with CXXOperatorCallExpr or CXXMemberCallExpr
24 - check different names or arguments
25 - change getDirectCallee() to getCallee()
26 - etc.
29 #include "plugin.hxx"
31 namespace loplugin
34 class ChangeFunctionCalls
35 : public RecursiveASTVisitor< ChangeFunctionCalls >
36 , public RewritePlugin
38 public:
39 explicit ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter );
40 virtual void run() override;
41 bool VisitCallExpr( const CallExpr* call );
44 ChangeFunctionCalls::ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter )
45 : RewritePlugin( compiler, rewriter )
49 void ChangeFunctionCalls::run()
51 TraverseDecl( compiler.getASTContext().getTranslationUnitDecl());
54 bool ChangeFunctionCalls::VisitCallExpr( const CallExpr* call )
56 if( ignoreLocation( call ))
57 return true;
58 // Using getDirectCallee() here means that we find only calls
59 // that call the function directly (i.e. not using a pointer, for example).
60 // Use getCallee() to include also those :
61 // if( const FunctionDecl* func = dyn_cast_or_null< FunctionDecl >( call->getCalleeDecl()))
62 if( const FunctionDecl* func = call->getDirectCallee())
64 // Optimize, getQualifiedNameAsString() is reportedly expensive,
65 // so first check fast details like number of arguments or the (unqualified)
66 // name before checking the fully qualified name.
67 // See FunctionDecl for all the API about the function.
68 if( func->getNumParams() == 1 && func->getIdentifier() != NULL
69 && ( func->getName() == "bar" ))
71 string qualifiedName = func->getQualifiedNameAsString();
72 if( qualifiedName == "bar" )
74 // Further checks about arguments. Check mainly ParmVarDecl, VarDecl,
75 // ValueDecl and QualType for Clang API details.
76 string arg0 = func->getParamDecl( 0 )->getType().getAsString();
77 if( arg0 == "unsigned int" )
79 insertTextAfterToken( call->getArg( 0 )->getLocEnd(), " + 10" );
80 report( DiagnosticsEngine::Warning, "found", call->getLocStart());
85 return true;
88 static Plugin::Registration< ChangeFunctionCalls > X( "changefunctioncalls" );
90 } // namespace
92 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */