diff options
Diffstat (limited to '')
-rw-r--r-- | compilerplugins/clang/redundantstatic.cxx | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/compilerplugins/clang/redundantstatic.cxx b/compilerplugins/clang/redundantstatic.cxx new file mode 100644 index 000000000..40f6ab45f --- /dev/null +++ b/compilerplugins/clang/redundantstatic.cxx @@ -0,0 +1,122 @@ +/* -*- 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. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +/* +This is a compile check. + +Warns about functions with static keyword in an unnamed namespace. +*/ + +namespace loplugin +{ + +class RedundantStatic + : public loplugin::FilteringPlugin<RedundantStatic> + { + public: + explicit RedundantStatic( const InstantiationData& data ); + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + virtual void run() override; + bool VisitFunctionDecl( const FunctionDecl* func ); + + bool VisitVarDecl(VarDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (!decl->isFileVarDecl() || decl->isStaticDataMember()) { + return true; + } + if (decl->getStorageClass() != SC_Static) { + return true; + } + if (decl->isInAnonymousNamespace()) { + auto loc = decl->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + auto const name = Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + if (name == "CPPUNIT_TEST_SUITE_REGISTRATION" + || name == "CPPUNIT_TEST_SUITE_NAMED_REGISTRATION") + { + // Those macros contain a `static`, but are often used in an unnamed + // namespace, so filter them out: + return true; + } + } + report( + DiagnosticsEngine::Warning, "redundant 'static' keyword in unnamed namespace", + decl->getLocation()) + << decl->getSourceRange(); + return true; + } + if (decl->isInline()) { + return true; + } + if (!loplugin::TypeCheck(decl->getType()).ConstNonVolatile()) { + return true; + } + report( + DiagnosticsEngine::Warning, + "non-inline variable of non-volatile const-qualified type is redundantly marked as" + " 'static'", + decl->getLocation()) + << decl->getSourceRange(); + return true; + } + }; + +RedundantStatic::RedundantStatic( const InstantiationData& data ) + : FilteringPlugin( data ) + { + } + +void RedundantStatic::run() + { + if (preRun()) { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + } + + +bool RedundantStatic::VisitFunctionDecl( const FunctionDecl* func ) + + { + if( ignoreLocation( func ) ) + return true; + if( func -> isInAnonymousNamespace () ) + { + if ( !isa<CXXMethodDecl>(func) && !func->isInExternCContext() ) + { + if(func-> getStorageClass() == SC_Static) + { + report( DiagnosticsEngine::Warning, + "redundant 'static' keyword in unnamed namespace", + func->getBeginLoc()); + } + } + } + + return true; + } + +// Register the plugin action with the LO plugin handling. +static Plugin::Registration< RedundantStatic > redundantstatic("redundantstatic"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |