compilerplugins/clang/constparams.cxx | 145 ++++++++++++++++++----------- compilerplugins/clang/test/constparams.cxx | 22 ++++ 2 files changed, 115 insertions(+), 52 deletions(-)
New commits: commit 2e8a95d1f87a3dbdcc8846fa44d1899abc8edd9c Author: Stephan Bergmann <sberg...@redhat.com> Date: Fri Sep 29 23:39:50 2017 +0200 loplugin:constparams: Ignore functions whose address is taken (unless as the callee of a function call). In response to <https://gerrit.libreoffice.org/#/c/42912/> "DO NOT MERGE - error in clang static plugin". Many of the whitelisted functions can now be taken off the list. Change-Id: I04c2ee445e7973a288f42fd663d8b2d78cd3c5aa Reviewed-on: https://gerrit.libreoffice.org/42958 Reviewed-by: Stephan Bergmann <sberg...@redhat.com> Tested-by: Stephan Bergmann <sberg...@redhat.com> diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx index 62300f4d5eb2..5ce9df2e5e2c 100644 --- a/compilerplugins/clang/constparams.cxx +++ b/compilerplugins/clang/constparams.cxx @@ -8,6 +8,7 @@ */ #include <algorithm> +#include <set> #include <string> #include <unordered_set> #include <unordered_map> @@ -61,15 +62,21 @@ public: for (const ParmVarDecl *pParmVarDecl : interestingSet) { if (cannotBeConstSet.find(pParmVarDecl) == cannotBeConstSet.end()) { + auto functionDecl = parmToFunction[pParmVarDecl]; + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (ignoredFunctions_.find(canonicalDecl) + != ignoredFunctions_.end()) + { + continue; + } report( DiagnosticsEngine::Warning, "this parameter can be const", pParmVarDecl->getLocStart()) << pParmVarDecl->getSourceRange(); - auto functionDecl = parmToFunction[pParmVarDecl]; - if (functionDecl->getCanonicalDecl()->getLocation() != functionDecl->getLocation()) { + if (canonicalDecl->getLocation() != functionDecl->getLocation()) { unsigned idx = pParmVarDecl->getFunctionScopeIndex(); - const ParmVarDecl* pOther = functionDecl->getCanonicalDecl()->getParamDecl(idx); + const ParmVarDecl* pOther = canonicalDecl->getParamDecl(idx); report( DiagnosticsEngine::Note, "canonical parameter declaration here", @@ -80,6 +87,86 @@ public: } } + bool TraverseCallExpr(CallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor::TraverseCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor::TraverseCXXOperatorCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor::TraverseCXXMemberCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCUDAKernelCallExpr(CUDAKernelCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor::TraverseCUDAKernelCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseUserDefinedLiteral(UserDefinedLiteral * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = RecursiveASTVisitor::TraverseUserDefinedLiteral(expr); + callee_ = saved; + return ret; + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { + if (expr == callee_) { + return true; + } + if (ignoreLocation(expr)) { + return true; + } + if (expr->getCastKind() != CK_FunctionToPointerDecay) { + return true; + } + auto const dre = dyn_cast<DeclRefExpr>( + expr->getSubExpr()->IgnoreParens()); + if (dre == nullptr) { + return true; + } + auto const fd = dyn_cast<FunctionDecl>(dre->getDecl()); + if (fd == nullptr) { + return true; + } + ignoredFunctions_.insert(fd->getCanonicalDecl()); + return true; + } + + bool VisitUnaryAddrOf(UnaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const dre = dyn_cast<DeclRefExpr>( + expr->getSubExpr()->IgnoreParenImpCasts()); + if (dre == nullptr) { + return true; + } + auto const fd = dyn_cast<FunctionDecl>(dre->getDecl()); + if (fd == nullptr) { + return true; + } + ignoredFunctions_.insert(fd->getCanonicalDecl()); + return true; + } + bool VisitFunctionDecl(const FunctionDecl *); bool VisitDeclRefExpr(const DeclRefExpr *); @@ -90,6 +177,8 @@ private: std::unordered_set<const ParmVarDecl*> interestingSet; std::unordered_map<const ParmVarDecl*, const FunctionDecl*> parmToFunction; std::unordered_set<const ParmVarDecl*> cannotBeConstSet; + std::set<FunctionDecl const *> ignoredFunctions_; + Expr const * callee_ = nullptr; }; bool ConstParams::VisitFunctionDecl(const FunctionDecl * functionDecl) @@ -128,65 +217,17 @@ bool ConstParams::VisitFunctionDecl(const FunctionDecl * functionDecl) if (functionDecl->getIdentifier()) { StringRef name = functionDecl->getName(); - if (name == "yyerror" // ignore lex/yacc callback - // some function callbacks - // TODO should really use a two-pass algorithm to detect and ignore these automatically - || name == "PDFSigningPKCS7PasswordCallback" - || name == "VCLExceptionSignal_impl" - || name == "parseXcsFile" - || name == "GraphicsExposePredicate" - || name == "ImplPredicateEvent" - || name == "timestamp_predicate" - || name == "signalScreenSizeChanged" - || name == "signalMonitorsChanged" - || name == "signalButton" - || name == "signalFocus" - || name == "signalDestroy" - || name == "signalSettingsNotify" - || name == "signalStyleSet" - || name == "signalIMCommit" - || name == "compressWheelEvents" - || name == "MenuBarSignalKey" - || name == "signalDragDropReceived" - || name == "memory_write" - || name == "file_write" + if ( name == "file_write" || name == "SalMainPipeExchangeSignal_impl" || name.startswith("SbRtl_") - || name == "my_if_errors" - || name == "my_eval_defined" - || name == "my_eval_variable" - || name == "ImpGetEscDir" - || name == "ImpGetPercent" - || name == "ImpGetAlign" - || name == "write_function" - || name == "PyUNO_getattr" - || name == "PyUNO_setattr" - || name == "PyUNOStruct_setattr" - || name == "PyUNOStruct_getattr" || name == "GoNext" || name == "GoPrevious" - || name == "lcl_SetOtherLineHeight" - || name == "BoxNmsToPtr" - || name == "PtrToBoxNms" - || name == "RelNmsToBoxNms" - || name == "RelBoxNmsToPtr" - || name == "BoxNmsToRelNm" - || name == "MakeFormula_" - || name == "GetFormulaBoxes" - || name == "HasValidBoxes_" - || name == "SplitMergeBoxNm_" || name.startswith("Read_F_") - || name == "UpdateFieldInformation" - // #ifdef win32 - || name == "convert_slashes" // UNO component entry points || name.endswith("component_getFactory") - // external API - || name == "Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeOutputStream_flush" || name == "egiGraphicExport" || name == "etiGraphicExport" || name == "epsGraphicExport" - || name == "releasePool" // vcl/osx/saldata.cxx ) return true; } diff --git a/compilerplugins/clang/test/constparams.cxx b/compilerplugins/clang/test/constparams.cxx index fd4ee2cd63f7..feb07f1b6066 100644 --- a/compilerplugins/clang/test/constparams.cxx +++ b/compilerplugins/clang/test/constparams.cxx @@ -24,4 +24,26 @@ struct Class3 Class3(void * f2) : m_f2(static_cast<int*>(f2)) {} }; +int const * f1(int *); // expected-note {{canonical parameter declaration here [loplugin:constparams]}} +int const * f2(int *); +int const * f3(int *); +void g() { + int const * (*p1)(int *); + int n = 0; + f1(&n); + p1 = f2; + typedef void (*P2)(); + P2 p2; + p2 = (P2) (f3); +} +int const * f1(int * p) { // expected-error {{this parameter can be const [loplugin:constparams]}} + return p; +} +int const * f2(int * p) { + return p; +} +int const * f3(int * p) { + return p; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits