compilerplugins/clang/store/README | 3 compilerplugins/clang/store/badvectorinit.cxx | 214 - compilerplugins/clang/store/bodynotinblock.cxx | 147 - compilerplugins/clang/store/bodynotinblock.hxx | 35 compilerplugins/clang/store/cascadingassignop.cxx | 94 compilerplugins/clang/store/cascadingassignop.hxx | 35 compilerplugins/clang/store/cascadingcondop.cxx | 85 compilerplugins/clang/store/cascadingcondop.hxx | 35 compilerplugins/clang/store/changefunctioncalls.cxx | 91 compilerplugins/clang/store/checkunusedparams.cxx | 502 ---- compilerplugins/clang/store/comparisonwithconstant.cxx | 168 - compilerplugins/clang/store/constantfunction.cxx | 506 ---- compilerplugins/clang/store/constfields.cxx | 596 ----- compilerplugins/clang/store/constfields.py | 86 compilerplugins/clang/store/constfieldsrewrite.cxx | 169 - compilerplugins/clang/store/constvars.cxx | 558 ----- compilerplugins/clang/store/convertlong.cxx | 139 - compilerplugins/clang/store/countusersofdefaultparams.cxx | 250 -- compilerplugins/clang/store/countusersofdefaultparams.py | 80 compilerplugins/clang/store/deadclass.cxx | 69 compilerplugins/clang/store/defaultparams.cxx | 128 - compilerplugins/clang/store/deletedspecial.cxx | 152 - compilerplugins/clang/store/derivedclass.cxx | 70 compilerplugins/clang/store/dodgyswitch.cxx | 78 compilerplugins/clang/store/doubleconvert.cxx | 83 compilerplugins/clang/store/finalprotected.cxx | 84 compilerplugins/clang/store/findoncontainer.cxx | 77 compilerplugins/clang/store/fpcomparison.cxx | 382 --- compilerplugins/clang/store/inlinefields.cxx | 251 -- compilerplugins/clang/store/inlinefields.py | 72 compilerplugins/clang/store/inlinesimplememberfunctions.cxx | 294 -- compilerplugins/clang/store/lclstaticfix.cxx | 54 compilerplugins/clang/store/lclstaticfix.hxx | 30 compilerplugins/clang/store/manualrefcount.cxx | 318 -- compilerplugins/clang/store/memoryvar.cxx | 238 -- compilerplugins/clang/store/namespaceindentation.cxx | 220 - compilerplugins/clang/store/oncevar.cxx | 414 --- compilerplugins/clang/store/optmove.cxx | 161 - compilerplugins/clang/store/optvalue.cxx | 66 compilerplugins/clang/store/paintmethodconversion.cxx | 94 compilerplugins/clang/store/postfixincrementfix.cxx | 132 - compilerplugins/clang/store/postfixincrementfix.hxx | 35 compilerplugins/clang/store/putpoolitem.cxx | 103 compilerplugins/clang/store/refassign.cxx | 151 - compilerplugins/clang/store/removeforwardstringdecl.cxx | 78 compilerplugins/clang/store/removeforwardstringdecl.hxx | 32 compilerplugins/clang/store/removevirtuals.cxx | 150 - compilerplugins/clang/store/returnbyref.cxx | 138 - compilerplugins/clang/store/returnunique.cxx | 83 compilerplugins/clang/store/revisibility.cxx | 89 compilerplugins/clang/store/rtlconstasciimacro.cxx | 144 - compilerplugins/clang/store/rtlref.cxx | 143 - compilerplugins/clang/store/sequentialassign.cxx | 327 -- compilerplugins/clang/store/sfxitemsetrewrite.cxx | 419 --- compilerplugins/clang/store/shouldreturnbool.cxx | 248 -- compilerplugins/clang/store/simplifybool.cxx | 1333 ------------ compilerplugins/clang/store/staticvar.cxx | 208 - compilerplugins/clang/store/stdexception.cxx | 188 - compilerplugins/clang/store/stringbuffer.cxx | 75 compilerplugins/clang/store/stringliteraldefine.cxx | 171 - compilerplugins/clang/store/stringloop.cxx | 292 -- compilerplugins/clang/store/stylepolice.cxx | 196 - compilerplugins/clang/store/svstreamoutputoperators.cxx | 223 -- compilerplugins/clang/store/test/deadclass.cxx | 15 compilerplugins/clang/store/test/rtlref.cxx | 33 compilerplugins/clang/store/toolslong.cxx | 653 ----- compilerplugins/clang/store/tutorial/tutorial1.cxx | 68 compilerplugins/clang/store/tutorial/tutorial1.hxx | 35 compilerplugins/clang/store/tutorial/tutorial1_example.cxx | 21 compilerplugins/clang/store/tutorial/tutorial2.cxx | 95 compilerplugins/clang/store/tutorial/tutorial2.hxx | 35 compilerplugins/clang/store/tutorial/tutorial2_example.cxx | 18 compilerplugins/clang/store/tutorial/tutorial3.cxx | 77 compilerplugins/clang/store/tutorial/tutorial3.hxx | 37 compilerplugins/clang/store/unique2optional.cxx | 264 -- compilerplugins/clang/store/unusedcode.cxx | 77 compilerplugins/clang/store/unusedfieldsremove.cxx | 137 - compilerplugins/clang/store/unusedindex.cxx | 87 compilerplugins/clang/store/unusedmethodsremove.cxx | 153 - compilerplugins/clang/store/valueof.cxx | 148 - compilerplugins/clang/test/constfields.cxx | 45 compilerplugins/clang/test/constvars.cxx | 94 compilerplugins/clang/test/convertlong.cxx | 42 compilerplugins/clang/test/dodgyswitch.cxx | 30 compilerplugins/clang/test/doubleconvert.cxx | 25 compilerplugins/clang/test/namespaceindentation.cxx | 50 compilerplugins/clang/test/oncevar.cxx | 66 compilerplugins/clang/test/optmove.cxx | 53 compilerplugins/clang/test/optvalue.cxx | 75 compilerplugins/clang/test/putpoolitem.cxx | 48 compilerplugins/clang/test/refassign.cxx | 31 compilerplugins/clang/test/sequentialassign.cxx | 98 compilerplugins/clang/test/shouldreturnbool.cxx | 31 compilerplugins/clang/test/staticvar.cxx | 80 compilerplugins/clang/test/stringbuffer.cxx | 22 compilerplugins/clang/test/stringliteraldefine.cxx | 56 compilerplugins/clang/test/stringloop.cxx | 41 compilerplugins/clang/test/unusedindex.cxx | 42 solenv/clang-format/excludelist | 56 99 files changed, 15024 deletions(-)
New commits: commit 390f378723b65fdc77b314858cd8a48605749b79 Author: Stephan Bergmann <[email protected]> AuthorDate: Thu Oct 16 14:48:02 2025 +0200 Commit: Stephan Bergmann <[email protected]> CommitDate: Fri Oct 17 08:00:14 2025 +0200 Remove atticized compilerplugins and their accompanying tests (see the discussion starting in the comments at <https://gerrit.libreoffice.org/c/core/+/136841/3#message-2d2ff562ccd80cf776f0b2068f028dd22a40e4e9> "move old/unused plugins to store") Change-Id: I9582e934c3224dd0a4c25d0574b47f9ee49ed611 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192554 Reviewed-by: Stephan Bergmann <[email protected]> Tested-by: Jenkins diff --git a/compilerplugins/clang/store/README b/compilerplugins/clang/store/README deleted file mode 100644 index b562544128f2..000000000000 --- a/compilerplugins/clang/store/README +++ /dev/null @@ -1,3 +0,0 @@ -This plugin actions are not used. They are still kept in case they would be useful again -(they can be activated again by simply moving them back in the clang/ source directory) -or simply as a reference when writing new plugins. diff --git a/compilerplugins/clang/store/badvectorinit.cxx b/compilerplugins/clang/store/badvectorinit.cxx deleted file mode 100644 index 4ab086d9ecc8..000000000000 --- a/compilerplugins/clang/store/badvectorinit.cxx +++ /dev/null @@ -1,214 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <cassert> -#include <string> -#include <iostream> -#include <fstream> -#include <set> -#include "plugin.hxx" - -/** - -Comments from Bjoern Michaelsen: - -Killing the 1-argument vector fill constructor: - - std::vector< basebmp::Color > aDevPal(2); - -in general is probably a Good Thing(tm). It can just be too misleading. -Requiring at least the explicit two-value fill constructor for the rare cases where -someone wants a filled vector isn't too much to ask and less prone to -misunderstandings: - - std::vector< basebmp::Color > aDevPal(2, basebmp::Color(0,0,0)); - -Although that _still_ might be misleading[1], so turning all those into the -somewhat longer, but more explicit: - - std::vector< basebmp::Color > aDevPal; - aDevPal.reserve(2); - aDevPal.push_back(...); - ... - -> So I suppose the check would be for a size reservation on a vector -> followed by push_back - rather than some array indexing - does that make -> sense ? or did I go crazy ;-) - -Yes, in general you want neither of the above forms. Preferably instead of -e.g.: - - std::vector< basebmp::Color > aDevPal(2); - aDevPal[0] = basebmp::Color( 0, 0, 0 ); - aDevPal[1] = basebmp::Color( 0xff, 0xff, 0xff ); - -you would -- if possible -- simply: - - std::vector< basebmp::Color > aDevPal{ - basebmp::Color( 0, 0, 0 ), - basebmp::Color( 0xff, 0xff, 0xff ) }; - -and only for complex cases, where you do not have the elements statically -available, something like: - - std::vector< foo > vFoos; - vFoos.reserve(vInput.size()); - std::transform(std::back_inserter(vFoos), - vInput.begin(), - vInput.end(), - [] (decltype(vInput)::value_type aInputValue) { return do_something(aInputValue); }); - -see also: -https://skyfromme.wordpress.com/2015/03/02/50-ways-to-fill-your-vector/ -https://skyfromme.wordpress.com/2015/03/12/following-the-white-rabbit/ -(tl;dr: Use initializer lists to fill vectors when possible). - -Best, - -Bjoern - -[1] Well, except that: - std::vector<int>(3, 0) - is doing something different from: - std::vector<int>{3, 0} - just to make things more interesting. But hey, that's C++ for you. - But that wart exists for the 1-arg ctor too -- yet another reason to kill that. -*/ - -namespace { - - -class BadVectorInit: - public loplugin::FilteringPlugin<BadVectorInit> -{ -public: - explicit BadVectorInit(InstantiationData const & data): FilteringPlugin(data) {} - - virtual void run() override - { - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); - } - - bool VisitCXXConstructExpr(const CXXConstructExpr* ); - bool TraverseFunctionDecl(FunctionDecl* ); - bool VisitCXXMemberCallExpr(const CXXMemberCallExpr* ); -private: - StringRef getFilename(SourceLocation loc); - std::set<const VarDecl*> suspectSet; -}; - -bool BadVectorInit::TraverseFunctionDecl(FunctionDecl* decl) -{ - bool ret = RecursiveASTVisitor::TraverseFunctionDecl(decl); - suspectSet.clear(); - return ret; -} - -StringRef BadVectorInit::getFilename(SourceLocation loc) -{ - SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc); - StringRef name { getFilenameOfLocation(spellingLocation) }; - return name; -} - -bool BadVectorInit::VisitCXXMemberCallExpr(const CXXMemberCallExpr* expr) -{ - if (suspectSet.empty() || ignoreLocation( expr )) - return true; - - // need to exclude some false positives - StringRef aFileName = getFilename(expr->getLocStart()); - if (aFileName == SRCDIR "/framework/source/services/autorecovery.cxx" - || aFileName == SRCDIR "/vcl/source/opengl/OpenGLHelper.cxx" - || aFileName == SRCDIR "/vcl/source/gdi/gdimtf.cxx" - ) - { - return true; - } - - const FunctionDecl* functionDecl = expr->getDirectCallee(); - if (!functionDecl) - return true; - if (functionDecl->getNameAsString().find("push_back") == string::npos) - return true; - const DeclRefExpr* declExpr = dyn_cast<DeclRefExpr>(expr->getImplicitObjectArgument()); - if (!declExpr) - return true; - const VarDecl* varDecl = dyn_cast<VarDecl>(declExpr->getDecl()); - if (!varDecl) - return true; - varDecl = varDecl->getCanonicalDecl(); - if (suspectSet.find(varDecl) == suspectSet.end()) - return true; - report( - DiagnosticsEngine::Warning, - "calling push_back after using sized constructor", - expr->getLocStart()) - << expr->getSourceRange(); - report( - DiagnosticsEngine::Note, - "on this var", - varDecl->getLocStart()) - << varDecl->getSourceRange(); - - return true; -} - -bool BadVectorInit::VisitCXXConstructExpr(const CXXConstructExpr* expr) -{ - if (ignoreLocation( expr )) - return true; - - const CXXConstructorDecl *consDecl = expr->getConstructor(); - consDecl = consDecl->getCanonicalDecl(); - - // The default constructor can potentially have a parameter, e.g. - // in glibcxx-debug the default constructor is: - // explicit vector(const _Allocator& __a = _Allocator()) - if (consDecl->param_size() == 0 || consDecl->isDefaultConstructor()) - return true; - - std::string aParentName = consDecl->getParent()->getQualifiedNameAsString(); - if (aParentName.find("vector") == string::npos && aParentName.find("deque") == string::npos) - return true; - - // ignore the copy/move constructors, and those taking an initializer_list - // etc.: - if (consDecl->isCopyConstructor() || consDecl->isMoveConstructor()) - return true; - const ParmVarDecl* pParam = consDecl->getParamDecl(0); - std::string aParam1 = pParam->getOriginalType().getAsString(); - if (aParam1.find("initializer_list") != string::npos - || aParam1.find("iterator") != string::npos) - return true; - - // found a call to the 1-arg vector constructor, now look for the VarDecl it belongs to - - const Stmt* parent = expr; - do { - parent = parentStmt(parent); - if (!parent) break; - if (isa<DeclStmt>(parent)) - { - const DeclStmt* declStmt = dyn_cast<DeclStmt>(parent); - const Decl* decl = declStmt->getSingleDecl(); - if (decl && isa<VarDecl>(decl)) - suspectSet.insert(dyn_cast<VarDecl>(decl)->getCanonicalDecl()); - break; - } - } while (true); - - return true; -} - -loplugin::Plugin::Registration< BadVectorInit > X("badvectorinit", true); - -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/bodynotinblock.cxx b/compilerplugins/clang/store/bodynotinblock.cxx deleted file mode 100644 index ca4f904992c8..000000000000 --- a/compilerplugins/clang/store/bodynotinblock.cxx +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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. - * - */ - -#include "bodynotinblock.hxx" - -namespace loplugin -{ - -/* -This is a compile check. - -Check for two statements that are both indented to look like a body of if/while/for -but are not inside a compound statement and thus the second one is unrelated. - -For example: - - if( a != 0 ) - b = 2; - c = 3; - -Here either both statements should be inside {} or the second statement in indented wrong. -*/ - -BodyNotInBlock::BodyNotInBlock( const InstantiationData& data ) - : Plugin( data ) - { - } - -void BodyNotInBlock::run() - { - TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); - } - -bool BodyNotInBlock::VisitIfStmt( const IfStmt* stmt ) - { - if( ignoreLocation( stmt )) - return true; - checkBody( stmt->getThen(), stmt->getIfLoc(), 0, stmt->getElse() != NULL ); - checkBody( stmt->getElse(), stmt->getElseLoc(), 0 ); - return true; - } - -bool BodyNotInBlock::VisitWhileStmt( const WhileStmt* stmt ) - { - if( ignoreLocation( stmt )) - return true; - checkBody( stmt->getBody(), stmt->getWhileLoc(), 1 ); - return true; - } - -bool BodyNotInBlock::VisitForStmt( const ForStmt* stmt ) - { - if( ignoreLocation( stmt )) - return true; - checkBody( stmt->getBody(), stmt->getForLoc(), 2 ); - return true; - } - -bool BodyNotInBlock::VisitCXXForRangeStmt( const CXXForRangeStmt* stmt ) - { - if( ignoreLocation( stmt )) - return true; - checkBody( stmt->getBody(), stmt->getForLoc(), 2 ); - return true; - } - -void BodyNotInBlock::checkBody( const Stmt* body, SourceLocation stmtLocation, int stmtType, bool dontGoUp ) - { - if( body == NULL ) - return; - // TODO: If the if/else/while/for comes from a macro expansion, ignore it completely for - // now. The code below could assume everything is in the same place (and thus also column) - // and give a false warning. Moreover some macros are rather loosely written and would - // result in poor formatting. To be evaluated later, maybe this could be handled - // including macro expansion. - if( stmtLocation.isMacroID()) - return; - if( dyn_cast< CompoundStmt >( body )) - return; // if body is a compound statement, then it is in {} - const Stmt* previousParent = parentStmt( body ); // Here the statement itself. - // Find the next statement (in source position) after 'body'. - for(;;) - { - const Stmt* parent = parentStmt( previousParent ); - if( parent == NULL ) - break; - for( ConstStmtIterator it = parent->child_begin(); - it != parent->child_end(); - ) - { - if( *it == previousParent ) // found grand(grand...)parent - { - // get next statement after our (grand...)parent - ++it; - while( it != parent->child_end() && *it == NULL ) - ++it; // skip empty ones (missing 'else' bodies for example) - if( it != parent->child_end()) - { - bool invalid1, invalid2; - unsigned bodyColumn = compiler.getSourceManager() - .getPresumedColumnNumber( body->getLocStart(), &invalid1 ); - unsigned nextStatementColumn = compiler.getSourceManager() - .getPresumedColumnNumber( (*it)->getLocStart(), &invalid2 ); - if( invalid1 || invalid2 ) - return; - if( bodyColumn == nextStatementColumn ) - { - report( DiagnosticsEngine::Warning, - "statement aligned as second statement in %select{if|while|for}0 body but not in a statement block", - (*it)->getLocStart()) << stmtType; - report( DiagnosticsEngine::Note, - "%select{if|while|for}0 body statement is here", - body->getLocStart()) << stmtType; - } - return; - } - // else we need to go higher to find the next statement - } - else - ++it; - } - // If going up would mean leaving a {} block, stop, because the } should - // make it visible the two statements are not in the same body. - if( dyn_cast< CompoundStmt >( parent )) - return; - // If the body to be checked is a body of an if statement that has also - // an else part, don't go up, the else is after the body and should make - // it clear the body does not continue there. - if( dontGoUp ) - return; - previousParent = parent; - } - } - -static Plugin::Registration< BodyNotInBlock > X( "bodynotinblock" ); - -} // namespace - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/bodynotinblock.hxx b/compilerplugins/clang/store/bodynotinblock.hxx deleted file mode 100644 index d74a4fbc169d..000000000000 --- a/compilerplugins/clang/store/bodynotinblock.hxx +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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. - * - */ - -#pragma once - -#include "plugin.hxx" - -namespace loplugin -{ - -class BodyNotInBlock - : public loplugin::FilteringPlugin<BodyNotInBlock> - { - public: - explicit BodyNotInBlock( const InstantiationData& data ); - virtual void run() override; - bool VisitIfStmt( const IfStmt* stmt ); - bool VisitWhileStmt( const WhileStmt* stmt ); - bool VisitForStmt( const ForStmt* stmt ); - bool VisitCXXForRangeStmt( const CXXForRangeStmt* stmt ); - private: - void checkBody( const Stmt* body, SourceLocation stmtLocation, int stmtType, bool dontGoUp = false ); - }; - -} // namespace - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingassignop.cxx b/compilerplugins/clang/store/cascadingassignop.cxx deleted file mode 100644 index a1098ee0642c..000000000000 --- a/compilerplugins/clang/store/cascadingassignop.cxx +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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. - * - */ - -#include "cascadingassignop.hxx" - -/* -This is a compile check. - -It checks for complex statements with conditional operators in conditional -operators, which are error prone, e.g. - Thing foo = IsBar() ? ( IsBaz() ? b1 : b2 ) : b3; - -However, it finds 556 cases in sw/source alone, thus likely needs some more -restricting, e.g. by checking for multiline conditional operator statements or -a certain length in characters (but that needs the Context/SourceManager, which -I haven't played with yet). -*/ - -// the value is rather arbitrary, but code above this number of stmts begins to -// be smelly -static const int stmtlimit = 20; - -namespace loplugin -{ - -struct WalkCounter -{ - int stmtcount; - bool cascading; - bool conditionals; -}; - -// Ctor, nothing special, pass the argument(s). -CascadingAssignOp::CascadingAssignOp( const InstantiationData& data ) - : FilteringPlugin( data ) -{ -} - -// Perform the actual action. -void CascadingAssignOp::run() -{ - // Traverse the whole AST of the translation unit (i.e. examine the whole source file). - // The Clang AST helper class will call VisitReturnStmt for every return statement. - TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); -} - -void CascadingAssignOp::Walk( const Stmt* stmt, WalkCounter& c ) -{ - for(Stmt::const_child_iterator it = stmt->child_begin(); it != stmt->child_end(); ++it) - { - ++c.stmtcount; - const BinaryOperator* binop = dyn_cast< BinaryOperator >( *it ); - if ( binop ) - { - if ( (binop->isAssignmentOp() || binop->isCompoundAssignmentOp())) - c.cascading = true; - if ( dyn_cast< AbstractConditionalOperator >( binop ) || binop->isLogicalOp()) - c.conditionals = true; - } - Walk(*it, c); - } -} - -bool CascadingAssignOp::VisitStmt( const Stmt* stmt ) -{ - const BinaryOperator* binop = dyn_cast< BinaryOperator >( stmt ); - if ( binop && (binop->isAssignmentOp() || binop->isCompoundAssignmentOp())) - { - WalkCounter c = { 0, false, false }; - Walk(binop, c); - if(c.cascading && c.conditionals && c.stmtcount >= stmtlimit) - { - std::string msg("cascading assign operator mixing in conditionals, complexity: "); - msg.append(std::to_string(c.stmtcount)); - report( DiagnosticsEngine::Warning, msg, binop->getLocStart()); - } - } - return true; -} - -// Register the plugin action with the LO plugin handling. -static Plugin::Registration< CascadingAssignOp > X( "cascadingassignop" ); - -} // namespace loplugin - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingassignop.hxx b/compilerplugins/clang/store/cascadingassignop.hxx deleted file mode 100644 index 147ecaad0dd2..000000000000 --- a/compilerplugins/clang/store/cascadingassignop.hxx +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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. - * - */ - -#pragma once - -#include "plugin.hxx" - -namespace loplugin -{ - -struct WalkCounter; - -// The class implementing the plugin action. -class CascadingAssignOp - // Inherits from the Clang class that will allow examining the Clang AST tree (i.e. syntax tree). - : public FilteringPlugin< CascadingAssignOp > - { - public: - CascadingAssignOp( const InstantiationData& data ); - virtual void run() override; - void Walk( const Stmt* stmt, WalkCounter& c ); - bool VisitStmt( const Stmt* stmt ); - }; - -} // namespace loplugin - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingcondop.cxx b/compilerplugins/clang/store/cascadingcondop.cxx deleted file mode 100644 index 4671f41b436a..000000000000 --- a/compilerplugins/clang/store/cascadingcondop.cxx +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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. - * - */ - -#include "cascadingcondop.hxx" - -/* -This is a compile check. - -It checks for complex statements with conditional operators in conditional -operators, which are error prone, e.g. - Thing foo = IsBar() ? ( IsBaz() ? b1 : b2 ) : b3; - -However, it finds 556 cases in sw/source alone, thus likely needs some more -restricting, e.g. by checking for multiline conditional operator statements or -a certain length in characters (but that needs the Context/SourceManager, which -I haven't played with yet). -*/ - -// the value is rather arbitrary, but code above this number of stmts begins to -// be smelly -static const int stmtlimit = 50; - -namespace loplugin -{ -struct WalkCounter -{ - int stmtcount; - bool cascading; -}; - -// Ctor, nothing special, pass the argument(s). -CascadingCondOp::CascadingCondOp(const InstantiationData& data) - : FilteringPlugin(data) -{ -} - -// Perform the actual action. -void CascadingCondOp::run() -{ - // Traverse the whole AST of the translation unit (i.e. examine the whole source file). - // The Clang AST helper class will call VisitReturnStmt for every return statement. - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); -} - -void CascadingCondOp::Walk(const Stmt* stmt, WalkCounter& c) -{ - for (Stmt::const_child_iterator it = stmt->child_begin(); it != stmt->child_end(); ++it) - { - ++c.stmtcount; - if (dyn_cast<ConditionalOperator>(*it)) - c.cascading = true; - Walk(*it, c); - } -} - -bool CascadingCondOp::VisitStmt(const Stmt* stmt) -{ - if (const ConditionalOperator* condop = dyn_cast<ConditionalOperator>(stmt)) - { - WalkCounter c = { 0, false }; - Walk(condop, c); - if (c.cascading && c.stmtcount >= stmtlimit) - { - std::string msg("cascading conditional operator, complexity: "); - msg.append(std::to_string(c.stmtcount)); - report(DiagnosticsEngine::Warning, msg, condop->getLocStart()); - } - } - return true; -} - -// Register the plugin action with the LO plugin handling. -static Plugin::Registration<CascadingCondOp> X("cascadingcondop"); - -} // namespace loplugin - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingcondop.hxx b/compilerplugins/clang/store/cascadingcondop.hxx deleted file mode 100644 index 599fafd8263a..000000000000 --- a/compilerplugins/clang/store/cascadingcondop.hxx +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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. - * - */ - -#pragma once - -#include "plugin.hxx" - -namespace loplugin -{ - -struct WalkCounter; - -// The class implementing the plugin action. -class CascadingCondOp - // Inherits from the Clang class that will allow examining the Clang AST tree (i.e. syntax tree). - : public FilteringPlugin< CascadingCondOp > - { - public: - CascadingCondOp( const InstantiationData& data ); - virtual void run() override; - void Walk( const Stmt* stmt, WalkCounter& c ); - bool VisitStmt( const Stmt* stmt ); - }; - -} // namespace loplugin - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/changefunctioncalls.cxx b/compilerplugins/clang/store/changefunctioncalls.cxx deleted file mode 100644 index 9f5390a2150c..000000000000 --- a/compilerplugins/clang/store/changefunctioncalls.cxx +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * 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 -- change getDirectCallee() to getCallee() -- etc. -*/ - -#include "plugin.hxx" -#include "check.hxx" - -namespace loplugin -{ - -class ChangeFunctionCalls - : public loplugin::FilteringRewritePlugin< ChangeFunctionCalls > - { - public: - explicit ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter ); - virtual void run() override; - bool VisitCallExpr( const CallExpr* call ); - }; - -ChangeFunctionCalls::ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter ) - : FilteringRewritePlugin( compiler, rewriter ) - { - } - -void ChangeFunctionCalls::run() - { - TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); - } - -bool ChangeFunctionCalls::VisitCallExpr( const CallExpr* call ) - { - if( ignoreLocation( call )) - return true; - // Using getDirectCallee() here means that we find only calls - // that call the function directly (i.e. not using a pointer, for example). - // Use getCallee() to include also those : - // if( const FunctionDecl* func = dyn_cast_or_null< FunctionDecl >( call->getCalleeDecl())) - if( const FunctionDecl* func = call->getDirectCallee()) - { - // 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" )) - { - auto qt = loplugin::DeclCheck(func); - if( qt.Function("bar").GlobalNamespace() ) - { - // 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 - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/checkunusedparams.cxx b/compilerplugins/clang/store/checkunusedparams.cxx deleted file mode 100644 index 33916b4810bb..000000000000 --- a/compilerplugins/clang/store/checkunusedparams.cxx +++ /dev/null @@ -1,502 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <cassert> -#include <string> -#include <set> -#include <iostream> - -#include "config_clang.h" - -#include "plugin.hxx" - -/** -Find parameters that have no name, i.e. they are unused and we're worked around the "unused parameter" warning. - -Most of these can be removed. - -TODO look for places where we are working around the warning by doing - (void) param1; - */ -namespace { - -class CheckUnusedParams: public loplugin::FilteringPlugin<CheckUnusedParams> { -public: - explicit CheckUnusedParams(loplugin::InstantiationData const & data): - FilteringPlugin(data) {} - void run() override; - bool VisitFunctionDecl(FunctionDecl const *); - bool VisitUnaryOperator(UnaryOperator const *); - bool VisitInitListExpr(InitListExpr const *); - bool VisitCallExpr(CallExpr const *); - bool VisitBinaryOperator(BinaryOperator const *); - bool VisitCXXConstructExpr(CXXConstructExpr const *); -private: - void checkForFunctionDecl(Expr const *, bool bCheckOnly = false); - std::set<FunctionDecl const *> m_addressOfSet; - enum class PluginPhase { FindAddressOf, Warning }; - PluginPhase m_phase; -}; - -void CheckUnusedParams::run() -{ - StringRef fn(handler.getMainFileName()); - if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/")) - return; - // Taking pointer to function - if (loplugin::isSamePathname(fn, SRCDIR "/l10ntools/source/xmlparse.cxx")) - return; - // macro magic which declares something needed by an external library - if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/misc/gridprinter.cxx")) - return; - - // valid test/qa code - if (loplugin::hasPathnamePrefix(fn, SRCDIR "/compilerplugins/clang/test/")) - return; - if (loplugin::isSamePathname(fn, SRCDIR "/cppu/qa/test_reference.cxx")) - return; - - // leave this alone for now - if (loplugin::hasPathnamePrefix(fn, SRCDIR "/libreofficekit/")) - return; - // this has a certain pattern to its code which appears to include lots of unused params - if (loplugin::hasPathnamePrefix(fn, SRCDIR "/xmloff/")) - return; - // I believe someone is busy working on this chunk of code - if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/dataprovider.cxx")) - return; - // I think erack is working on stuff here - if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xiformula.cxx")) - return; - // lots of callbacks here - if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/lotus/op.cxx")) - return; - // template magic - if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/html/htmlpars.cxx")) - return; - - m_phase = PluginPhase::FindAddressOf; - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); - m_phase = PluginPhase::Warning; - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); -} - -bool CheckUnusedParams::VisitUnaryOperator(UnaryOperator const * op) { - if (op->getOpcode() != UO_AddrOf) { - return true; - } - if (m_phase != PluginPhase::FindAddressOf) - return true; - checkForFunctionDecl(op->getSubExpr()); - return true; -} - -bool CheckUnusedParams::VisitBinaryOperator(BinaryOperator const * binaryOperator) { - if (binaryOperator->getOpcode() != BO_Assign) { - return true; - } - if (m_phase != PluginPhase::FindAddressOf) - return true; - checkForFunctionDecl(binaryOperator->getRHS()); - return true; -} - -bool CheckUnusedParams::VisitCallExpr(CallExpr const * callExpr) { - if (m_phase != PluginPhase::FindAddressOf) - return true; - for (auto arg : callExpr->arguments()) - checkForFunctionDecl(arg); - return true; -} - -bool CheckUnusedParams::VisitCXXConstructExpr(CXXConstructExpr const * constructExpr) { - if (m_phase != PluginPhase::FindAddressOf) - return true; - for (auto arg : constructExpr->arguments()) - checkForFunctionDecl(arg); - return true; -} - -bool CheckUnusedParams::VisitInitListExpr(InitListExpr const * initListExpr) { - if (m_phase != PluginPhase::FindAddressOf) - return true; - for (auto subStmt : *initListExpr) - checkForFunctionDecl(dyn_cast<Expr>(subStmt)); - return true; -} - -void CheckUnusedParams::checkForFunctionDecl(Expr const * expr, bool bCheckOnly) { - auto e1 = expr->IgnoreParenCasts(); - auto declRef = dyn_cast<DeclRefExpr>(e1); - if (!declRef) - return; - auto functionDecl = dyn_cast<FunctionDecl>(declRef->getDecl()); - if (!functionDecl) - return; - if (bCheckOnly) - getParentStmt(expr)->dump(); - else - m_addressOfSet.insert(functionDecl->getCanonicalDecl()); -} - -static int noFieldsInRecord(RecordType const * recordType) { - auto recordDecl = recordType->getDecl(); - // if it's complicated, let's just assume it has fields - if (isa<ClassTemplateSpecializationDecl>(recordDecl)) - return 1; - return std::distance(recordDecl->field_begin(), recordDecl->field_end()); -} -static bool startswith(const std::string& rStr, const char* pSubStr) { - return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; -} -static bool endswith(const std::string& rStr, const char* pSubStr) { - auto len = strlen(pSubStr); - if (len > rStr.size()) - return false; - return rStr.compare(rStr.size() - len, rStr.size(), pSubStr) == 0; -} - -bool CheckUnusedParams::VisitFunctionDecl(FunctionDecl const * decl) { - if (m_phase != PluginPhase::Warning) - return true; - if (m_addressOfSet.find(decl->getCanonicalDecl()) != m_addressOfSet.end()) - return true; - if (ignoreLocation(decl)) - return true; - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) - return true; - - auto cxxMethodDecl = dyn_cast<CXXMethodDecl>(decl); - if (cxxMethodDecl) { - if (cxxMethodDecl->isVirtual()) - return true; - auto cxxConstructorDecl = dyn_cast<CXXConstructorDecl>(cxxMethodDecl); - if (cxxConstructorDecl && cxxConstructorDecl->isCopyOrMoveConstructor()) - return true; - } - if (!decl->isThisDeclarationADefinition()) - return true; - if (decl->isFunctionTemplateSpecialization()) - return true; - if (decl->isDeleted()) - return true; - if (decl->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate) - return true; - if (decl->isOverloadedOperator()) - return true; - if (decl->isExternC()) - return true; - - //TODO, filtering out any functions relating to class templates for now: - CXXRecordDecl const * r = dyn_cast<CXXRecordDecl>(decl->getDeclContext()); - if (r != nullptr - && (r->getTemplateSpecializationKind() != TSK_Undeclared - || r->isDependentContext())) - { - return true; - } - FunctionDecl const * canon = decl->getCanonicalDecl(); - std::string fqn = canon->getQualifiedNameAsString(); // because sometimes clang returns nonsense for the filename of canon - if (ignoreLocation(canon)) - return true; - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(canon->getLocation()))) - return true; - StringRef fn = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(canon->getBeginLoc())); - // Some backwards compat magic. - // TODO Can probably be removed, but need to do some checking - if (loplugin::isSamePathname(fn, SRCDIR "/include/sax/fshelper.hxx")) - return true; - // Platform-specific code - if (loplugin::isSamePathname(fn, SRCDIR "/include/svl/svdde.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/svmain.hxx")) - return true; - // passing pointer to function - if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/BitmapReadAccess.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtkobject.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtksalframe.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtkframe.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/extensions/source/propctrlr/propertyeditor.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/solar/inc/navtoolbar.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/grammar.cxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/lexer.cxx")) - return true; - // marked with a TODO/FIXME - if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/sallayout.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/accessibility/inc/standard/vclxaccessiblelist.hxx")) - return true; - // these are "extern C" but clang doesn't seem to report that accurately - if (loplugin::isSamePathname(fn, SRCDIR "/sax/source/fastparser/fastparser.cxx")) - return true; - // these all follow the same pattern, seems a pity to break that - if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/graphicfilter.hxx")) - return true; - // looks like work in progress - if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/ipdf/pdfdocument.cxx")) - return true; - // macro magic - if (loplugin::isSamePathname(fn, SRCDIR "/basctl/source/inc/basidesh.hxx")) - return true; - // template magic - if (loplugin::hasPathnamePrefix(fn, SRCDIR "/canvas/")) - return true; - if (loplugin::hasPathnamePrefix(fn, SRCDIR "/include/canvas/")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/include/comphelper/unwrapargs.hxx")) - return true; - // this looks like vaguely useful code (ParseError) that I'm loathe to remove - if (loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/inc/RowFunctionParser.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/include/svx/EnhancedCustomShapeFunctionParser.hxx")) - return true; - // TODO marker parameter in constructor, should probably be using an enum - if (loplugin::isSamePathname(fn, SRCDIR "/framework/inc/uielement/uicommanddescription.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/SlideTransitionPane.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/animations/CustomAnimationPane.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/table/TableDesignPane.hxx")) - return true; - // debug stuff - if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/core/data/column2.cxx")) - return true; - // weird stuff - if (loplugin::isSamePathname(fn, SRCDIR "/scaddins/source/analysis/analysishelper.hxx")) - return true; - // SFX_DECL_CHILDWINDOWCONTEXT macro stuff - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/NavigatorChildWindow.hxx")) - return true; - // TODO, need to remove this from the .sdi file too - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/SlideSorterViewShell.hxx")) - return true; - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/OutlineViewShell.hxx")) - return true; - // SFX_DECL_INTERFACE macro stuff - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/ViewShellBase.hxx")) - return true; - // debug stuff - if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/ppt/pptinanimations.hxx")) - return true; - // takes pointer to fn - if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/shell.hxx")) - return true; - // TODO, need to remove this from the .sdi file too - if (fqn == "SfxObjectShell::StateView_Impl") - return true; - // SFX_DECL_CHILDWINDOW_WITHID macro - if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/infobar.hxx")) - return true; - // this looks like vaguely useful code (ParseError) that I'm loathe to remove - if (loplugin::isSamePathname(fn, SRCDIR "/slideshow/source/inc/slideshowexceptions.hxx")) - return true; - // SFX_DECL_VIEWFACTORY macro - if (loplugin::isSamePathname(fn, SRCDIR "/starmath/inc/view.hxx")) - return true; - // debugging - if (fqn == "BrowseBox::DoShowCursor" || fqn == "BrowseBox::DoHideCursor") - return true; - // if I change this one, it then overrides a superclass virtual method - if (fqn == "GalleryBrowser2::KeyInput") - return true; - // takes pointer to function - if (fqn == "cmis::AuthProvider::onedriveAuthCodeFallback" || fqn == "cmis::AuthProvider::gdriveAuthCodeFallback") - return true; - if (fqn == "ooo_mount_operation_ask_password") - return true; - // TODO tricky to remove because of default params - if (fqn == "xmloff::OAttribute2Property::addBooleanProperty") - return true; - // taking pointer to function - if (fqn == "sw::DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl" - || fqn == "sw::DocumentContentOperationsManager::DeleteRangeImpl" - || fqn == "SwTableFormula::GetFormulaBoxes" - || fqn == "SwFEShell::Drag" - || fqn == "GetASCWriter" || fqn == "GetHTMLWriter" || fqn == "GetXMLWriter" - || fqn == "SwWrtShell::UpdateLayoutFrame" || fqn == "SwWrtShell::DefaultDrag" - || fqn == "SwWrtShell::DefaultEndDrag" - || startswith(fqn, "SwWW8ImplReader::Read_")) - return true; - // WIN32 only - if (fqn == "SwFntObj::GuessLeading") - return true; - // SFX_DECL_CHILDWINDOW_WITHID macro - if (fqn == "SwSpellDialogChildWindow::SwSpellDialogChildWindow" - || fqn == "SwFieldDlgWrapper::SwFieldDlgWrapper" - || fqn == "SwInputChild::SwInputChild") - return true; - // SFX_DECL_VIEWFACTORY macro - if (fqn == "SwSrcView::SwSrcView") - return true; - // Serves to disambiguate two very similar methods - if (fqn == "MSWordStyles::BuildGetSlot") - return true; - // TODO there are just too many default params to make this worth fixing right now - if (fqn == "ScDocument::CopyMultiRangeFromClip") - return true; - // TODO looks like this needs fixing? - if (fqn == "ScTable::ExtendPrintArea") - return true; - // there is a FIXME in the code - if (fqn == "ScRangeUtil::IsAbsTabArea") - return true; - // SFX_DECL_CHILDWINDOW_WITHID - if (fqn == "ScInputWindowWrapper::ScInputWindowWrapper" - || fqn == "sc::SearchResultsDlgWrapper::SearchResultsDlgWrapper") - return true; - // ExecMethod in .sdi file - if (fqn == "ScChartShell::ExecuteExportAsGraphic") - return true; - // bool marker parameter - if (fqn == "SvxIconReplacementDialog::SvxIconReplacementDialog") - return true; - // used as pointer to fn - if (endswith(fqn, "_createInstance")) - return true; - // callback - if (startswith(fqn, "SbRtl_")) - return true; - // takes pointer to fn - if (fqn == "migration::BasicMigration_create" || fqn == "migration::WordbookMigration_create" - || fqn == "comp_CBlankNode::_create" || fqn == "comp_CURI::_create" - || fqn == "comp_CLiteral::_create" || fqn == "CDocumentBuilder::_getInstance" - || fqn == "DOM::CDocumentBuilder::_getInstance" - || fqn == "xml_security::serial_number_adapter::create" - || fqn == "desktop::splash::create" || fqn == "ScannerManager_CreateInstance" - || fqn == "formula::FormulaOpCodeMapperObj::create" - || fqn == "(anonymous namespace)::createInstance" - || fqn == "x_error_handler" - || fqn == "warning_func" - || fqn == "error_func" - || fqn == "ScaDateAddIn_CreateInstance" - || fqn == "ScaPricingAddIn_CreateInstance" - || fqn == "(anonymous namespace)::PDFSigningPKCS7PasswordCallback" - || fqn == "ContextMenuEventLink" - || fqn == "DelayedCloseEventLink" - || fqn == "GDIMetaFile::ImplColMonoFnc" - || fqn == "vcl::getGlyph0" - || fqn == "vcl::getGlyph6" - || fqn == "vcl::getGlyph12" - || fqn == "setPasswordCallback" - || fqn == "VCLExceptionSignal_impl" - || fqn == "getFontTable" - || fqn == "textconversiondlgs::ChineseTranslation_UnoDialog::create" - || fqn == "pcr::DefaultHelpProvider::Create" - || fqn == "pcr::DefaultFormComponentInspectorModel::Create" - || fqn == "pcr::ObjectInspectorModel::Create" - || fqn == "GraphicExportFilter::GraphicExportFilter" - || fqn == "CertificateContainer::CertificateContainer" - || startswith(fqn, "ParseCSS1_") - ) - return true; - // TODO - if (fqn == "FontSubsetInfo::CreateFontSubsetFromType1") - return true; - // used in template magic - if (fqn == "MtfRenderer::MtfRenderer" || fqn == "shell::sessioninstall::SyncDbusSessionHelper::SyncDbusSessionHelper" - || fqn == "dp_gui::LicenseDialog::LicenseDialog" - || fqn == "(anonymous namespace)::OGLTransitionFactoryImpl::OGLTransitionFactoryImpl") - return true; - // FIXME - if (fqn == "GtkSalDisplay::filterGdkEvent" || fqn == "SvXMLEmbeddedObjectHelper::ImplReadObject" - || fqn == "chart::CachedDataSequence::CachedDataSequence") - return true; - // used via macro - if (fqn == "framework::MediaTypeDetectionHelper::MediaTypeDetectionHelper" - || fqn == "framework::UriAbbreviation::UriAbbreviation" - || fqn == "framework::DispatchDisabler::DispatchDisabler" - || fqn == "framework::DispatchRecorderSupplier::DispatchRecorderSupplier") - return true; - // TODO Armin Le Grand is still working on this - if (fqn == "svx::frame::CreateDiagFrameBorderPrimitives" - || fqn == "svx::frame::CreateBorderPrimitives") - return true; - // marked with a TODO - if (fqn == "pcr::FormLinkDialog::getExistingRelation" - || fqn == "ooo::vba::DebugHelper::basicexception" - || fqn == "ScPrintFunc::DrawToDev") - return true; - // macros at work - if (fqn == "msfilter::lcl_PrintDigest") - return true; - // TODO something wrong here, the method that calls this (Normal::GenSlidingWindowFunction) cannot be correct - if (fqn == "sc::opencl::OpBase::Gen") - return true; - // Can't change this without conflicting with another constructor with the same signature - if (fqn == "XclExpSupbook::XclExpSupbook") - return true; - // ignore the LINK macros from include/tools/link.hxx - if (decl->getLocation().isMacroID()) - return true; - // debug code in sw/ - if (fqn == "lcl_dbg_out") - return true; - - for( auto it = decl->param_begin(); it != decl->param_end(); ++it) { - auto param = *it; - if (param->hasAttr<UnusedAttr>()) - continue; - if (!param->getName().empty()) - continue; - // ignore params which are enum types with only a single enumerator, these are marker/tag types - auto paramType = param->getType(); - if (paramType->isEnumeralType()) { - auto enumType = paramType->getAs<EnumType>(); - int cnt = std::distance(enumType->getDecl()->enumerator_begin(), enumType->getDecl()->enumerator_end()); - if (cnt == 1) - continue; - } - // ignore params which are a reference to a struct which has no fields. - // These are either - // (a) marker/tag types - // (b) selective "friend" access - if (paramType->isReferenceType()) { - auto referenceType = paramType->getAs<ReferenceType>(); - if (referenceType->getPointeeType()->isRecordType()) { - auto recordType = referenceType->getPointeeType()->getAs<RecordType>(); - if (noFieldsInRecord(recordType) == 0) - continue; - } - } - else if (paramType->isRecordType()) { - if (noFieldsInRecord(paramType->getAs<RecordType>()) == 0) - continue; - } - report( DiagnosticsEngine::Warning, - "unused param %0 in %1", param->getBeginLoc()) - << param->getSourceRange() - << param->getName() - << fqn; - if (canon != decl) - { - unsigned idx = param->getFunctionScopeIndex(); - const ParmVarDecl* pOther = canon->getParamDecl(idx); - report( DiagnosticsEngine::Note, "declaration is here", - pOther->getBeginLoc()) - << pOther->getSourceRange(); - } - } - return true; -} - -loplugin::Plugin::Registration<CheckUnusedParams> X("checkunusedparams", false); - -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/comparisonwithconstant.cxx b/compilerplugins/clang/store/comparisonwithconstant.cxx deleted file mode 100644 index d796b7c3a3a1..000000000000 --- a/compilerplugins/clang/store/comparisonwithconstant.cxx +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <cassert> -#include <string> -#include <iostream> -#include <fstream> -#include <set> - -#include "compat.hxx" -#include "plugin.hxx" - -/** - Look for comparisons where the constant is on the left, it should be on the right. - */ - -namespace { - -class ComparisonWithConstant : - public loplugin::FilteringRewritePlugin<ComparisonWithConstant> -{ -public: - explicit ComparisonWithConstant(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) {} - - virtual void run() override - { - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); - } - - // Deliberately drop RecursiveASTVisitor::TraverseBinaryOperator's DataRecursionQueue - // parameter; TraverseBinaryOperator must use stack instead of data recursion for any - // children's VisitBinaryOperator to see changes to occurrence_ by a parent - // VisitBinaryOperator: - bool TraverseBinaryOperator(BinaryOperator * S) - { - auto const op = S->getOpcode(); - if (op != BO_EQ && op != BO_NE) { - return RecursiveASTVisitor::TraverseBinaryOperator(S); - } - auto const saved = occurrence_; - auto const ret = RecursiveASTVisitor::TraverseBinaryOperator(S); - occurrence_ = saved; - return ret; - } - - bool VisitBinaryOperator(const BinaryOperator *); -private: - bool rewrite(const BinaryOperator *); - std::string getExprAsString(SourceRange range); - SourceRange ignoreMacroExpansions(SourceRange range); - - bool occurrence_ = false; -}; - -bool ComparisonWithConstant::VisitBinaryOperator(const BinaryOperator* binaryOp) -{ - if (ignoreLocation(binaryOp)) { - return true; - } - if (!(binaryOp->getOpcode() == BO_EQ || binaryOp->getOpcode() == BO_NE)) { - return true; - } - // protect against clang assert - if (binaryOp->getLHS()->isValueDependent() || binaryOp->getRHS()->isValueDependent()) { - return true; - } - if (!binaryOp->getLHS()->isEvaluatable(compiler.getASTContext())) { - return true; - } - if (binaryOp->getRHS()->isEvaluatable(compiler.getASTContext())) { - return true; - } - if (occurrence_ || !rewrite(binaryOp)) - { - report( - DiagnosticsEngine::Warning, "Rather put constant on right when comparing", - binaryOp->getSourceRange().getBegin()) - << binaryOp->getSourceRange(); - } - occurrence_ = true; - return true; -} - - -bool ComparisonWithConstant::rewrite(const BinaryOperator * binaryOp) { - if (rewriter == nullptr) { - return false; - } - - auto lhsRange = ignoreMacroExpansions(binaryOp->getLHS()->getSourceRange()); - if (!lhsRange.isValid()) { - return false; - } - auto rhsRange = ignoreMacroExpansions(binaryOp->getRHS()->getSourceRange()); - if (!rhsRange.isValid()) { - return false; - } - - const std::string lhsString = getExprAsString(lhsRange); - const std::string rhsString = getExprAsString(rhsRange); - - // switch LHS and RHS - if (!replaceText(lhsRange, rhsString)) { - return false; - } - if (!replaceText(rhsRange, lhsString)) { - return false; - } - - return true; -} - -// get the expression contents -std::string ComparisonWithConstant::getExprAsString(SourceRange range) -{ - SourceManager& SM = compiler.getSourceManager(); - SourceLocation startLoc = range.getBegin(); - SourceLocation endLoc = range.getEnd(); - const char *p1 = SM.getCharacterData( startLoc ); - const char *p2 = SM.getCharacterData( endLoc ); - unsigned n = Lexer::MeasureTokenLength( endLoc, SM, compiler.getLangOpts()); - return std::string( p1, p2 - p1 + n); -} - -SourceRange ComparisonWithConstant::ignoreMacroExpansions(SourceRange range) { - while (compiler.getSourceManager().isMacroArgExpansion(range.getBegin())) { - range.setBegin( - compiler.getSourceManager().getImmediateMacroCallerLoc( - range.getBegin())); - } - if (range.getBegin().isMacroID()) { - SourceLocation loc; - if (Lexer::isAtStartOfMacroExpansion( - range.getBegin(), compiler.getSourceManager(), - compiler.getLangOpts(), &loc)) - { - range.setBegin(loc); - } - } - while (compiler.getSourceManager().isMacroArgExpansion(range.getEnd())) { - range.setEnd( - compiler.getSourceManager().getImmediateMacroCallerLoc( - range.getEnd())); - } - if (range.getEnd().isMacroID()) { - SourceLocation loc; - if (Lexer::isAtEndOfMacroExpansion( - range.getEnd(), compiler.getSourceManager(), - compiler.getLangOpts(), &loc)) - { - range.setEnd(loc); - } - } - return range.getBegin().isMacroID() || range.getEnd().isMacroID() - ? SourceRange() : range; -} - -loplugin::Plugin::Registration< ComparisonWithConstant > X("comparisonwithconstant", false); - -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/constantfunction.cxx b/compilerplugins/clang/store/constantfunction.cxx deleted file mode 100644 index 85ed14bd8466..000000000000 --- a/compilerplugins/clang/store/constantfunction.cxx +++ /dev/null @@ -1,506 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include "plugin.hxx" -#include <iostream> - -/* - Look for member functions that merely return a compile-time constant, or they are empty, and can thus - be either removed, or converted into a constant. - - This mostly tends to happen as a side-effect of other cleanups. -*/ -namespace { - -class ConstantFunction: - public loplugin::FilteringPlugin<ConstantFunction> -{ - StringRef getFilename(const FunctionDecl* functionDecl); -public: - explicit ConstantFunction(InstantiationData const & data): FilteringRewritePlugin(data) {} - - void run() override - { - // these files crash clang-3.5 somewhere in the isEvaluatable/EvaluateAsXXX stuff -/* FileID mainFileID = compiler.getSourceManager().getMainFileID(); - if (strstr(compiler.getSourceManager().getFileEntryForID(mainFileID)->getName(), "bootstrapfixture.cxx") != 0) { - return; - } - if (strstr(compiler.getSourceManager().getFileEntryForID(mainFileID)->getName(), "gtkinst.cxx") != 0) { - return; - }*/ - - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); - } - - bool VisitFunctionDecl(const FunctionDecl *); -}; - -StringRef ConstantFunction::getFilename(const FunctionDecl* functionDecl) -{ - SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(functionDecl->getCanonicalDecl()->getNameInfo().getLoc()); - StringRef name { getFilenameOfLocation(spellingLocation) }; - return name; -} - -static bool startsWith(const std::string& rStr, const char* pSubStr) { - return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; -} - -bool ConstantFunction::VisitFunctionDecl(const FunctionDecl * pFunctionDecl) { - if (ignoreLocation(pFunctionDecl)) { - return true; - } - if (!pFunctionDecl->hasBody()) { - return true; - } - if (!pFunctionDecl->isThisDeclarationADefinition()) { - return true; - } - // stuff declared extern-C is almost always used as a some kind of callback - if (pFunctionDecl->isExternC()) { - return true; - } - if (pFunctionDecl->isConstexpr()) { - return true; - } - if (pFunctionDecl->isMain()) { - return true; - } - - StringRef aFileName = getFilename(pFunctionDecl); - - // various tests in here are empty stubs under Linux - if (aFileName.startswith(SRCDIR "/sal/qa/")) { - return true; - } - // lots of empty stuff here where it looks like someone is still going to "fill in the blanks" - if (aFileName.startswith(SRCDIR "/basegfx/test/")) { - return true; - } - // bridges has some weird stuff in it... - if (aFileName.startswith(SRCDIR "/bridges/")) { - return true; - } - // dummy implementation of DDE, since it is only active on Windows - if (aFileName == SRCDIR "/svl/unx/source/svdde/ddedummy.cxx" - || aFileName == SRCDIR "/include/svl/svdde.hxx") { - return true; - } - // fancy templates at work here - if (aFileName == SRCDIR "/vcl/source/gdi/bmpfast.cxx") { - return true; - } - // bunch of stuff used as callbacks here - if (aFileName == SRCDIR "/vcl/generic/glyphs/gcach_layout.cxx") { - return true; - } - // salplug runtime-loading mechanism at work - if (aFileName == SRCDIR "/vcl/inc/salinst.hxx") { - return true; - } - // lots of callbacks here - if (aFileName == SRCDIR "/extensions/source/plugin/unx/npnapi.cxx") { - return true; - } - // vcl/unx/gtk3 re-using vcl/unx/gtk: - if (aFileName.find("/../../gtk/") != std::string::npos) { - return true; - } - // used by code generated by python - if (aFileName == SRCDIR "/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx") { - return true; - } - // this test just test the include of some headers - if (aFileName == SRCDIR "/officecfg/qa/cppheader.cxx") { - return true; - } - // just ignore this for now, people furiously hacking in there - if (startsWith(aFileName, SRCDIR "/libreofficekit")) { - return true; - } - - - const CXXMethodDecl *pCXXMethodDecl = dyn_cast<CXXMethodDecl>(pFunctionDecl); - if (pCXXMethodDecl) { - if (pCXXMethodDecl->isVirtual()) { - return true; - } - // static with inline body will be optimised at compile-time to a constant anyway - if (pCXXMethodDecl->isStatic() && (pCXXMethodDecl->hasInlineBody() || pCXXMethodDecl->isInlineSpecified())) { - return true; - } - // this catches some stuff in templates - if (pFunctionDecl->hasAttr<OverrideAttr>()) { - return true; - } - } - // a free function with an inline body will be optimised at compile-time to a constant anyway - if (!pCXXMethodDecl && pFunctionDecl->isInlineSpecified()) { - return true; - } - if (isa<CXXConstructorDecl>(pFunctionDecl) || isa<CXXDestructorDecl>(pFunctionDecl) || isa<CXXConversionDecl>(pFunctionDecl)) { - return true; - } - if (isInUnoIncludeFile(pFunctionDecl)) { - return true; - } - - switch (pFunctionDecl->getOverloadedOperator()) { - case OO_Delete: - case OO_EqualEqual: - case OO_Call: - return true; - default: - break; - } - - std::string aFunctionName = pFunctionDecl->getQualifiedNameAsString(); - - // something to do with dynamic loading in sal/textenc/textenc.cxx - if (aFunctionName == "thisModule") { - return true; - } - // an empty stub under certain conditions, sal/osl/unx/thread.cxx - if (aFunctionName == "osl_thread_priority_init_Impl") { - return true; - } - // a pointer to this function is taken and passed to an underlying API, cppu/source/uno/lbenv.cxx - if (aFunctionName == "defenv_dispose") { - return true; - } - // a pointer to this function is taken and passed to an underlying API, cppuhelper/source/exc_thrower.cxx - if (aFunctionName == "ExceptionThrower_acquire_release_nop") { - return true; - } - // used as a callback, /vcl/source/filter/jpeg/JpegReader.cxx - if (aFunctionName == "term_source") { - return true; - } - // only valid for windows, extensions/source/update/check/updatecheck.cxx - if (aFunctionName == "(anonymous namespace)::UpdateCheckThread::hasInternetConnection") { - return true; - } - // used as callback, extensions/source/plugin/unx/npwrap.cxx - if (aFunctionName == "plugin_x_error_handler" || aFunctionName == "noClosure") { - return true; - } - // used as callback, sax/source/expatwrap/sax_expat.cxx - if (aFunctionName == "(anonymous namespace)::SaxExpatParser_Impl::callbackUnknownEncoding") { - return true; - } - // used as callback, i18npool/source/textconversion/textconversion.cxx - if (aFunctionName == "com::sun::star::i18n::nullFunc") { - return true; - } - // used as callback, xmloff/source/text/txtparae.cxx - if (aFunctionName == "(anonymous namespace)::lcl_TextContentsUnfiltered") { - return true; - } - // template magic, include/canvas/verifyinput.hxx - if (aFunctionName == "canvastools::verifyInput") { - return true; - } - // template magic, cppcanvas/source/mtfrenderer/implrenderer.cxx - if (aFunctionName == "cppcanvas::internal::(anonymous namespace)::AreaQuery::result") { - return true; - } - // callback, drawinglayer/source/dumper/XShapeDumper. - if (aFunctionName == "(anonymous namespace)::closeCallback") { - return true; - } - // callback, basic/source/runtime/runtime.cxx - if (aFunctionName == "SbiRuntime::StepNOP") { - return true; - } - // DLL stuff, only used on windows, basic/source/runtime/dllmgr.hxx - if (aFunctionName == "SbiDllMgr::FreeDll") { - return true; - } - // only used on Windows, basic/source/sbx/sbxdec.cxx - if (aFunctionName == "SbxDecimal::neg" || aFunctionName == "SbxDecimal::isZero") { - return true; - } - // used as a callback, include/sfx2/shell.hxx - if (aFunctionName == "SfxShell::EmptyExecStub" || aFunctionName == "SfxShell::EmptyStateStub" - || aFunctionName == "SfxShell::VerbState") { - return true; - } - // SFX_IMPL_POS_CHILDWINDOW_WITHID macro - if (aFunctionName.find("GetChildWindowId") != std::string::npos) { - return true; - } - // SFX_IMPL_SUPERCLASS_INTERFACE macro - if (aFunctionName.find("InitInterface_Impl") != std::string::npos) { - return true; - } - // callback, vcl/unx/generic/app/sm.cxx - if (aFunctionName == "IgnoreIceIOErrors" || aFunctionName == "IgnoreIceErrors") { - return true; - } - // callback, vcl/unx/gtk/a11y/atkcomponent.cxx - if (aFunctionName == "component_wrapper_get_mdi_zorder") { - return true; - } - // callback, vcl/unx/gtk/a11y/atkaction.cxx - if (aFunctionName == "action_wrapper_set_description") { - return true; - } - // callback, vcl/unx/gtk/a11y/atkutil.cxx - if (aFunctionName == "ooo_atk_util_get_toolkit_version" || aFunctionName == "ooo_atk_util_get_toolkit_name") { - return true; - } - // callback, vcl/unx/gtk/a11y/atktextattributes.cxx - if (aFunctionName == "InvalidValue") { - return true; - } - // callback, vcl/unx/gtk/a11y/atktable.cxx - if (aFunctionName == "table_wrapper_set_summary" || aFunctionName == "table_wrapper_set_row_header" - || aFunctionName == "table_wrapper_set_row_description" - || aFunctionName == "table_wrapper_set_column_header" - || aFunctionName == "table_wrapper_set_column_description" - || aFunctionName == "table_wrapper_set_caption") { - return true; - } - // callbacks, vcl/unx/gtk/window/gtksalframe.cxx - if (startsWith(aFunctionName, "GtkSalFrame::IMHandler::signal")) { - return true; - } - // callbacks, vcl/unx/gtk/window/glomenu.cxx - if (startsWith(aFunctionName, "g_lo_menu_is_mutable")) { - return true; - } - // only contains code for certain versions of GTK, /vcl/unx/gtk/window/gtksalframe.cx - if (aFunctionName == "GtkSalFrame::AllocateFrame") { - return true; - } - // only valid for Windows, embeddedobj/source/msole/olemisc.cxx - if (aFunctionName == "OleEmbeddedObject::GetRidOfComponent") { - return true; - } - // callback, svx/source/accessibility/ShapeTypeHandler.cxx - if (aFunctionName == "accessibility::CreateEmptyShapeReference") { - return true; - } - // chart2/source/view/main/AbstractShapeFactory.cxx - if (aFunctionName == "chart::(anonymous namespace)::thisModule") { - return true; - } - // chart2/source/tools/InternalData.cxx - if (aFunctionName == "chart::InternalData::dump") { - return true; - } - // hwpfilter/ - if (aFunctionName == "debug" || aFunctionName == "token_debug") { - return true; - } - // callback, sdext/source/presenter/PresenterFrameworkObserver.cxx - if (aFunctionName == "sdext::presenter::PresenterFrameworkObserver::True") { - return true; - } - // callback, sw/source/core/doc/tblrwcl.cxx - if (aFunctionName == "lcl_DelOtherBox") { - return true; - } - // callback, sw/source/filter/ww8/ww8par.cxx - if (aFunctionName == "SwWW8ImplReader::Read_Majority") { - return true; - } - // callback, sw/source/filter/ww8/ww8par5.cxx - if (aFunctionName == "SwWW8ImplReader::Read_F_Shape") { - return true; - } - // called from SDI file, I don't know what that stuff is about, sd/source/ui/slidesorter/shell/SlideSorterViewShell.cx - if (aFunctionName == "sd::slidesorter::SlideSorterViewShell::ExecStatusBar" - || aFunctionName == "sd::OutlineViewShell::ExecStatusBar") { - return true; - } - // only used in debug mode, sd/source/filter/ppt/pptinanimations.cxx - if (startsWith(aFunctionName, "ppt::AnimationImporter::dump")) { - return true; - } - // only used in ENABLE_SDREMOTE_BLUETOOTH mode, sd/source/ui/dlg/tpoption.cx - if (aFunctionName == "SdTpOptionsMisc::SetImpressMode") { - return true; - } - // template magic, sc/source/ui/docshell/datastream.cxx - if (startsWith(aFunctionName, "sc::(anonymous namespace)::CSVHandler::")) { - return true; - } - // called from SDI file, I don't know what that stuff is about, sc/source/ui/view/cellsh4.cxx - if (aFunctionName == "ScCellShell::GetStateCursor") { - return true; - } - // template magic, sc/source/filter/excel/xepivot.cxx - if (aFunctionName == "XclExpPivotCache::SaveXml") { - return true; - } - // template magic, sc/source/filter/html/htmlpars.cxx - if (startsWith(aFunctionName, "(anonymous namespace)::CSSHandler::")) { - return true; - } - // callbacks, sc/source/filter/oox/formulaparser.cxx - if (startsWith(aFunctionName, "oox::xls::BiffFormulaParserImpl::import")) { - return true; - } - // template magic, sc/qa/unit/helper/csv_handler.hxx - if (startsWith(aFunctionName, "csv_handler::") || startsWith(aFunctionName, "conditional_format_handler::")) { - return true; - } - // template magic, slideshow/source/inc/listenercontainer.hxx - if (startsWith(aFunctionName, "slideshow::internal::EmptyBase::EmptyClearableGuard::")) { - return true; - } - // callback, scripting/source/vbaevents/eventhelper.cxx - if (aFunctionName == "ApproveAll") { - return true; - } - // only on WNT, basic/qa/cppunit/test_vba.cx - if (aFunctionName == "(anonymous namespace)::VBATest::testMiscOLEStuff") { - return true; - } - // GtkSalFrame::TriggerPaintEvent() is only compiled under certain versions of GTK - if (aFunctionName == "GtkSalFrame::TriggerPaintEvent") { - return true; - } - if (aFunctionName == "SwVectorModifyBase::dumpAsXml") { - return true; - } - // vcl/unx/gtk3 re-using vcl/unx/gtk: - if (aFunctionName == "DeInitAtkBridge" - || aFunctionName == "GtkData::initNWF" - || aFunctionName == "GtkSalFrame::EnsureAppMenuWatch" - || aFunctionName == "InitAtkBridge") - { - return true; - } - if (aFunctionName == "sc::AlignedAllocator::operator!=") { - return true; - } - if (aFunctionName == "clipboard_owner_init") { - return true; - } - // returns sizeof(struct) vcl/source/gdi/dibtools.cxx - if (aFunctionName == "getDIBV5HeaderSize") { - return true; - } - // windows only - if (aFunctionName == "InitAccessBridge") { - return true; - } - // callbacks - if (aFunctionName == "disabled_initSystray" || aFunctionName == "disabled_deInitSystray") { - return true; - } - // behind a BREAKPAD option - if (aFunctionName == "desktop::(anonymous namespace)::crashReportInfoExists") { - return true; - } - // LOK stuff - if (aFunctionName == "doc_getTileMode") { - return true; - } - // apparently this will be useful at sometime in the future - if (aFunctionName == "LocaleDataWrapper::getCurrZeroChar") { - return true; - } - // marked with TODO - if (aFunctionName == "oglcanvas::TextLayout::draw") { - return true; - } - // called from the .sdi files - if (aFunctionName == "SfxObjectShell::StateView_Impl") { - return true; - } - // gtk callback - if (aFunctionName == "GtkSalFrame::signalVisibility") { - return true; - } - // platform-version-dependent code - if (aFunctionName == "(anonymous namespace)::ACTIVE_TAB") { - return true; - } - // SMIL callbacks - if (aFunctionName == "boost::sp_scalar_constructor_hook" || aFunctionName == "boost::sp_scalar_destructor_hook") { - return true; - } - - - - - std::string aImmediateMacro = ""; - if (compiler.getSourceManager().isMacroBodyExpansion(pFunctionDecl->getLocStart()) ) { - StringRef name { Lexer::getImmediateMacroName( - pFunctionDecl->getLocStart(), compiler.getSourceManager(), compiler.getLangOpts()) }; - aImmediateMacro = name; - if (name.startswith("IMPL_LINK_") ) - { - return true; - } - } - - const CompoundStmt *pCompoundStmt = dyn_cast<CompoundStmt>(pFunctionDecl->getBody()); - bool bEmptyBody = false; - if (pCompoundStmt) { - if (pCompoundStmt->size() > 1) { - return true; - } - if (pCompoundStmt->size() > 0) { - const ReturnStmt *pReturnStmt = dyn_cast<ReturnStmt>(*pCompoundStmt->body_begin()); - if (!pReturnStmt) { - return true; - } - if (const UnaryOperator* unaryOp = dyn_cast<UnaryOperator>(pReturnStmt->getRetValue())) { - if (unaryOp->getOpcode() == UO_AddrOf) { - return true; - } - } - if (pReturnStmt->getRetValue() != nullptr) { - // && !pReturnStmt->getRetValue()->isEvaluatable(compiler.getASTContext())) { - bool aBoolResult; - llvm::APSInt aIntResult; - if (pReturnStmt->getRetValue()->isTypeDependent() - || (!pReturnStmt->getRetValue()->EvaluateAsBooleanCondition(aBoolResult, compiler.getASTContext()) - && !pReturnStmt->getRetValue()->EvaluateAsInt(aIntResult, compiler.getASTContext()))) - { - return true; - } - } - } else { - bEmptyBody = true; - } - } - - std::string aMessage = "this "; - aMessage += pCXXMethodDecl ? "method" : "function"; - if (bEmptyBody) { - aMessage += " is empty and should be removed, " + aFunctionName; - } else { - aMessage += " returns a constant value and should be converted to a constant " - "or to static inline, " + aFunctionName + ", " + aImmediateMacro; - } - report( - DiagnosticsEngine::Warning, - aMessage, - pFunctionDecl->getLocStart()) - << pFunctionDecl->getSourceRange(); - if (pFunctionDecl != pFunctionDecl->getCanonicalDecl()) - report( - DiagnosticsEngine::Note, - aMessage, - pFunctionDecl->getCanonicalDecl()->getLocStart()) - << pFunctionDecl->getCanonicalDecl()->getSourceRange(); - return true; -} - -loplugin::Plugin::Registration<ConstantFunction> X("constantfunction"); - -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/constfields.cxx b/compilerplugins/clang/store/constfields.cxx deleted file mode 100644 index 692c84daeb8c..000000000000 --- a/compilerplugins/clang/store/constfields.cxx +++ /dev/null @@ -1,596 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#if !defined _WIN32 //TODO, #include <sys/file.h> - -#include <cassert> -#include <string> -#include <iostream> -#include <fstream> -#include <unordered_set> -#include <vector> -#include <algorithm> -#include <sys/file.h> -#include <unistd.h> - -#include "config_clang.h" - -#include "plugin.hxx" -#include "check.hxx" - -#include "clang/AST/ParentMapContext.h" - -/** -Look for fields that are only assigned to in the constructor using field-init, and can therefore be const. - -The process goes something like this: - $ make check - $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='constfields' check - $ ./compilerplugins/clang/constfields.py - -and then - $ for dir in *; do make $dir FORCE_COMPILE=all UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='constfieldsrewrite' $dir; done -to auto-remove the method declarations - -*/ - -namespace -{ -struct MyFieldInfo -{ - const RecordDecl* parentRecord; - std::string parentClass; - std::string fieldName; - std::string fieldType; - std::string sourceLocation; - std::string access; -}; -bool operator<(const MyFieldInfo& lhs, const MyFieldInfo& rhs) -{ - return std::tie(lhs.parentClass, lhs.fieldName) < std::tie(rhs.parentClass, rhs.fieldName); -} - -// try to limit the voluminous output a little -static std::set<MyFieldInfo> cannotBeConstSet; -static std::set<MyFieldInfo> definitionSet; - -/** - * Wrap the different kinds of callable and callee objects in the clang AST so I can define methods that handle everything. - */ -class CallerWrapper -{ - const CallExpr* m_callExpr; - const CXXConstructExpr* m_cxxConstructExpr; - -public: - CallerWrapper(const CallExpr* callExpr) - : m_callExpr(callExpr) - , m_cxxConstructExpr(nullptr) - { - } - CallerWrapper(const CXXConstructExpr* cxxConstructExpr) - : m_callExpr(nullptr) - , m_cxxConstructExpr(cxxConstructExpr) - { - } - unsigned getNumArgs() const - { - return m_callExpr ? m_callExpr->getNumArgs() : m_cxxConstructExpr->getNumArgs(); - } - const Expr* getArg(unsigned i) const - { - return m_callExpr ? m_callExpr->getArg(i) : m_cxxConstructExpr->getArg(i); - } -}; -class CalleeWrapper -{ - const FunctionDecl* m_calleeFunctionDecl = nullptr; - const CXXConstructorDecl* m_cxxConstructorDecl = nullptr; - const FunctionProtoType* m_functionPrototype = nullptr; - -public: - explicit CalleeWrapper(const FunctionDecl* calleeFunctionDecl) - : m_calleeFunctionDecl(calleeFunctionDecl) - { - } - explicit CalleeWrapper(const CXXConstructExpr* cxxConstructExpr) - : m_cxxConstructorDecl(cxxConstructExpr->getConstructor()) - { - } - explicit CalleeWrapper(const FunctionProtoType* functionPrototype) - : m_functionPrototype(functionPrototype) - { - } - unsigned getNumParams() const - { - if (m_calleeFunctionDecl) - return m_calleeFunctionDecl->getNumParams(); - else if (m_cxxConstructorDecl) - return m_cxxConstructorDecl->getNumParams(); - else if (m_functionPrototype->param_type_begin() == m_functionPrototype->param_type_end()) - // FunctionProtoType will assert if we call getParamTypes() and it has no params - return 0; - else - return m_functionPrototype->getParamTypes().size(); - } - const QualType getParamType(unsigned i) const - { - if (m_calleeFunctionDecl) - return m_calleeFunctionDecl->getParamDecl(i)->getType(); - else if (m_cxxConstructorDecl) - return m_cxxConstructorDecl->getParamDecl(i)->getType(); - else - return m_functionPrototype->getParamTypes()[i]; - } - std::string getNameAsString() const - { - if (m_calleeFunctionDecl) - return m_calleeFunctionDecl->getNameAsString(); - else if (m_cxxConstructorDecl) - return m_cxxConstructorDecl->getNameAsString(); - else - return ""; - } - CXXMethodDecl const* getAsCXXMethodDecl() const - { - if (m_calleeFunctionDecl) - return dyn_cast<CXXMethodDecl>(m_calleeFunctionDecl); - return nullptr; - } -}; - -class ConstFields : public RecursiveASTVisitor<ConstFields>, public loplugin::Plugin -{ -public: - explicit ConstFields(loplugin::InstantiationData const& data) - : Plugin(data) - { - } - - virtual void run() override; - - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - - bool VisitFieldDecl(const FieldDecl*); - bool VisitMemberExpr(const MemberExpr*); - bool TraverseCXXConstructorDecl(CXXConstructorDecl*); - bool TraverseCXXMethodDecl(CXXMethodDecl*); - bool TraverseFunctionDecl(FunctionDecl*); - bool TraverseIfStmt(IfStmt*); - -private: - MyFieldInfo niceName(const FieldDecl*); - void check(const FieldDecl* fieldDecl, const Expr* memberExpr); - bool isSomeKindOfZero(const Expr* arg); - bool IsPassedByNonConst(const FieldDecl* fieldDecl, const Stmt* child, CallerWrapper callExpr, - CalleeWrapper calleeFunctionDecl); - llvm::Optional<CalleeWrapper> getCallee(CallExpr const*); - - RecordDecl* insideMoveOrCopyDeclParent = nullptr; - // For reasons I do not understand, parentFunctionDecl() is not reliable, so - // we store the parent function on the way down the AST. - FunctionDecl* insideFunctionDecl = nullptr; - std::vector<FieldDecl const*> insideConditionalCheckOfMemberSet; -}; - -void ConstFields::run() -{ - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); - - if (!isUnitTestMode()) - { - // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes - // writing to the same logfile - std::string output; - for (const MyFieldInfo& s : cannotBeConstSet) - output += "write-outside-constructor: " + s.parentClass + " " + s.fieldName + " "; - for (const MyFieldInfo& s : definitionSet) - output += "definition: " + s.access + " " + s.parentClass + " " + s.fieldName + " " - + s.fieldType + " " + s.sourceLocation + " "; - std::ofstream myfile; - myfile.open(WORKDIR "/loplugin.constfields.log", std::ios::app | std::ios::out); - myfile << output; - myfile.close(); - } - else - { - for (const MyFieldInfo& s : cannotBeConstSet) - report(DiagnosticsEngine::Warning, "notconst %0", s.parentRecord->getBeginLoc()) - << s.fieldName; - } -} - -MyFieldInfo ConstFields::niceName(const FieldDecl* fieldDecl) -{ - MyFieldInfo aInfo; - - const RecordDecl* recordDecl = fieldDecl->getParent(); - - if (const CXXRecordDecl* cxxRecordDecl = dyn_cast<CXXRecordDecl>(recordDecl)) - { - if (cxxRecordDecl->getTemplateInstantiationPattern()) - cxxRecordDecl = cxxRecordDecl->getTemplateInstantiationPattern(); - aInfo.parentRecord = cxxRecordDecl; - aInfo.parentClass = cxxRecordDecl->getQualifiedNameAsString(); - } - else - { - aInfo.parentRecord = recordDecl; - aInfo.parentClass = recordDecl->getQualifiedNameAsString(); - } - - aInfo.fieldName = fieldDecl->getNameAsString(); - // sometimes the name (if it's an anonymous thing) contains the full path of the build folder, which we don't need - size_t idx = aInfo.fieldName.find(SRCDIR); - if (idx != std::string::npos) - { - aInfo.fieldName = aInfo.fieldName.replace(idx, strlen(SRCDIR), ""); - } - aInfo.fieldType = fieldDecl->getType().getAsString(); - - SourceLocation expansionLoc - = compiler.getSourceManager().getExpansionLoc(fieldDecl->getLocation()); - StringRef name = getFilenameOfLocation(expansionLoc); - aInfo.sourceLocation - = std::string(name.substr(strlen(SRCDIR) + 1)) + ":" - + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); - loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); - - switch (fieldDecl->getAccess()) - { - case AS_public: - aInfo.access = "public"; - break; - case AS_private: - aInfo.access = "private"; - break; - case AS_protected: - aInfo.access = "protected"; - break; - default: - aInfo.access = "unknown"; - break; - } - - return aInfo; -} - -bool ConstFields::VisitFieldDecl(const FieldDecl* fieldDecl) -{ - fieldDecl = fieldDecl->getCanonicalDecl(); - if (ignoreLocation(fieldDecl)) - { - return true; - } - // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) - { - return true; - } - definitionSet.insert(niceName(fieldDecl)); - return true; -} - -bool ConstFields::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxConstructorDecl) -{ - auto copy = insideMoveOrCopyDeclParent; - if (!ignoreLocation(cxxConstructorDecl) && cxxConstructorDecl->isThisDeclarationADefinition()) - { - if (cxxConstructorDecl->isCopyOrMoveConstructor()) - insideMoveOrCopyDeclParent = cxxConstructorDecl->getParent(); - } - bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(cxxConstructorDecl); - insideMoveOrCopyDeclParent = copy; - return ret; -} - -bool ConstFields::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) -{ - auto copy1 = insideMoveOrCopyDeclParent; - auto copy2 = insideFunctionDecl; - if (!ignoreLocation(cxxMethodDecl) && cxxMethodDecl->isThisDeclarationADefinition()) - { - if (cxxMethodDecl->isCopyAssignmentOperator() || cxxMethodDecl->isMoveAssignmentOperator()) - insideMoveOrCopyDeclParent = cxxMethodDecl->getParent(); - } - insideFunctionDecl = cxxMethodDecl; - bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); - insideMoveOrCopyDeclParent = copy1; - insideFunctionDecl = copy2; - return ret; -} - -bool ConstFields::TraverseFunctionDecl(FunctionDecl* functionDecl) -{ - auto copy2 = insideFunctionDecl; - insideFunctionDecl = functionDecl; - bool ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); - insideFunctionDecl = copy2; - return ret; -} - -bool ConstFields::TraverseIfStmt(IfStmt* ifStmt) -{ - FieldDecl const* memberFieldDecl = nullptr; - if (Expr const* cond = ifStmt->getCond()) - { - if (auto memberExpr = dyn_cast<MemberExpr>(cond->IgnoreParenImpCasts())) - { - if ((memberFieldDecl = dyn_cast<FieldDecl>(memberExpr->getMemberDecl()))) - insideConditionalCheckOfMemberSet.push_back(memberFieldDecl); - } - } - bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt); - if (memberFieldDecl) - insideConditionalCheckOfMemberSet.pop_back(); - return ret; -} - -bool ConstFields::VisitMemberExpr(const MemberExpr* memberExpr) -{ - const ValueDecl* decl = memberExpr->getMemberDecl(); - const FieldDecl* fieldDecl = dyn_cast<FieldDecl>(decl); - if (!fieldDecl) - { - return true; - } - fieldDecl = fieldDecl->getCanonicalDecl(); - if (ignoreLocation(fieldDecl)) - { - return true; - } - // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) - { - return true; - } - - check(fieldDecl, memberExpr); - - return true; -} - -void ConstFields::check(const FieldDecl* fieldDecl, const Expr* memberExpr) -{ - auto parentsRange = compiler.getASTContext().getParents(*memberExpr); - const Stmt* child = memberExpr; - const Stmt* parent - = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get<Stmt>(); - // walk up the tree until we find something interesting - bool bCannotBeConst = false; - bool bDump = false; - auto walkUp = [&]() { - child = parent; - auto parentsRange = compiler.getASTContext().getParents(*parent); - parent = parentsRange.begin() == parentsRange.end() ? nullptr - : parentsRange.begin()->get<Stmt>(); - }; - do - { - if (!parent) - { - // check if we have an expression like - // int& r = m_field; - auto parentsRange = compiler.getASTContext().getParents(*child); - if (parentsRange.begin() != parentsRange.end()) - { - auto varDecl = dyn_cast_or_null<VarDecl>(parentsRange.begin()->get<Decl>()); - // The isImplicit() call is to avoid triggering when we see the vardecl which is part of a for-range statement, - // which is of type 'T&&' and also an l-value-ref ? - if (varDecl && !varDecl->isImplicit() - && loplugin::TypeCheck(varDecl->getType()).LvalueReference().NonConst()) - { - bCannotBeConst = true; - } - } - break; - } - if (isa<CXXReinterpretCastExpr>(parent)) - { - // once we see one of these, there is not much useful we can know - bCannotBeConst = true; - break; - } - else if (isa<CastExpr>(parent) || isa<MemberExpr>(parent) || isa<ParenExpr>(parent) - || isa<ParenListExpr>(parent) || isa<ArrayInitLoopExpr>(parent) - || isa<ExprWithCleanups>(parent)) - { - walkUp(); - } - else if (auto unaryOperator = dyn_cast<UnaryOperator>(parent)) - { - UnaryOperator::Opcode op = unaryOperator->getOpcode(); - if (op == UO_AddrOf || op == UO_PostInc || op == UO_PostDec || op == UO_PreInc - || op == UO_PreDec) - { - bCannotBeConst = true; - } - walkUp(); - } - else if (auto operatorCallExpr = dyn_cast<CXXOperatorCallExpr>(parent)) - { - auto callee = getCallee(operatorCallExpr); - if (callee) - { - // if calling a non-const operator on the field - auto calleeMethodDecl = callee->getAsCXXMethodDecl(); - if (calleeMethodDecl && operatorCallExpr->getArg(0) == child - && !calleeMethodDecl->isConst()) - { - bCannotBeConst = true; - } - else if (IsPassedByNonConst(fieldDecl, child, operatorCallExpr, *callee)) - { - bCannotBeConst = true; - } - } - else - bCannotBeConst = true; // conservative, could improve - walkUp(); - } - else if (auto cxxMemberCallExpr = dyn_cast<CXXMemberCallExpr>(parent)) - { - const CXXMethodDecl* calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); - if (calleeMethodDecl) - { - // if calling a non-const method on the field - const Expr* tmp = dyn_cast<Expr>(child); - if (tmp->isBoundMemberFunction(compiler.getASTContext())) - { - tmp = dyn_cast<MemberExpr>(tmp)->getBase(); - } - if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp - && !calleeMethodDecl->isConst()) - { - bCannotBeConst = true; - break; - } - if (IsPassedByNonConst(fieldDecl, child, cxxMemberCallExpr, - CalleeWrapper(calleeMethodDecl))) - bCannotBeConst = true; - } - else - bCannotBeConst = true; // can happen in templates - walkUp(); - } - else if (auto cxxConstructExpr = dyn_cast<CXXConstructExpr>(parent)) - { - if (IsPassedByNonConst(fieldDecl, child, cxxConstructExpr, - CalleeWrapper(cxxConstructExpr))) - bCannotBeConst = true; - walkUp(); - } - else if (auto callExpr = dyn_cast<CallExpr>(parent)) - { - auto callee = getCallee(callExpr); - if (callee) - { - if (IsPassedByNonConst(fieldDecl, child, callExpr, *callee)) - bCannotBeConst = true; - } - else - bCannotBeConst = true; // conservative, could improve - walkUp(); - } - else if (auto binaryOp = dyn_cast<BinaryOperator>(parent)) - { - BinaryOperator::Opcode op = binaryOp->getOpcode(); - const bool assignmentOp = op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign - || op == BO_RemAssign || op == BO_AddAssign - || op == BO_SubAssign || op == BO_ShlAssign - || op == BO_ShrAssign || op == BO_AndAssign - || op == BO_XorAssign || op == BO_OrAssign; - if (assignmentOp) - { - if (binaryOp->getLHS() == child) - bCannotBeConst = true; - else if (loplugin::TypeCheck(binaryOp->getLHS()->getType()) - .LvalueReference() - .NonConst()) - // if the LHS is a non-const reference, we could write to the field later on - bCannotBeConst = true; - } - walkUp(); - } - else if (isa<ReturnStmt>(parent)) - { - if (insideFunctionDecl) - { - auto tc = loplugin::TypeCheck(insideFunctionDecl->getReturnType()); - if (tc.LvalueReference().NonConst()) - bCannotBeConst = true; - } - break; - } - else if (isa<SwitchStmt>(parent) || isa<WhileStmt>(parent) || isa<ForStmt>(parent) - || isa<IfStmt>(parent) || isa<DoStmt>(parent) || isa<CXXForRangeStmt>(parent) - || isa<DefaultStmt>(parent)) - { - break; - } - else - { - walkUp(); - } - } while (true); - - if (bDump) - { - report(DiagnosticsEngine::Warning, "oh dear, what can the matter be? writtenTo=%0", - memberExpr->getBeginLoc()) - << bCannotBeConst << memberExpr->getSourceRange(); - if (parent) - { - report(DiagnosticsEngine::Note, "parent over here", parent->getBeginLoc()) - << parent->getSourceRange(); - parent->dump(); - } - memberExpr->dump(); - fieldDecl->getType()->dump(); - } - - if (bCannotBeConst) - { - cannotBeConstSet.insert(niceName(fieldDecl)); - } -} - -bool ConstFields::IsPassedByNonConst(const FieldDecl* fieldDecl, const Stmt* child, - CallerWrapper callExpr, CalleeWrapper calleeFunctionDecl) -{ - unsigned len = std::min(callExpr.getNumArgs(), calleeFunctionDecl.getNumParams()); - // if it's an array, passing it by value to a method typically means the - // callee takes a pointer and can modify the array - if (fieldDecl->getType()->isConstantArrayType()) - { - for (unsigned i = 0; i < len; ++i) - if (callExpr.getArg(i) == child) - if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)).Pointer().NonConst()) - return true; - } - else - { - for (unsigned i = 0; i < len; ++i) - if (callExpr.getArg(i) == child) - if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)) - .LvalueReference() - .NonConst()) - return true; - } - return false; -} - -llvm::Optional<CalleeWrapper> ConstFields::getCallee(CallExpr const* callExpr) -{ - FunctionDecl const* functionDecl = callExpr->getDirectCallee(); - if (functionDecl) - return CalleeWrapper(functionDecl); - - // Extract the functionprototype from a type - clang::Type const* calleeType = callExpr->getCallee()->getType().getTypePtr(); - if (auto pointerType = calleeType->getUnqualifiedDesugaredType()->getAs<clang::PointerType>()) - { - if (auto prototype = pointerType->getPointeeType() - ->getUnqualifiedDesugaredType() - ->getAs<FunctionProtoType>()) - { - return CalleeWrapper(prototype); - } - } - - return llvm::Optional<CalleeWrapper>(); -} - -loplugin::Plugin::Registration<ConstFields> X("constfields", false); -} - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/constfields.py b/compilerplugins/clang/store/constfields.py deleted file mode 100755 index ef3154d7b348..000000000000 --- a/compilerplugins/clang/store/constfields.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/python - -import re -import io - -definitionSet = set() -definitionToSourceLocationMap = dict() -definitionToTypeMap = dict() -writeFromOutsideConstructorSet = set() - -# clang does not always use exactly the same numbers in the type-parameter vars it generates -# so I need to substitute them to ensure we can match correctly. -normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") -def normalizeTypeParams( line ): - return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) - -def parseFieldInfo( tokens ): - if len(tokens) == 3: - return (normalizeTypeParams(tokens[1]), tokens[2]) - else: - return (normalizeTypeParams(tokens[1]), "") - -with io.open("workdir/loplugin.constfields.log", "rb", buffering=1024*1024) as txt: - for line in txt: - tokens = line.strip().split(" ") - if tokens[0] == "definition:": - access = tokens[1] - fieldInfo = (normalizeTypeParams(tokens[2]), tokens[3]) - srcLoc = tokens[5] - # ignore external source code - if (srcLoc.startswith("external/")): - continue - # ignore build folder - if (srcLoc.startswith("workdir/")): - continue - definitionSet.add(fieldInfo) - definitionToTypeMap[fieldInfo] = tokens[4] - definitionToSourceLocationMap[fieldInfo] = tokens[5] - elif tokens[0] == "write-outside-constructor:": - writeFromOutsideConstructorSet.add(parseFieldInfo(tokens)) - else: - print( "unknown line: " + line) - -# Calculate can-be-const-field set -canBeConstFieldSet = set() -for d in definitionSet: - if d in writeFromOutsideConstructorSet: - continue - srcLoc = definitionToSourceLocationMap[d] - fieldType = definitionToTypeMap[d] - if fieldType.startswith("const "): - continue - if "std::unique_ptr" in fieldType: - continue - if "std::shared_ptr" in fieldType: - continue - if "Reference<" in fieldType: - continue - if "VclPtr<" in fieldType: - continue - if "osl::Mutex" in fieldType: - continue - if "::sfx2::sidebar::ControllerItem" in fieldType: - continue - canBeConstFieldSet.add((d[0] + " " + d[1] + " " + fieldType, srcLoc)) - - -# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely -def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): - return [int(text) if text.isdigit() else text.lower() - for text in re.split(_nsre, s)] -# sort by both the source-line and the datatype, so the output file ordering is stable -# when we have multiple items on the same source line -def v_sort_key(v): - return natural_sort_key(v[1]) + [v[0]] - -# sort results by name and line number -tmp6list = sorted(canBeConstFieldSet, key=lambda v: v_sort_key(v)) - -# print out the results -with open("compilerplugins/clang/constfields.results", "wt") as f: - for t in tmp6list: - f.write( t[1] + " " ) - f.write( " " + t[0] + " " ) - - diff --git a/compilerplugins/clang/store/constfieldsrewrite.cxx b/compilerplugins/clang/store/constfieldsrewrite.cxx deleted file mode 100644 index d72bb43aad7a..000000000000 --- a/compilerplugins/clang/store/constfieldsrewrite.cxx +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#if !defined _WIN32 //TODO, #include <sys/mman.h> - -#include <cassert> -#include <string> -#include <iostream> -#include "plugin.hxx" -#include "check.hxx" -#include "config_clang.h" -#include <sys/mman.h> -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/stat.h> -#include <assert.h> -#include <cstring> - -/** -e ... etc. - the rest is truncated
