1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
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()
34 class ChangeFunctionCalls
35 : public RecursiveASTVisitor
< ChangeFunctionCalls
>
36 , public RewritePlugin
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
))
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());
88 static Plugin::Registration
< ChangeFunctionCalls
> X( "changefunctioncalls" );
92 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */