diff options
Diffstat (limited to 'compilerplugins/clang')
35 files changed, 1813 insertions, 80 deletions
diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index 4eebb46d96f3..16e304981669 100644 --- a/compilerplugins/clang/badstatics.cxx +++ b/compilerplugins/clang/badstatics.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> #include "check.hxx" @@ -22,8 +24,12 @@ public: explicit BadStatics(loplugin::InstantiationData const& rData): FilteringPlugin(rData) {} + bool preRun() override { + return compiler.getLangOpts().CPlusPlus; // no non-trivial dtors in C + } + void run() override { - if (compiler.getLangOpts().CPlusPlus) { // no non-trivial dtors in C + if (preRun()) { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } } @@ -244,8 +250,10 @@ public: }; -loplugin::Plugin::Registration<BadStatics> X("badstatics"); +loplugin::Plugin::Registration<BadStatics> badstatics("badstatics"); } // namespace +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/blockblock.cxx b/compilerplugins/clang/blockblock.cxx index 9358845abc47..8405609af3df 100644 --- a/compilerplugins/clang/blockblock.cxx +++ b/compilerplugins/clang/blockblock.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> #include <string> #include <iostream> @@ -26,13 +28,18 @@ public: explicit BlockBlock(loplugin::InstantiationData const & data): FilteringPlugin(data) {} - virtual void run() override + virtual bool preRun() override { StringRef fn(handler.getMainFileName()); if (loplugin::isSamePathname(fn, SRCDIR "/sal/osl/unx/file_misc.cxx")) - return; + return false; + return true; + } - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } } bool VisitCompoundStmt(CompoundStmt const * ); @@ -67,8 +74,10 @@ bool BlockBlock::VisitCompoundStmt(CompoundStmt const * compound) return true; } -loplugin::Plugin::Registration< BlockBlock > X("blockblock", true); +loplugin::Plugin::Registration< BlockBlock > blockblock("blockblock", true); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/charrightshift.cxx b/compilerplugins/clang/charrightshift.cxx index aa4c85d3f22d..6f3027002daa 100644 --- a/compilerplugins/clang/charrightshift.cxx +++ b/compilerplugins/clang/charrightshift.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "check.hxx" #include "plugin.hxx" @@ -51,8 +53,10 @@ public: } }; -loplugin::Plugin::Registration<CharRightShift> X("charrightshift"); +loplugin::Plugin::Registration<CharRightShift> charrightshift("charrightshift"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/check.hxx b/compilerplugins/clang/check.hxx index 0d636636a81a..fd4d46fd0b97 100644 --- a/compilerplugins/clang/check.hxx +++ b/compilerplugins/clang/check.hxx @@ -115,6 +115,8 @@ public: inline ContextCheck Struct(llvm::StringRef id) const; + explicit ContextCheck(const clang::NamespaceDecl * decl ) : context_( decl ) {} + private: friend DeclCheck; friend TypeCheck; diff --git a/compilerplugins/clang/datamembershadow.cxx b/compilerplugins/clang/datamembershadow.cxx index 6c7f866761a8..d325650becea 100644 --- a/compilerplugins/clang/datamembershadow.cxx +++ b/compilerplugins/clang/datamembershadow.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <string> #include <iostream> #include <map> @@ -114,8 +116,10 @@ bool DataMemberShadow::VisitFieldDecl(FieldDecl const * fieldDecl) return true; } -loplugin::Plugin::Registration< DataMemberShadow > X("datamembershadow", true); +loplugin::Plugin::Registration< DataMemberShadow > datamembershadow("datamembershadow", true); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/dbgunhandledexception.cxx b/compilerplugins/clang/dbgunhandledexception.cxx index e701b38849f2..81d6126fb3af 100644 --- a/compilerplugins/clang/dbgunhandledexception.cxx +++ b/compilerplugins/clang/dbgunhandledexception.cxx @@ -9,6 +9,8 @@ * */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "check.hxx" #include "plugin.hxx" #include <clang/Lex/Lexer.h> @@ -31,9 +33,11 @@ public: virtual void run() override; bool VisitCallExpr(CallExpr const* call); bool TraverseCXXCatchStmt(CXXCatchStmt*); + bool PreTraverseCXXCatchStmt(CXXCatchStmt*); + bool PostTraverseCXXCatchStmt(CXXCatchStmt*, bool traverseOk); private: - CXXCatchStmt const* currCatchStmt = nullptr; + std::stack<CXXCatchStmt const*> currCatchStmt; }; DbgUnhandledException::DbgUnhandledException(const InstantiationData& data) @@ -46,13 +50,27 @@ void DbgUnhandledException::run() TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } +bool DbgUnhandledException::PreTraverseCXXCatchStmt(CXXCatchStmt* catchStmt) +{ + currCatchStmt.push(catchStmt); + return true; +} + +bool DbgUnhandledException::PostTraverseCXXCatchStmt(CXXCatchStmt* catchStmt, bool) +{ + assert(currCatchStmt.top() == catchStmt); + currCatchStmt.pop(); + return true; +} + bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt* catchStmt) { - auto prevCatchStmt = currCatchStmt; - currCatchStmt = catchStmt; - auto rv = RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt); - currCatchStmt = prevCatchStmt; - return rv; + if (!PreTraverseCXXCatchStmt(catchStmt)) + return false; + bool ret = RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt); + if (!PostTraverseCXXCatchStmt(catchStmt, ret)) + return false; + return ret; } bool DbgUnhandledException::VisitCallExpr(const CallExpr* call) @@ -66,13 +84,13 @@ bool DbgUnhandledException::VisitCallExpr(const CallExpr* call) if (!func->getIdentifier() || func->getName() != "DbgUnhandledException") return true; - if (!currCatchStmt) + if (currCatchStmt.empty()) { report(DiagnosticsEngine::Warning, "DBG_UNHANDLED_EXCEPTION outside catch block", compat::getBeginLoc(call)); return true; } - auto catchBlock = dyn_cast<CompoundStmt>(currCatchStmt->getHandlerBlock()); + auto catchBlock = dyn_cast<CompoundStmt>(currCatchStmt.top()->getHandlerBlock()); if (!catchBlock) { report(DiagnosticsEngine::Warning, @@ -100,8 +118,10 @@ bool DbgUnhandledException::VisitCallExpr(const CallExpr* call) return true; } -static Plugin::Registration<DbgUnhandledException> X("dbgunhandledexception"); +static Plugin::Registration<DbgUnhandledException> dbgunhandledexception("dbgunhandledexception"); } // namespace +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/derefnullptr.cxx b/compilerplugins/clang/derefnullptr.cxx index cc5ffe431a2f..61ffbfab24df 100644 --- a/compilerplugins/clang/derefnullptr.cxx +++ b/compilerplugins/clang/derefnullptr.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "plugin.hxx" namespace { @@ -38,8 +40,10 @@ bool DerefNullPtr::VisitUnaryDeref(UnaryOperator const * op) { return true; } -loplugin::Plugin::Registration<DerefNullPtr> X("derefnullptr"); +loplugin::Plugin::Registration<DerefNullPtr> derefnullptr("derefnullptr"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/doubleconvert.cxx b/compilerplugins/clang/doubleconvert.cxx index ea93084511cf..95565301b751 100644 --- a/compilerplugins/clang/doubleconvert.cxx +++ b/compilerplugins/clang/doubleconvert.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "check.hxx" #include "compat.hxx" #include "plugin.hxx" @@ -78,7 +80,9 @@ bool DoubleConvert::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr const return true; } -static loplugin::Plugin::Registration<DoubleConvert> reg("doubleconvert"); +static loplugin::Plugin::Registration<DoubleConvert> doubleconvert("doubleconvert"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/dyncastvisibility.cxx b/compilerplugins/clang/dyncastvisibility.cxx index 8b29f0735ca9..0f6021101e2b 100644 --- a/compilerplugins/clang/dyncastvisibility.cxx +++ b/compilerplugins/clang/dyncastvisibility.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <algorithm> #include <cassert> #include <cstddef> @@ -184,17 +186,22 @@ public: return true; } + virtual bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + } private: void run() override { - if (compiler.getLangOpts().CPlusPlus) { + if (preRun()) { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } } }; -static loplugin::Plugin::Registration<DynCastVisibility> reg( +static loplugin::Plugin::Registration<DynCastVisibility> dyncastvisibility( "dyncastvisibility"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/empty.cxx b/compilerplugins/clang/empty.cxx index 74cc7b06e176..4d48ca620087 100644 --- a/compilerplugins/clang/empty.cxx +++ b/compilerplugins/clang/empty.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> #include "check.hxx" @@ -180,7 +182,9 @@ private: } }; -loplugin::Plugin::Registration<Empty> X("empty"); +loplugin::Plugin::Registration<Empty> emptyRegistration("empty"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/emptyif.cxx b/compilerplugins/clang/emptyif.cxx index 76f9c033018e..ef7eac50d048 100644 --- a/compilerplugins/clang/emptyif.cxx +++ b/compilerplugins/clang/emptyif.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> #include <string> #include <iostream> @@ -84,7 +86,9 @@ bool EmptyIf::VisitIfStmt(IfStmt const* ifStmt) return true; } -loplugin::Plugin::Registration<EmptyIf> X("emptyif", true); +loplugin::Plugin::Registration<EmptyIf> emptyif("emptyif", true); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/externandnotdefined.cxx b/compilerplugins/clang/externandnotdefined.cxx index afd77abe7bda..72b250d3d82e 100644 --- a/compilerplugins/clang/externandnotdefined.cxx +++ b/compilerplugins/clang/externandnotdefined.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <string> #include "plugin.hxx" @@ -71,8 +73,10 @@ bool ExternAndNotDefined::VisitFunctionDecl(const FunctionDecl * functionDecl) { } -loplugin::Plugin::Registration< ExternAndNotDefined > X("externandnotdefined"); +loplugin::Plugin::Registration< ExternAndNotDefined > externandnotdefined("externandnotdefined"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/externvar.cxx b/compilerplugins/clang/externvar.cxx index 93a08092bd08..eb20d3f36b0d 100644 --- a/compilerplugins/clang/externvar.cxx +++ b/compilerplugins/clang/externvar.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "check.hxx" #include "plugin.hxx" @@ -109,8 +111,10 @@ public: } }; -loplugin::Plugin::Registration<ExternVar> X("externvar"); +loplugin::Plugin::Registration<ExternVar> externvar("externvar"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/inlinevisible.cxx b/compilerplugins/clang/inlinevisible.cxx index c32eb9b0d74c..8e232a337837 100644 --- a/compilerplugins/clang/inlinevisible.cxx +++ b/compilerplugins/clang/inlinevisible.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> #include <string> @@ -46,8 +48,10 @@ bool InlineVisible::VisitFunctionDecl(FunctionDecl const * decl) { return true; } -loplugin::Plugin::Registration<InlineVisible> X("inlinevisible"); +loplugin::Plugin::Registration<InlineVisible> inlinevisible("inlinevisible"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/loopvartoosmall.cxx b/compilerplugins/clang/loopvartoosmall.cxx index 7ebe34f22474..896266385dea 100644 --- a/compilerplugins/clang/loopvartoosmall.cxx +++ b/compilerplugins/clang/loopvartoosmall.cxx @@ -9,6 +9,8 @@ * */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <algorithm> #include <cassert> #include <list> @@ -234,8 +236,10 @@ void LoopVarTooSmall::checkExpr(Expr const * expr) { } } -loplugin::Plugin::Registration< LoopVarTooSmall > X("loopvartoosmall"); +loplugin::Plugin::Registration< LoopVarTooSmall > loopvartoosmall("loopvartoosmall"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx index 2167cc0e2a7f..1a1ca44a91ab 100644 --- a/compilerplugins/clang/plugin.cxx +++ b/compilerplugins/clang/plugin.cxx @@ -154,9 +154,10 @@ void normalizeDotDotInFilePath( std::string & s ) } } -void Plugin::registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, bool isPPCallback, bool byDefault ) +void Plugin::registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ) { - PluginHandler::registerPlugin( create, optionName, isPPCallback, byDefault ); + PluginHandler::registerPlugin( create, optionName, isPPCallback, isSharedPlugin, byDefault ); } bool Plugin::evaluate(const Expr* expr, APSInt& x) diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx index 4aab4beb4b8d..19908d8257e5 100644 --- a/compilerplugins/clang/plugin.hxx +++ b/compilerplugins/clang/plugin.hxx @@ -51,11 +51,20 @@ class Plugin public: explicit Plugin( const InstantiationData& data ); virtual ~Plugin() {} + // The main function of the plugin. + // Note that for shared plugins, its functionality must be split into preRun() and postRun(), + // see sharedvisitor/generator.cxx . virtual void run() = 0; + // Should be called from run() before TraverseDecl(). + // If returns false, run() should not do anything. + virtual bool preRun() { return true; } + virtual void postRun() {} template< typename T > class Registration; - enum { isPPCallback = false }; // Returns location right after the end of the token that starts at the given location. SourceLocation locationAfterToken( SourceLocation location ); + virtual bool setSharedPlugin( Plugin* /*plugin*/, const char* /*name*/ ) { return false; } + enum { isPPCallback = false }; + enum { isSharedPlugin = false }; protected: DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const; bool ignoreLocation( SourceLocation loc ) const @@ -92,7 +101,8 @@ protected: Expr const * argument1, Expr const * argument2); private: - static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, bool isPPCallback, bool byDefault ); + static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ); template< typename T > static Plugin* createHelper( const InstantiationData& data ); bool evaluate(const Expr* expr, APSInt& x); @@ -220,7 +230,7 @@ template< typename T > inline Plugin::Registration< T >::Registration( const char* optionName, bool byDefault ) { - registerPlugin( &T::template createHelper< T >, optionName, T::isPPCallback, byDefault ); + registerPlugin( &T::template createHelper< T >, optionName, T::isPPCallback, T::isSharedPlugin, byDefault ); } inline diff --git a/compilerplugins/clang/pluginhandler.cxx b/compilerplugins/clang/pluginhandler.cxx index 540e58dcd222..4296b981f767 100644 --- a/compilerplugins/clang/pluginhandler.cxx +++ b/compilerplugins/clang/pluginhandler.cxx @@ -46,7 +46,9 @@ struct PluginData Plugin* object; const char* optionName; bool isPPCallback; + bool isSharedPlugin; bool byDefault; + bool disabledRun; }; const int MAX_PLUGINS = 200; @@ -150,9 +152,26 @@ void PluginHandler::createPlugins( std::set< std::string > rewriters ) } for( auto r: rewriters ) report( DiagnosticsEngine::Fatal, "unknown plugin tool %0" ) << r; + // If there is a shared plugin, make it handle all plugins that it can handle. + for( int i = 0; i < pluginCount; ++i ) + { + if( plugins[ i ].isSharedPlugin && plugins[ i ].object != nullptr ) + { + Plugin* plugin = plugins[ i ].object; + for( int j = 0; j < pluginCount; ++j ) + { + if( plugins[ j ].object != nullptr + && plugin->setSharedPlugin( plugins[ j ].object, plugins[ j ].optionName )) + { + plugins[ j ].disabledRun = true; + } + } + } + } } -void PluginHandler::registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, bool isPPCallback, bool byDefault ) +void PluginHandler::registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ) { assert( !bPluginObjectsCreated ); assert( pluginCount < MAX_PLUGINS ); @@ -160,7 +179,9 @@ void PluginHandler::registerPlugin( Plugin* (*create)( const InstantiationData& plugins[ pluginCount ].object = NULL; plugins[ pluginCount ].optionName = optionName; plugins[ pluginCount ].isPPCallback = isPPCallback; + plugins[ pluginCount ].isSharedPlugin = isSharedPlugin; plugins[ pluginCount ].byDefault = byDefault; + plugins[ pluginCount ].disabledRun = false; ++pluginCount; } @@ -281,7 +302,7 @@ void PluginHandler::HandleTranslationUnit( ASTContext& context ) for( int i = 0; i < pluginCount; ++i ) { - if( plugins[ i ].object != NULL ) + if( plugins[ i ].object != NULL && !plugins[ i ].disabledRun ) { plugins[ i ].object->run(); } diff --git a/compilerplugins/clang/pluginhandler.hxx b/compilerplugins/clang/pluginhandler.hxx index d51afebccac7..10b4ae21df2b 100644 --- a/compilerplugins/clang/pluginhandler.hxx +++ b/compilerplugins/clang/pluginhandler.hxx @@ -50,7 +50,8 @@ public: PluginHandler( CompilerInstance& compiler, const std::vector< std::string >& args ); virtual ~PluginHandler(); virtual void HandleTranslationUnit( ASTContext& context ) override; - static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, bool isPPCallback, bool byDefault ); + static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ); DiagnosticBuilder report( DiagnosticsEngine::Level level, const char * plugin, StringRef message, CompilerInstance& compiler, SourceLocation loc = SourceLocation()); bool ignoreLocation(SourceLocation loc); diff --git a/compilerplugins/clang/privatebase.cxx b/compilerplugins/clang/privatebase.cxx index 5e92aaa7ea9c..6819647f88c5 100644 --- a/compilerplugins/clang/privatebase.cxx +++ b/compilerplugins/clang/privatebase.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "plugin.hxx" namespace { @@ -48,8 +50,10 @@ bool PrivateBase::VisitCXXRecordDecl(CXXRecordDecl const * decl) { return true; } -loplugin::Plugin::Registration<PrivateBase> X("privatebase"); +loplugin::Plugin::Registration<PrivateBase> privatebase("privatebase"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/reservedid.cxx b/compilerplugins/clang/reservedid.cxx index f05890cda0a5..acdc18217514 100644 --- a/compilerplugins/clang/reservedid.cxx +++ b/compilerplugins/clang/reservedid.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <algorithm> #include <cassert> #include <limits> @@ -40,6 +42,7 @@ public: {} void run() override; + void postRun() override; bool VisitNamedDecl(NamedDecl const * decl); @@ -56,8 +59,12 @@ private: void ReservedId::run() { //TODO: Rules for C? - if (TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()) - && compiler.hasPreprocessor()) + if (TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + postRun(); +} + +void ReservedId::postRun() { + if( compiler.hasPreprocessor()) { auto & prep = compiler.getPreprocessor(); for (auto const & m: prep.macros(false)) { @@ -302,8 +309,10 @@ bool ReservedId::isApi(NamedDecl const * decl) { return false; } -loplugin::Plugin::Registration<ReservedId> X("reservedid"); +loplugin::Plugin::Registration<ReservedId> reservedid("reservedid"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/sharedvisitor/generator.cxx b/compilerplugins/clang/sharedvisitor/generator.cxx new file mode 100644 index 000000000000..c714c0cc69db --- /dev/null +++ b/compilerplugins/clang/sharedvisitor/generator.cxx @@ -0,0 +1,563 @@ +/* -*- 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/. + */ + +/* +This tool generates another "plugin" which in fact only dispatches Visit* and Traverse* +calls to all other plugins registered with it. This means that there is just one +RecursiveASTVisitor pass for all those plugins instead of one per each, which +with the current number of plugins actually makes a performance difference. + +If you work on a plugin, comment out LO_CLANG_SHARED_PLUGINS in Makefile-clang.mk in order +to disable the feature (re-generating takes time). + +Requirements for plugins: +- Can use Visit* and Traverse* functions, but not WalkUp*. +- Visit* functions can generally remain unmodified. +- run() function must be split into preRun() and postRun() if there's any additional functionality + besides calling TraverseDecl(). The shared visitor will call the preRun() and postRun() functions + as necessary while calling its own run(). The run() function of the plugin must stay + (in case of a non-shared build) but should generally look like this: + if( preRun()) + if( TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + postRun(); +- Traverse* functions must be split into PreTraverse* and PostTraverse*, similarly to how run() + is handled, the Traverse* function should generally look like this: + bool ret = true; + if( PreTraverse*(decl)) + { + ret = RecursiveASTVisitor::Traverse*(decl); + PostTraverse*(decl, ret); + } + return ret; + + +TODO: +- Create macros for the standardized layout of run(), Traverse*, etc.? +- Possibly check plugin sources more thoroughly (e.g. that run() doesn't actually do more). +- Have one tool that extracts info from plugin .cxx files into some .txt file and another tool + that generates sharedvisitor.cxx based on those files? That would generally make the generation + faster when doing incremental changes. The .txt file could also contain some checksum of the .cxx + to avoid the analysing pass completely if just the timestamp has changed. +- Do not re-compile sharedvisitor.cxx if its contents have not actually changed. +- Is it possible to make the clang code analyze just the .cxx without also parsing all the headers? +- Instead of having to comment out LO_CLANG_SHARED_PLUGINS, implement --enable-compiler-plugins=debug . + +*/ + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/Tooling.h" + +#include <iostream> +#include <fstream> +#include <set> + +#include "../check.hxx" +#include "../check.cxx" + +using namespace std; + +using namespace clang; + +using namespace loplugin; + +// Info about a Visit* function in a plugin. +struct VisitFunctionInfo +{ + string name; + string argument; +}; + + +// Info about a Traverse* function in a plugin. +struct TraverseFunctionInfo +{ + string name; + string argument; + bool hasPre = false; + bool hasPost = false; +}; + +struct VisitFunctionInfoLess +{ + bool operator()( const VisitFunctionInfo& l, const VisitFunctionInfo& r ) const + { + return l.name < r.name; + } +}; + +struct TraverseFunctionInfoLess +{ + bool operator()( const TraverseFunctionInfo& l, const TraverseFunctionInfo& r ) const + { + return l.name < r.name; + } +}; + + +// Information about each LO plugin. +struct PluginInfo +{ + string className; // e.g. "BadStatics" + string variableName; // e.g. "badStatics" + string lowercaseName; + bool shouldVisitTemplateInstantiations; + bool shouldVisitImplicitCode; + set< VisitFunctionInfo, VisitFunctionInfoLess > visitFunctions; + set< TraverseFunctionInfo, TraverseFunctionInfoLess > traverseFunctions; +}; + +// We need separate visitors for shouldVisitTemplateInstantiations and shouldVisitImplicitCode, +// so split plugins into groups by what they should visit. +// It seems that trying to handle the shouldVisit* functionality with just one visitor +// is tricky. +enum PluginType +{ + PluginBasic, + PluginVisitTemplates, + PluginVisitImplicit, + PluginVisitTemplatesImplicit, +}; + +const int Plugin_Begin = PluginBasic; +const int Plugin_End = PluginVisitTemplatesImplicit + 1; +static const char* const pluginTypeNames[ Plugin_End ] + = { "Basic", "VisitTemplates", "VisitImplicit", "VisitTemplatesImplicit" }; + +static vector< PluginInfo > plugins[ Plugin_End ]; + + +void generateVisitor( PluginType type ); + +void generate() +{ + ostream& output = cout; + output << +"// This file is autogenerated. Do not modify.\n" +"// Generated by compilerplugins/clang/sharedvisitor/generator.cxx .\n" +"\n" +"#ifdef LO_CLANG_SHARED_PLUGINS\n" +"\n" +"#include <config_clang.h>\n" +"\n" +"#include <clang/AST/ASTContext.h>\n" +"#include <clang/AST/RecursiveASTVisitor.h>\n" +"\n" +"#include \"../plugin.hxx\"\n" +"\n"; + + output << "#undef LO_CLANG_SHARED_PLUGINS // to get sources of individual plugins\n"; + for( const auto& pluginGroup : plugins ) + for( const PluginInfo& plugin : pluginGroup ) + output << "#include \"../" << plugin.lowercaseName << ".cxx\"" << endl; + + output << +"\n" +"using namespace clang;\n" +"using namespace llvm;\n" +"\n" +"namespace loplugin\n" +"{\n"; + + for( int type = Plugin_Begin; type < Plugin_End; ++type ) + generateVisitor( static_cast< PluginType >( type )); + + output << +"} // namespace loplugin\n" +"\n" +"#endif // LO_CLANG_SHARED_PLUGINS\n"; +}; + +void generateVisitor( PluginType type ) +{ + if( plugins[ type ].empty()) + return; + ostream& output = cout; + output << +"\n" +"class SharedRecursiveASTVisitor" << pluginTypeNames[ type ] << "\n" +" : public FilteringPlugin< SharedRecursiveASTVisitor" << pluginTypeNames[ type ] << ">\n" +"{\n" +"public:\n" +" explicit SharedRecursiveASTVisitor" << pluginTypeNames[ type ] << "(const InstantiationData& rData)\n" +" : FilteringPlugin(rData)\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + output << " , " << plugin.variableName << "( nullptr )\n"; + output << " {}\n"; + + output << +" virtual bool preRun() override\n" +" {\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + output << " if( " << plugin.variableName << " && !" << plugin.variableName << "->preRun())\n"; + // This will disable the plugin for the rest of the run. + output << " " << plugin.variableName << " = nullptr;\n"; + } + output << +" return anyPluginActive();\n" +" }\n"; + + output << +" virtual void postRun() override\n" +" {\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + output << " if( " << plugin.variableName << " )\n"; + output << " " << plugin.variableName << "->postRun();\n"; + } + output << +" }\n"; + + output << +" virtual void run() override {\n" +" if (preRun()) {\n" +" TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());\n" +" postRun();\n" +" }\n" +" }\n" +" enum { isSharedPlugin = true };\n"; + + output << +" virtual bool setSharedPlugin( Plugin* plugin, const char* name ) override\n" +" {\n"; + bool first = true; + for( const PluginInfo& plugin : plugins[ type ] ) + { + output << " "; + if( !first ) + output << "else "; + first = false; + output << "if( strcmp( name, \"" << plugin.lowercaseName << "\" ) == 0 )\n"; + output << " " << plugin.variableName << " = static_cast< " << plugin.className << "* >( plugin );\n"; + } + output << +" else\n" +" return false;\n" +" return true;\n" +" }\n"; + + if( type == PluginVisitTemplates || type == PluginVisitTemplatesImplicit ) + output << "bool shouldVisitTemplateInstantiations() const { return true; }\n"; + if( type == PluginVisitImplicit || type == PluginVisitTemplatesImplicit ) + output << "bool shouldVisitImplicitCode() const { return true; }\n"; + + set< VisitFunctionInfo, VisitFunctionInfoLess > visitFunctions; + for( const PluginInfo& plugin : plugins[ type ] ) + for( const VisitFunctionInfo& visit : plugin.visitFunctions ) + visitFunctions.insert( visit ); + for( const VisitFunctionInfo& visit : visitFunctions ) + { + output << " bool " << visit.name << "(" << visit.argument << " arg)\n"; + output << +" {\n" +" if( ignoreLocation( arg ))\n" +" return true;\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + if( plugin.visitFunctions.find( visit ) == plugin.visitFunctions.end()) + continue; + output << " if( " << plugin.variableName << " != nullptr "; + output << ")\n"; + output << " {\n"; + output << " if( !" << plugin.variableName << "->" << visit.name << "( arg ))\n"; + // This will disable the plugin for the rest of the run (as would returning false + // from Visit* normally do in the non-shared case). + output << " " << plugin.variableName << " = nullptr;\n"; + output << " }\n"; + } + output << +" return anyPluginActive();\n" +" }\n"; + } + + set< TraverseFunctionInfo, TraverseFunctionInfoLess > traverseFunctions; + for( const PluginInfo& plugin : plugins[ type ] ) + for( const TraverseFunctionInfo& traverse : plugin.traverseFunctions ) + traverseFunctions.insert( traverse ); + for( const TraverseFunctionInfo& traverse : traverseFunctions ) + { + output << " bool " << traverse.name << "(" << traverse.argument << " arg)\n"; + output << " {\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + auto pluginTraverse = plugin.traverseFunctions.find( traverse ); + if( pluginTraverse == plugin.traverseFunctions.end()) + continue; + output << " " << plugin.className << "* save" << plugin.className << " = " << plugin.variableName << ";\n"; + if( pluginTraverse->hasPre ) + { + output << " if( " << plugin.variableName << " != nullptr "; + output << ")\n"; + output << " {\n"; + output << " if( !" << plugin.variableName << "->Pre" << traverse.name << "( arg ))\n"; + // This will disable the plugin for the time of the traverse, until restored later, + // just like directly returning from Traverse* would skip that part. + output << " " << plugin.variableName << " = nullptr;\n"; + output << " }\n"; + } + } + output << " bool ret = RecursiveASTVisitor::" << traverse.name << "( arg );\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + auto pluginTraverse = plugin.traverseFunctions.find( traverse ); + if( pluginTraverse == plugin.traverseFunctions.end()) + continue; + if( pluginTraverse->hasPost ) + { + output << " if( " << plugin.variableName << " != nullptr "; + output << ")\n"; + output << " {\n"; + output << " if( !" << plugin.variableName << "->Post" << traverse.name << "( arg, ret ))\n"; + // This will disable the plugin for the rest of the run. + output << " save" << plugin.className << " = nullptr;\n"; + output << " }\n"; + } + output << " " << plugin.variableName << " = save" << plugin.className << ";\n"; + } + output << " return ret;\n"; + output << " }\n"; + } + + output << +"private:\n"; + + output << +" bool anyPluginActive() const\n" +" {\n"; + first = true; + for( const PluginInfo& plugin : plugins[ type ] ) + { + if( first ) + output << " return " << plugin.variableName << " != nullptr"; + else + output << "\n || " << plugin.variableName << " != nullptr"; + first = false; + } + output << ";\n"; + output << " }\n"; + + for( const PluginInfo& plugin : plugins[ type ] ) + output << " " << plugin.className << "* " << plugin.variableName << ";\n"; + + output << +"};\n" +"\n" +"loplugin::Plugin::Registration< SharedRecursiveASTVisitor" << pluginTypeNames[ type ] + << " > registration" << pluginTypeNames[ type ] << "(\"sharedvisitor" << pluginTypeNames[ type ] << "\");\n" +"\n"; +} + +class CheckFileVisitor + : public RecursiveASTVisitor< CheckFileVisitor > +{ +public: + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration); + + bool TraverseNamespaceDecl(NamespaceDecl * decl) + { + // Skip non-LO namespaces the same way FilteringPlugin does. + if( !ContextCheck( decl ).Namespace( "loplugin" ).GlobalNamespace() + && !ContextCheck( decl ).AnonymousNamespace()) + { + return true; + } + return RecursiveASTVisitor<CheckFileVisitor>::TraverseNamespaceDecl(decl); + } +}; + +static bool inheritsPluginClassCheck( const Decl* decl ) +{ + return bool( DeclCheck( decl ).Class( "FilteringPlugin" ).Namespace( "loplugin" ).GlobalNamespace()) + || bool( DeclCheck( decl ).Class( "FilteringRewritePlugin" ).Namespace( "loplugin" ).GlobalNamespace()); +} + +static TraverseFunctionInfo findOrCreateTraverseFunctionInfo( PluginInfo& pluginInfo, StringRef name ) +{ + TraverseFunctionInfo info; + info.name = name; + auto foundInfo = pluginInfo.traverseFunctions.find( info ); + if( foundInfo != pluginInfo.traverseFunctions.end()) + { + info = move( *foundInfo ); + pluginInfo.traverseFunctions.erase( foundInfo ); + } + return info; +} + +bool CheckFileVisitor::VisitCXXRecordDecl( CXXRecordDecl* decl ) +{ + if( !isDerivedFrom( decl, inheritsPluginClassCheck )) + return true; + + if( decl->getName() == "FilteringPlugin" || decl->getName() == "FilteringRewritePlugin" ) + return true; + + PluginInfo pluginInfo; + pluginInfo.className = decl->getName().str(); + pluginInfo.variableName = pluginInfo.className; + assert( pluginInfo.variableName.size() > 0 ); + pluginInfo.variableName[ 0 ] = tolower( pluginInfo.variableName[ 0 ] ); + pluginInfo.lowercaseName = pluginInfo.className; + for( char& c : pluginInfo.lowercaseName ) + c = tolower( c ); + pluginInfo.shouldVisitTemplateInstantiations = false; + pluginInfo.shouldVisitImplicitCode = false; + for( const CXXMethodDecl* method : decl->methods()) + { + if( !method->getDeclName().isIdentifier()) + continue; + if( method->isStatic() || method->getAccess() != AS_public ) + continue; + if( method->getName().startswith( "Visit" )) + { + if( method->getNumParams() == 1 ) + { + VisitFunctionInfo visitInfo; + visitInfo.name = method->getName().str(); + visitInfo.argument = method->getParamDecl( 0 )->getTypeSourceInfo()->getType().getAsString(); + pluginInfo.visitFunctions.insert( move( visitInfo )); + } + else + { + cerr << "Unhandled Visit* function: " << pluginInfo.className << "::" << method->getName().str() << endl; + abort(); + } + } + else if( method->getName().startswith( "Traverse" )) + { + if( method->getNumParams() == 1 ) + { + TraverseFunctionInfo traverseInfo = findOrCreateTraverseFunctionInfo( pluginInfo, method->getName()); + traverseInfo.argument = method->getParamDecl( 0 )->getTypeSourceInfo()->getType().getAsString(); + pluginInfo.traverseFunctions.insert( move( traverseInfo )); + } + else + { + cerr << "Unhandled Traverse* function: " << pluginInfo.className << "::" << method->getName().str() << endl; + abort(); + } + } + else if( method->getName().startswith( "PreTraverse" )) + { + TraverseFunctionInfo traverseInfo = findOrCreateTraverseFunctionInfo( pluginInfo, method->getName(). substr( 3 )); + traverseInfo.hasPre = true; + pluginInfo.traverseFunctions.insert( move( traverseInfo )); + } + else if( method->getName().startswith( "PostTraverse" )) + { + TraverseFunctionInfo traverseInfo = findOrCreateTraverseFunctionInfo( pluginInfo, method->getName().substr( 4 )); + traverseInfo.hasPost = true; + pluginInfo.traverseFunctions.insert( move( traverseInfo )); + } + else if( method->getName() == "shouldVisitTemplateInstantiations" ) + pluginInfo.shouldVisitTemplateInstantiations = true; + else if( method->getName() == "shouldVisitImplicitCode" ) + pluginInfo.shouldVisitImplicitCode = true; + else if( method->getName().startswith( "WalkUp" )) + { + cerr << "WalkUp function not supported for shared visitor: " << pluginInfo.className << "::" << method->getName().str() << endl; + abort(); + } + } + + if( pluginInfo.shouldVisitTemplateInstantiations && pluginInfo.shouldVisitImplicitCode ) + plugins[ PluginVisitTemplatesImplicit ].push_back( move( pluginInfo )); + else if( pluginInfo.shouldVisitTemplateInstantiations ) + plugins[ PluginVisitTemplates ].push_back( move( pluginInfo )); + else if( pluginInfo.shouldVisitImplicitCode ) + plugins[ PluginVisitImplicit ].push_back( move( pluginInfo )); + else + plugins[ PluginBasic ].push_back( move( pluginInfo )); + return true; +} + + +class FindNamedClassConsumer + : public ASTConsumer +{ +public: + virtual void HandleTranslationUnit(ASTContext& context) override + { + visitor.TraverseDecl( context.getTranslationUnitDecl()); + } +private: + CheckFileVisitor visitor; +}; + +class FindNamedClassAction + : public ASTFrontendAction + { +public: + virtual unique_ptr<ASTConsumer> CreateASTConsumer( CompilerInstance&, StringRef ) override + { + return unique_ptr<ASTConsumer>( new FindNamedClassConsumer ); + } +}; + + +string readSourceFile( const char* filename ) +{ + string contents; + ifstream stream( filename ); + if( !stream ) + { + cerr << "Failed to open: " << filename << endl; + exit( 1 ); + } + string line; + bool hasIfdef = false; + while( getline( stream, line )) + { + // TODO add checks that it's e.g. not "#ifdef" ? + if( line.find( "#ifndef LO_CLANG_SHARED_PLUGINS" ) == 0 ) + hasIfdef = true; + contents += line; + contents += '\n'; + } + if( stream.eof() && hasIfdef ) + return contents; + return ""; +} + +int main(int argc, char** argv) +{ + for( int i = 1; i < argc; ++ i ) + { + string contents = readSourceFile(argv[i]); + if( contents.empty()) + continue; +#define STRINGIFY2(a) #a +#define STRINGIFY(a) STRINGIFY2(a) + vector< string > args = + { + "-I" STRINGIFY(BUILDDIR) "/config_host", // plugin sources use e.g. config_global.h + "-I" STRINGIFY(CLANGDIR) "/include", // clang's headers + "-I" STRINGIFY(CLANGSYSINCLUDE), // clang system headers + "-std=c++11", + "-D__STDC_CONSTANT_MACROS", // Clang headers require these. + "-D__STDC_FORMAT_MACROS", + "-D__STDC_LIMIT_MACROS", + }; + if( !clang::tooling::runToolOnCodeWithArgs( new FindNamedClassAction, contents, args, argv[ i ] )) + { + cerr << "Failed to analyze: " << argv[ i ] << endl; + return 2; + } + } + for( int type = Plugin_Begin; type < Plugin_End; ++type ) + { + sort( plugins[ static_cast< PluginType >( type ) ].begin(), plugins[ static_cast< PluginType >( type ) ].end(), + []( const PluginInfo& l, const PluginInfo& r ) { return l.className < r.className; } ); + } + generate(); + return 0; +} diff --git a/compilerplugins/clang/sharedvisitor/sharedvisitor.cxx b/compilerplugins/clang/sharedvisitor/sharedvisitor.cxx new file mode 100644 index 000000000000..5b72c329691d --- /dev/null +++ b/compilerplugins/clang/sharedvisitor/sharedvisitor.cxx @@ -0,0 +1,964 @@ +// This file is autogenerated. Do not modify. +// Generated by compilerplugins/clang/sharedvisitor/generator.cxx . + +#ifdef LO_CLANG_SHARED_PLUGINS + +#include <config_clang.h> + +#include <clang/AST/ASTContext.h> +#include <clang/AST/RecursiveASTVisitor.h> + +#include "../plugin.hxx" + +#undef LO_CLANG_SHARED_PLUGINS // to get sources of individual plugins +#include "../badstatics.cxx" +#include "../blockblock.cxx" +#include "../charrightshift.cxx" +#include "../datamembershadow.cxx" +#include "../dbgunhandledexception.cxx" +#include "../derefnullptr.cxx" +#include "../doubleconvert.cxx" +#include "../empty.cxx" +#include "../emptyif.cxx" +#include "../externandnotdefined.cxx" +#include "../externvar.cxx" +#include "../inlinevisible.cxx" +#include "../loopvartoosmall.cxx" +#include "../privatebase.cxx" +#include "../reservedid.cxx" +#include "../simplifyconstruct.cxx" +#include "../stringstatic.cxx" +#include "../subtlezeroinit.cxx" +#include "../unnecessaryoverride.cxx" +#include "../unnecessaryparen.cxx" +#include "../unreffun.cxx" +#include "../unusedvariablecheck.cxx" +#include "../weakobject.cxx" +#include "../dyncastvisibility.cxx" +#include "../vclwidgets.cxx" + +using namespace clang; +using namespace llvm; + +namespace loplugin +{ + +class SharedRecursiveASTVisitorBasic + : public FilteringPlugin< SharedRecursiveASTVisitorBasic> +{ +public: + explicit SharedRecursiveASTVisitorBasic(const InstantiationData& rData) + : FilteringPlugin(rData) + , badStatics( nullptr ) + , blockBlock( nullptr ) + , charRightShift( nullptr ) + , dataMemberShadow( nullptr ) + , dbgUnhandledException( nullptr ) + , derefNullPtr( nullptr ) + , doubleConvert( nullptr ) + , empty( nullptr ) + , emptyIf( nullptr ) + , externAndNotDefined( nullptr ) + , externVar( nullptr ) + , inlineVisible( nullptr ) + , loopVarTooSmall( nullptr ) + , privateBase( nullptr ) + , reservedId( nullptr ) + , simplifyConstruct( nullptr ) + , stringStatic( nullptr ) + , subtleZeroInit( nullptr ) + , unnecessaryOverride( nullptr ) + , unnecessaryParen( nullptr ) + , unrefFun( nullptr ) + , unusedVariableCheck( nullptr ) + , weakObject( nullptr ) + {} + virtual bool preRun() override + { + if( badStatics && !badStatics->preRun()) + badStatics = nullptr; + if( blockBlock && !blockBlock->preRun()) + blockBlock = nullptr; + if( charRightShift && !charRightShift->preRun()) + charRightShift = nullptr; + if( dataMemberShadow && !dataMemberShadow->preRun()) + dataMemberShadow = nullptr; + if( dbgUnhandledException && !dbgUnhandledException->preRun()) + dbgUnhandledException = nullptr; + if( derefNullPtr && !derefNullPtr->preRun()) + derefNullPtr = nullptr; + if( doubleConvert && !doubleConvert->preRun()) + doubleConvert = nullptr; + if( empty && !empty->preRun()) + empty = nullptr; + if( emptyIf && !emptyIf->preRun()) + emptyIf = nullptr; + if( externAndNotDefined && !externAndNotDefined->preRun()) + externAndNotDefined = nullptr; + if( externVar && !externVar->preRun()) + externVar = nullptr; + if( inlineVisible && !inlineVisible->preRun()) + inlineVisible = nullptr; + if( loopVarTooSmall && !loopVarTooSmall->preRun()) + loopVarTooSmall = nullptr; + if( privateBase && !privateBase->preRun()) + privateBase = nullptr; + if( reservedId && !reservedId->preRun()) + reservedId = nullptr; + if( simplifyConstruct && !simplifyConstruct->preRun()) + simplifyConstruct = nullptr; + if( stringStatic && !stringStatic->preRun()) + stringStatic = nullptr; + if( subtleZeroInit && !subtleZeroInit->preRun()) + subtleZeroInit = nullptr; + if( unnecessaryOverride && !unnecessaryOverride->preRun()) + unnecessaryOverride = nullptr; + if( unnecessaryParen && !unnecessaryParen->preRun()) + unnecessaryParen = nullptr; + if( unrefFun && !unrefFun->preRun()) + unrefFun = nullptr; + if( unusedVariableCheck && !unusedVariableCheck->preRun()) + unusedVariableCheck = nullptr; + if( weakObject && !weakObject->preRun()) + weakObject = nullptr; + return anyPluginActive(); + } + virtual void postRun() override + { + if( badStatics ) + badStatics->postRun(); + if( blockBlock ) + blockBlock->postRun(); + if( charRightShift ) + charRightShift->postRun(); + if( dataMemberShadow ) + dataMemberShadow->postRun(); + if( dbgUnhandledException ) + dbgUnhandledException->postRun(); + if( derefNullPtr ) + derefNullPtr->postRun(); + if( doubleConvert ) + doubleConvert->postRun(); + if( empty ) + empty->postRun(); + if( emptyIf ) + emptyIf->postRun(); + if( externAndNotDefined ) + externAndNotDefined->postRun(); + if( externVar ) + externVar->postRun(); + if( inlineVisible ) + inlineVisible->postRun(); + if( loopVarTooSmall ) + loopVarTooSmall->postRun(); + if( privateBase ) + privateBase->postRun(); + if( reservedId ) + reservedId->postRun(); + if( simplifyConstruct ) + simplifyConstruct->postRun(); + if( stringStatic ) + stringStatic->postRun(); + if( subtleZeroInit ) + subtleZeroInit->postRun(); + if( unnecessaryOverride ) + unnecessaryOverride->postRun(); + if( unnecessaryParen ) + unnecessaryParen->postRun(); + if( unrefFun ) + unrefFun->postRun(); + if( unusedVariableCheck ) + unusedVariableCheck->postRun(); + if( weakObject ) + weakObject->postRun(); + } + virtual void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + postRun(); + } + } + enum { isSharedPlugin = true }; + virtual bool setSharedPlugin( Plugin* plugin, const char* name ) override + { + if( strcmp( name, "badstatics" ) == 0 ) + badStatics = static_cast< BadStatics* >( plugin ); + else if( strcmp( name, "blockblock" ) == 0 ) + blockBlock = static_cast< BlockBlock* >( plugin ); + else if( strcmp( name, "charrightshift" ) == 0 ) + charRightShift = static_cast< CharRightShift* >( plugin ); + else if( strcmp( name, "datamembershadow" ) == 0 ) + dataMemberShadow = static_cast< DataMemberShadow* >( plugin ); + else if( strcmp( name, "dbgunhandledexception" ) == 0 ) + dbgUnhandledException = static_cast< DbgUnhandledException* >( plugin ); + else if( strcmp( name, "derefnullptr" ) == 0 ) + derefNullPtr = static_cast< DerefNullPtr* >( plugin ); + else if( strcmp( name, "doubleconvert" ) == 0 ) + doubleConvert = static_cast< DoubleConvert* >( plugin ); + else if( strcmp( name, "empty" ) == 0 ) + empty = static_cast< Empty* >( plugin ); + else if( strcmp( name, "emptyif" ) == 0 ) + emptyIf = static_cast< EmptyIf* >( plugin ); + else if( strcmp( name, "externandnotdefined" ) == 0 ) + externAndNotDefined = static_cast< ExternAndNotDefined* >( plugin ); + else if( strcmp( name, "externvar" ) == 0 ) + externVar = static_cast< ExternVar* >( plugin ); + else if( strcmp( name, "inlinevisible" ) == 0 ) + inlineVisible = static_cast< InlineVisible* >( plugin ); + else if( strcmp( name, "loopvartoosmall" ) == 0 ) + loopVarTooSmall = static_cast< LoopVarTooSmall* >( plugin ); + else if( strcmp( name, "privatebase" ) == 0 ) + privateBase = static_cast< PrivateBase* >( plugin ); + else if( strcmp( name, "reservedid" ) == 0 ) + reservedId = static_cast< ReservedId* >( plugin ); + else if( strcmp( name, "simplifyconstruct" ) == 0 ) + simplifyConstruct = static_cast< SimplifyConstruct* >( plugin ); + else if( strcmp( name, "stringstatic" ) == 0 ) + stringStatic = static_cast< StringStatic* >( plugin ); + else if( strcmp( name, "subtlezeroinit" ) == 0 ) + subtleZeroInit = static_cast< SubtleZeroInit* >( plugin ); + else if( strcmp( name, "unnecessaryoverride" ) == 0 ) + unnecessaryOverride = static_cast< UnnecessaryOverride* >( plugin ); + else if( strcmp( name, "unnecessaryparen" ) == 0 ) + unnecessaryParen = static_cast< UnnecessaryParen* >( plugin ); + else if( strcmp( name, "unreffun" ) == 0 ) + unrefFun = static_cast< UnrefFun* >( plugin ); + else if( strcmp( name, "unusedvariablecheck" ) == 0 ) + unusedVariableCheck = static_cast< UnusedVariableCheck* >( plugin ); + else if( strcmp( name, "weakobject" ) == 0 ) + weakObject = static_cast< WeakObject* >( plugin ); + else + return false; + return true; + } + bool VisitBinEQ(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( empty != nullptr ) + { + if( !empty->VisitBinEQ( arg )) + empty = nullptr; + } + return anyPluginActive(); + } + bool VisitBinGE(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( empty != nullptr ) + { + if( !empty->VisitBinGE( arg )) + empty = nullptr; + } + return anyPluginActive(); + } + bool VisitBinGT(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( empty != nullptr ) + { + if( !empty->VisitBinGT( arg )) + empty = nullptr; + } + return anyPluginActive(); + } + bool VisitBinLE(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( empty != nullptr ) + { + if( !empty->VisitBinLE( arg )) + empty = nullptr; + } + return anyPluginActive(); + } + bool VisitBinLT(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( empty != nullptr ) + { + if( !empty->VisitBinLT( arg )) + empty = nullptr; + } + return anyPluginActive(); + } + bool VisitBinNE(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( empty != nullptr ) + { + if( !empty->VisitBinNE( arg )) + empty = nullptr; + } + return anyPluginActive(); + } + bool VisitBinShr(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( charRightShift != nullptr ) + { + if( !charRightShift->VisitBinShr( arg )) + charRightShift = nullptr; + } + return anyPluginActive(); + } + bool VisitBinaryConditionalOperator(const class clang::BinaryConditionalOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitBinaryConditionalOperator( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXConstructExpr(const class clang::CXXConstructExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( simplifyConstruct != nullptr ) + { + if( !simplifyConstruct->VisitCXXConstructExpr( arg )) + simplifyConstruct = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXDeleteExpr(const class clang::CXXDeleteExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitCXXDeleteExpr( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXMethodDecl(const class clang::CXXMethodDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryOverride != nullptr ) + { + if( !unnecessaryOverride->VisitCXXMethodDecl( arg )) + unnecessaryOverride = nullptr; + } + if( weakObject != nullptr ) + { + if( !weakObject->VisitCXXMethodDecl( arg )) + weakObject = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXNewExpr(const class clang::CXXNewExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( subtleZeroInit != nullptr ) + { + if( !subtleZeroInit->VisitCXXNewExpr( arg )) + subtleZeroInit = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXOperatorCallExpr(const class clang::CXXOperatorCallExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitCXXOperatorCallExpr( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXRecordDecl(const class clang::CXXRecordDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( privateBase != nullptr ) + { + if( !privateBase->VisitCXXRecordDecl( arg )) + privateBase = nullptr; + } + return anyPluginActive(); + } + bool VisitCallExpr(const class clang::CallExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( dbgUnhandledException != nullptr ) + { + if( !dbgUnhandledException->VisitCallExpr( arg )) + dbgUnhandledException = nullptr; + } + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitCallExpr( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitCaseStmt(const class clang::CaseStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitCaseStmt( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitCompoundStmt(const class clang::CompoundStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( blockBlock != nullptr ) + { + if( !blockBlock->VisitCompoundStmt( arg )) + blockBlock = nullptr; + } + return anyPluginActive(); + } + bool VisitConditionalOperator(const class clang::ConditionalOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitConditionalOperator( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitDoStmt(const class clang::DoStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( loopVarTooSmall != nullptr ) + { + if( !loopVarTooSmall->VisitDoStmt( arg )) + loopVarTooSmall = nullptr; + } + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitDoStmt( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitFieldDecl(const class clang::FieldDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( dataMemberShadow != nullptr ) + { + if( !dataMemberShadow->VisitFieldDecl( arg )) + dataMemberShadow = nullptr; + } + return anyPluginActive(); + } + bool VisitForStmt(const class clang::ForStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( loopVarTooSmall != nullptr ) + { + if( !loopVarTooSmall->VisitForStmt( arg )) + loopVarTooSmall = nullptr; + } + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitForStmt( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitFunctionDecl(const class clang::FunctionDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( externAndNotDefined != nullptr ) + { + if( !externAndNotDefined->VisitFunctionDecl( arg )) + externAndNotDefined = nullptr; + } + if( inlineVisible != nullptr ) + { + if( !inlineVisible->VisitFunctionDecl( arg )) + inlineVisible = nullptr; + } + if( unrefFun != nullptr ) + { + if( !unrefFun->VisitFunctionDecl( arg )) + unrefFun = nullptr; + } + return anyPluginActive(); + } + bool VisitIfStmt(const class clang::IfStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( emptyIf != nullptr ) + { + if( !emptyIf->VisitIfStmt( arg )) + emptyIf = nullptr; + } + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitIfStmt( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitMaterializeTemporaryExpr(const class clang::MaterializeTemporaryExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( doubleConvert != nullptr ) + { + if( !doubleConvert->VisitMaterializeTemporaryExpr( arg )) + doubleConvert = nullptr; + } + return anyPluginActive(); + } + bool VisitMemberExpr(const class clang::MemberExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitMemberExpr( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitNamedDecl(const class clang::NamedDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( reservedId != nullptr ) + { + if( !reservedId->VisitNamedDecl( arg )) + reservedId = nullptr; + } + return anyPluginActive(); + } + bool VisitParenExpr(const class clang::ParenExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitParenExpr( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitReturnStmt(const class clang::ReturnStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( stringStatic != nullptr ) + { + if( !stringStatic->VisitReturnStmt( arg )) + stringStatic = nullptr; + } + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitReturnStmt( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitSwitchStmt(const class clang::SwitchStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitSwitchStmt( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitUnaryDeref(const class clang::UnaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( derefNullPtr != nullptr ) + { + if( !derefNullPtr->VisitUnaryDeref( arg )) + derefNullPtr = nullptr; + } + return anyPluginActive(); + } + bool VisitUnaryExprOrTypeTraitExpr(const class clang::UnaryExprOrTypeTraitExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitUnaryExprOrTypeTraitExpr( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool VisitVarDecl(const class clang::VarDecl *const arg) + { + if( ignoreLocation( arg )) + return true; + if( badStatics != nullptr ) + { + if( !badStatics->VisitVarDecl( arg )) + badStatics = nullptr; + } + if( externVar != nullptr ) + { + if( !externVar->VisitVarDecl( arg )) + externVar = nullptr; + } + if( stringStatic != nullptr ) + { + if( !stringStatic->VisitVarDecl( arg )) + stringStatic = nullptr; + } + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitVarDecl( arg )) + unnecessaryParen = nullptr; + } + if( unusedVariableCheck != nullptr ) + { + if( !unusedVariableCheck->VisitVarDecl( arg )) + unusedVariableCheck = nullptr; + } + return anyPluginActive(); + } + bool VisitWhileStmt(const class clang::WhileStmt * arg) + { + if( ignoreLocation( arg )) + return true; + if( loopVarTooSmall != nullptr ) + { + if( !loopVarTooSmall->VisitWhileStmt( arg )) + loopVarTooSmall = nullptr; + } + if( unnecessaryParen != nullptr ) + { + if( !unnecessaryParen->VisitWhileStmt( arg )) + unnecessaryParen = nullptr; + } + return anyPluginActive(); + } + bool TraverseCXXBindTemporaryExpr(class clang::CXXBindTemporaryExpr * arg) + { + SimplifyConstruct* saveSimplifyConstruct = simplifyConstruct; + if( simplifyConstruct != nullptr ) + { + if( !simplifyConstruct->PreTraverseCXXBindTemporaryExpr( arg )) + simplifyConstruct = nullptr; + } + bool ret = RecursiveASTVisitor::TraverseCXXBindTemporaryExpr( arg ); + simplifyConstruct = saveSimplifyConstruct; + return ret; + } + bool TraverseCXXCatchStmt(class clang::CXXCatchStmt * arg) + { + DbgUnhandledException* saveDbgUnhandledException = dbgUnhandledException; + if( dbgUnhandledException != nullptr ) + { + if( !dbgUnhandledException->PreTraverseCXXCatchStmt( arg )) + dbgUnhandledException = nullptr; + } + bool ret = RecursiveASTVisitor::TraverseCXXCatchStmt( arg ); + if( dbgUnhandledException != nullptr ) + { + if( !dbgUnhandledException->PostTraverseCXXCatchStmt( arg, ret )) + saveDbgUnhandledException = nullptr; + } + dbgUnhandledException = saveDbgUnhandledException; + return ret; + } + bool TraverseFriendDecl(class clang::FriendDecl * arg) + { + UnrefFun* saveUnrefFun = unrefFun; + if( unrefFun != nullptr ) + { + if( !unrefFun->PreTraverseFriendDecl( arg )) + unrefFun = nullptr; + } + bool ret = RecursiveASTVisitor::TraverseFriendDecl( arg ); + if( unrefFun != nullptr ) + { + if( !unrefFun->PostTraverseFriendDecl( arg, ret )) + saveUnrefFun = nullptr; + } + unrefFun = saveUnrefFun; + return ret; + } + bool TraverseInitListExpr(class clang::InitListExpr * arg) + { + SimplifyConstruct* saveSimplifyConstruct = simplifyConstruct; + if( simplifyConstruct != nullptr ) + { + if( !simplifyConstruct->PreTraverseInitListExpr( arg )) + simplifyConstruct = nullptr; + } + bool ret = RecursiveASTVisitor::TraverseInitListExpr( arg ); + simplifyConstruct = saveSimplifyConstruct; + return ret; + } + bool TraverseReturnStmt(class clang::ReturnStmt * arg) + { + SimplifyConstruct* saveSimplifyConstruct = simplifyConstruct; + if( simplifyConstruct != nullptr ) + { + if( !simplifyConstruct->PreTraverseReturnStmt( arg )) + simplifyConstruct = nullptr; + } + bool ret = RecursiveASTVisitor::TraverseReturnStmt( arg ); + simplifyConstruct = saveSimplifyConstruct; + return ret; + } +private: + bool anyPluginActive() const + { + return badStatics != nullptr + || blockBlock != nullptr + || charRightShift != nullptr + || dataMemberShadow != nullptr + || dbgUnhandledException != nullptr + || derefNullPtr != nullptr + || doubleConvert != nullptr + || empty != nullptr + || emptyIf != nullptr + || externAndNotDefined != nullptr + || externVar != nullptr + || inlineVisible != nullptr + || loopVarTooSmall != nullptr + || privateBase != nullptr + || reservedId != nullptr + || simplifyConstruct != nullptr + || stringStatic != nullptr + || subtleZeroInit != nullptr + || unnecessaryOverride != nullptr + || unnecessaryParen != nullptr + || unrefFun != nullptr + || unusedVariableCheck != nullptr + || weakObject != nullptr; + } + BadStatics* badStatics; + BlockBlock* blockBlock; + CharRightShift* charRightShift; + DataMemberShadow* dataMemberShadow; + DbgUnhandledException* dbgUnhandledException; + DerefNullPtr* derefNullPtr; + DoubleConvert* doubleConvert; + Empty* empty; + EmptyIf* emptyIf; + ExternAndNotDefined* externAndNotDefined; + ExternVar* externVar; + InlineVisible* inlineVisible; + LoopVarTooSmall* loopVarTooSmall; + PrivateBase* privateBase; + ReservedId* reservedId; + SimplifyConstruct* simplifyConstruct; + StringStatic* stringStatic; + SubtleZeroInit* subtleZeroInit; + UnnecessaryOverride* unnecessaryOverride; + UnnecessaryParen* unnecessaryParen; + UnrefFun* unrefFun; + UnusedVariableCheck* unusedVariableCheck; + WeakObject* weakObject; +}; + +loplugin::Plugin::Registration< SharedRecursiveASTVisitorBasic > registrationBasic("sharedvisitorBasic"); + + +class SharedRecursiveASTVisitorVisitTemplates + : public FilteringPlugin< SharedRecursiveASTVisitorVisitTemplates> +{ +public: + explicit SharedRecursiveASTVisitorVisitTemplates(const InstantiationData& rData) + : FilteringPlugin(rData) + , dynCastVisibility( nullptr ) + , vCLWidgets( nullptr ) + {} + virtual bool preRun() override + { + if( dynCastVisibility && !dynCastVisibility->preRun()) + dynCastVisibility = nullptr; + if( vCLWidgets && !vCLWidgets->preRun()) + vCLWidgets = nullptr; + return anyPluginActive(); + } + virtual void postRun() override + { + if( dynCastVisibility ) + dynCastVisibility->postRun(); + if( vCLWidgets ) + vCLWidgets->postRun(); + } + virtual void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + postRun(); + } + } + enum { isSharedPlugin = true }; + virtual bool setSharedPlugin( Plugin* plugin, const char* name ) override + { + if( strcmp( name, "dyncastvisibility" ) == 0 ) + dynCastVisibility = static_cast< DynCastVisibility* >( plugin ); + else if( strcmp( name, "vclwidgets" ) == 0 ) + vCLWidgets = static_cast< VCLWidgets* >( plugin ); + else + return false; + return true; + } +bool shouldVisitTemplateInstantiations() const { return true; } + bool VisitBinaryOperator(const class clang::BinaryOperator * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitBinaryOperator( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXConstructExpr(const class clang::CXXConstructExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitCXXConstructExpr( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXDeleteExpr(const class clang::CXXDeleteExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitCXXDeleteExpr( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXDestructorDecl(const class clang::CXXDestructorDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitCXXDestructorDecl( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitCXXDynamicCastExpr(const class clang::CXXDynamicCastExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( dynCastVisibility != nullptr ) + { + if( !dynCastVisibility->VisitCXXDynamicCastExpr( arg )) + dynCastVisibility = nullptr; + } + return anyPluginActive(); + } + bool VisitCallExpr(const class clang::CallExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitCallExpr( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitDeclRefExpr(const class clang::DeclRefExpr * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitDeclRefExpr( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitFieldDecl(const class clang::FieldDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitFieldDecl( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitFunctionDecl(const class clang::FunctionDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitFunctionDecl( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitParmVarDecl(const class clang::ParmVarDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitParmVarDecl( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } + bool VisitVarDecl(const class clang::VarDecl * arg) + { + if( ignoreLocation( arg )) + return true; + if( vCLWidgets != nullptr ) + { + if( !vCLWidgets->VisitVarDecl( arg )) + vCLWidgets = nullptr; + } + return anyPluginActive(); + } +private: + bool anyPluginActive() const + { + return dynCastVisibility != nullptr + || vCLWidgets != nullptr; + } + DynCastVisibility* dynCastVisibility; + VCLWidgets* vCLWidgets; +}; + +loplugin::Plugin::Registration< SharedRecursiveASTVisitorVisitTemplates > registrationVisitTemplates("sharedvisitorVisitTemplates"); + +} // namespace loplugin + +#endif // LO_CLANG_SHARED_PLUGINS diff --git a/compilerplugins/clang/simplifyconstruct.cxx b/compilerplugins/clang/simplifyconstruct.cxx index b48764302eae..652a980cec6a 100644 --- a/compilerplugins/clang/simplifyconstruct.cxx +++ b/compilerplugins/clang/simplifyconstruct.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <memory> #include <cassert> #include <string> @@ -34,6 +36,10 @@ public: bool TraverseReturnStmt(ReturnStmt*) { return true; } bool TraverseInitListExpr(InitListExpr*) { return true; } bool TraverseCXXBindTemporaryExpr(CXXBindTemporaryExpr*) { return true; } + // ignore them for the shared visitor too + bool PreTraverseReturnStmt(ReturnStmt*) { return false; } + bool PreTraverseInitListExpr(InitListExpr*) { return false; } + bool PreTraverseCXXBindTemporaryExpr(CXXBindTemporaryExpr*) { return false; } }; bool SimplifyConstruct::VisitCXXConstructExpr(CXXConstructExpr const* constructExpr) @@ -63,7 +69,9 @@ bool SimplifyConstruct::VisitCXXConstructExpr(CXXConstructExpr const* constructE return true; } -loplugin::Plugin::Registration<SimplifyConstruct> X("simplifyconstruct", true); +loplugin::Plugin::Registration<SimplifyConstruct> simplifyconstruct("simplifyconstruct", true); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial1.cxx b/compilerplugins/clang/store/tutorial/tutorial1.cxx index 0b73431fbbad..9f7c97fb776f 100644 --- a/compilerplugins/clang/store/tutorial/tutorial1.cxx +++ b/compilerplugins/clang/store/tutorial/tutorial1.cxx @@ -61,7 +61,7 @@ bool Tutorial1::VisitReturnStmt( const ReturnStmt* returnstmt ) } // Register the plugin action with the LO plugin handling. -static Plugin::Registration< Tutorial1 > X( "tutorial1" ); +static Plugin::Registration< Tutorial1 > tutorial1( "tutorial1" ); } // namespace diff --git a/compilerplugins/clang/store/tutorial/tutorial2.cxx b/compilerplugins/clang/store/tutorial/tutorial2.cxx index 8ef338c6d5f8..49aaaa63183f 100644 --- a/compilerplugins/clang/store/tutorial/tutorial2.cxx +++ b/compilerplugins/clang/store/tutorial/tutorial2.cxx @@ -88,7 +88,7 @@ bool Tutorial2::isReturnFalse( const Stmt* stmt ) } // Register the plugin action with the LO plugin handling. -static Plugin::Registration< Tutorial2 > X( "tutorial2" ); +static Plugin::Registration< Tutorial2 > tutorial2( "tutorial2" ); } // namespace diff --git a/compilerplugins/clang/store/tutorial/tutorial3.cxx b/compilerplugins/clang/store/tutorial/tutorial3.cxx index e48118611eb7..33a1249a3400 100644 --- a/compilerplugins/clang/store/tutorial/tutorial3.cxx +++ b/compilerplugins/clang/store/tutorial/tutorial3.cxx @@ -70,7 +70,7 @@ void Tutorial3::modifyReturnFalse( const Stmt* stmt ) } // Register the plugin action with the LO plugin handling. -static Plugin::Registration< Tutorial3 > X( "tutorial3" ); +static Plugin::Registration< Tutorial3 > tutorial3( "tutorial3" ); } // namespace diff --git a/compilerplugins/clang/stringstatic.cxx b/compilerplugins/clang/stringstatic.cxx index 1a46fdd3dee8..a923da405f25 100644 --- a/compilerplugins/clang/stringstatic.cxx +++ b/compilerplugins/clang/stringstatic.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <set> #include "check.hxx" @@ -30,6 +32,8 @@ public: FilteringPlugin(rData) {} void run() override; + bool preRun() override; + void postRun() override; bool VisitVarDecl(VarDecl const*); bool VisitReturnStmt(ReturnStmt const*); private: @@ -39,16 +43,25 @@ private: void StringStatic::run() { + if( preRun()) + if( TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + postRun(); +} + +bool StringStatic::preRun() +{ StringRef fn(handler.getMainFileName()); // passing around pointers to global OUString if (loplugin::hasPathnamePrefix(fn, SRCDIR "/filter/source/svg/")) - return; + return false; // has a mix of literals and refs to external OUStrings if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/webdav-neon/ContentProperties.cxx")) - return; - - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + return false; + return true; +} +void StringStatic::postRun() +{ for (auto const & pVarDecl : excludeVars) { potentialVars.erase(pVarDecl); } @@ -128,8 +141,10 @@ bool StringStatic::VisitReturnStmt(ReturnStmt const * returnStmt) return true; } -loplugin::Plugin::Registration<StringStatic> X("stringstatic"); +loplugin::Plugin::Registration<StringStatic> stringstatic("stringstatic"); } // namespace +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/subtlezeroinit.cxx b/compilerplugins/clang/subtlezeroinit.cxx index aa0a3dd72d13..b1b91c8477d5 100644 --- a/compilerplugins/clang/subtlezeroinit.cxx +++ b/compilerplugins/clang/subtlezeroinit.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "plugin.hxx" // Find occurrences of 'new T()' where the instance is zero-initialized upfront @@ -45,16 +47,21 @@ public: return true; } -private: - void run() override { - if (compiler.getLangOpts().CPlusPlus) { + virtual bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + } + + virtual void run() override { + if (preRun()) { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } } }; -static loplugin::Plugin::Registration<SubtleZeroInit> reg("subtlezeroinit"); +static loplugin::Plugin::Registration<SubtleZeroInit> subtlezeroinit("subtlezeroinit"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unnecessaryoverride.cxx b/compilerplugins/clang/unnecessaryoverride.cxx index 00a1f7686c21..4d4cee322751 100644 --- a/compilerplugins/clang/unnecessaryoverride.cxx +++ b/compilerplugins/clang/unnecessaryoverride.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> #include <string> #include <iostream> @@ -69,31 +71,36 @@ class UnnecessaryOverride: public: explicit UnnecessaryOverride(loplugin::InstantiationData const & data): FilteringPlugin(data) {} - virtual void run() override + virtual bool preRun() override { // ignore some files with problematic macros StringRef fn(handler.getMainFileName()); if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/framework/factories/ChildWindowPane.cxx")) - return; + return false; if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/Date.cxx")) - return; + return false; if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/Time.cxx")) - return; + return false; if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/hyperdlg.cxx")) - return; + return false; if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/rubydialog.cxx")) - return; + return false; if (loplugin::hasPathnamePrefix(fn, SRCDIR "/canvas/")) - return; + return false; if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/view/spelldialog.cxx")) - return; + return false; if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/dlg/SpellDialogChildWindow.cxx")) - return; + return false; // HAVE_ODBC_ADMINISTRATION if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dsselect.cxx")) - return; + return false; + return true; + } - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + virtual void run() override + { + if( preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } bool VisitCXXMethodDecl(const CXXMethodDecl *); @@ -515,8 +522,10 @@ CXXMemberCallExpr const * UnnecessaryOverride::extractCallExpr(Expr const *retur return dyn_cast<CXXMemberCallExpr>(returnExpr->IgnoreParenImpCasts()); } -loplugin::Plugin::Registration< UnnecessaryOverride > X("unnecessaryoverride", true); +loplugin::Plugin::Registration< UnnecessaryOverride > unnecessaryoverride("unnecessaryoverride", true); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unnecessaryparen.cxx b/compilerplugins/clang/unnecessaryparen.cxx index 119ee98e13a5..9fb8fb85aa82 100644 --- a/compilerplugins/clang/unnecessaryparen.cxx +++ b/compilerplugins/clang/unnecessaryparen.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> #include <string> #include <iostream> @@ -73,16 +75,20 @@ public: explicit UnnecessaryParen(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) {} - virtual void run() override + virtual bool preRun() override { StringRef fn(handler.getMainFileName()); // fixing this, makes the source in the .y files look horrible if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx")) - return; + return false; if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/idlc/source/parser.cxx")) - return; - - TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + return false; + return true; + } + virtual void run() override + { + if( preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } bool VisitParenExpr(const ParenExpr *); @@ -626,8 +632,10 @@ bool UnnecessaryParen::removeParens(ParenExpr const * expr) { return true; } -loplugin::Plugin::Registration< UnnecessaryParen > X("unnecessaryparen", true); +loplugin::Plugin::Registration< UnnecessaryParen > unnecessaryparen("unnecessaryparen", true); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unreffun.cxx b/compilerplugins/clang/unreffun.cxx index 04c4e9f95dc1..e5ea7f34ee38 100644 --- a/compilerplugins/clang/unreffun.cxx +++ b/compilerplugins/clang/unreffun.cxx @@ -7,7 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <cassert> +#include <stack> #include <string> #include "clang/AST/Attr.h" @@ -71,18 +74,25 @@ public: void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + bool PreTraverseFriendDecl(FriendDecl * decl) { + friendFunction.push( dyn_cast_or_null<FunctionDecl>(decl->getFriendDecl())); + return true; + } + bool PostTraverseFriendDecl(FriendDecl *, bool ) { + friendFunction.pop(); + return true; + } bool TraverseFriendDecl(FriendDecl * decl) { - auto const old = friendFunction_; - friendFunction_ = dyn_cast_or_null<FunctionDecl>(decl->getFriendDecl()); + PreTraverseFriendDecl(decl); auto const ret = RecursiveASTVisitor::TraverseFriendDecl(decl); - friendFunction_ = old; + PostTraverseFriendDecl(decl, ret); return ret; } bool VisitFunctionDecl(FunctionDecl const * decl); private: - FunctionDecl const * friendFunction_ = nullptr; + std::stack<FunctionDecl const *> friendFunction; }; bool UnrefFun::VisitFunctionDecl(FunctionDecl const * decl) { @@ -98,7 +108,7 @@ bool UnrefFun::VisitFunctionDecl(FunctionDecl const * decl) { { return true; } - if (decl == friendFunction_) { + if (!friendFunction.empty() && decl == friendFunction.top()) { if (auto const lex = dyn_cast<CXXRecordDecl>(decl->getLexicalDeclContext())) { if (lex->isDependentContext()) { return true; @@ -200,8 +210,10 @@ bool UnrefFun::VisitFunctionDecl(FunctionDecl const * decl) { return true; } -loplugin::Plugin::Registration<UnrefFun> X("unreffun"); +loplugin::Plugin::Registration<UnrefFun> unreffun("unreffun"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedvariablecheck.cxx b/compilerplugins/clang/unusedvariablecheck.cxx index 8200ae8fc3b1..25af5438b465 100644 --- a/compilerplugins/clang/unusedvariablecheck.cxx +++ b/compilerplugins/clang/unusedvariablecheck.cxx @@ -9,6 +9,8 @@ * */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <config_global.h> #include "compat.hxx" @@ -72,8 +74,10 @@ bool UnusedVariableCheck::VisitVarDecl( const VarDecl* var ) return true; } -static Plugin::Registration< UnusedVariableCheck > X( "unusedvariablecheck" ); +static Plugin::Registration< UnusedVariableCheck > unusedvariablecheck( "unusedvariablecheck" ); } // namespace +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx index 8f625f5cdfdf..4c699bc5a77b 100644 --- a/compilerplugins/clang/vclwidgets.cxx +++ b/compilerplugins/clang/vclwidgets.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include <memory> #include <string> #include <iostream> @@ -859,8 +861,10 @@ bool VCLWidgets::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr ) return true; } -loplugin::Plugin::Registration< VCLWidgets > X("vclwidgets"); +loplugin::Plugin::Registration< VCLWidgets > vclwidgets("vclwidgets"); } +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/weakobject.cxx b/compilerplugins/clang/weakobject.cxx index 1f801d6acdd2..afa652befc1a 100644 --- a/compilerplugins/clang/weakobject.cxx +++ b/compilerplugins/clang/weakobject.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LO_CLANG_SHARED_PLUGINS + #include "check.hxx" #include "plugin.hxx" @@ -26,8 +28,11 @@ public: explicit WeakObject(loplugin::InstantiationData const& rData): FilteringPlugin(rData) {} + virtual bool preRun() override { + return compiler.getLangOpts().CPlusPlus; // no OWeakObject in C + } void run() override { - if (compiler.getLangOpts().CPlusPlus) { // no OWeakObject in C + if( preRun()) { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } } @@ -153,8 +158,10 @@ public: }; -loplugin::Plugin::Registration<WeakObject> X("weakobject"); +loplugin::Plugin::Registration<WeakObject> weakobject("weakobject"); } // namespace +#endif // LO_CLANG_SHARED_PLUGINS + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |