cid#1640468 Dereference after null check
[LibreOffice.git] / compilerplugins / clang / store / changefunctioncalls.cxx
blob9f5390a2150c22a190dc3354f81bd51284b958df
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"
30 #include "check.hxx"
32 namespace loplugin
35 class ChangeFunctionCalls
36 : public loplugin::FilteringRewritePlugin< ChangeFunctionCalls >
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 : FilteringRewritePlugin( 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 // so first check fast details like number of arguments or the (unqualified)
65 // name before checking the fully qualified name.
66 // See FunctionDecl for all the API about the function.
67 if( func->getNumParams() == 1 && func->getIdentifier() != NULL
68 && ( func->getName() == "bar" ))
70 auto qt = loplugin::DeclCheck(func);
71 if( qt.Function("bar").GlobalNamespace() )
73 // Further checks about arguments. Check mainly ParmVarDecl, VarDecl,
74 // ValueDecl and QualType for Clang API details.
75 string arg0 = func->getParamDecl( 0 )->getType().getAsString();
76 if( arg0 == "unsigned int" )
78 insertTextAfterToken( call->getArg( 0 )->getLocEnd(), " + 10" );
79 report( DiagnosticsEngine::Warning, "found", call->getLocStart());
84 return true;
87 static Plugin::Registration< ChangeFunctionCalls > X( "changefunctioncalls" );
89 } // namespace
91 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */