summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/Makefile-clang.mk48
-rw-r--r--compilerplugins/clang/badstatics.cxx12
-rw-r--r--compilerplugins/clang/blockblock.cxx17
-rw-r--r--compilerplugins/clang/charrightshift.cxx6
-rw-r--r--compilerplugins/clang/check.hxx2
-rw-r--r--compilerplugins/clang/datamembershadow.cxx6
-rw-r--r--compilerplugins/clang/dbgunhandledexception.cxx38
-rw-r--r--compilerplugins/clang/derefnullptr.cxx6
-rw-r--r--compilerplugins/clang/doubleconvert.cxx6
-rw-r--r--compilerplugins/clang/dyncastvisibility.cxx11
-rw-r--r--compilerplugins/clang/empty.cxx6
-rw-r--r--compilerplugins/clang/emptyif.cxx6
-rw-r--r--compilerplugins/clang/externandnotdefined.cxx6
-rw-r--r--compilerplugins/clang/externvar.cxx6
-rw-r--r--compilerplugins/clang/inlinevisible.cxx6
-rw-r--r--compilerplugins/clang/loopvartoosmall.cxx6
-rw-r--r--compilerplugins/clang/plugin.cxx5
-rw-r--r--compilerplugins/clang/plugin.hxx16
-rw-r--r--compilerplugins/clang/pluginhandler.cxx25
-rw-r--r--compilerplugins/clang/pluginhandler.hxx3
-rw-r--r--compilerplugins/clang/privatebase.cxx6
-rw-r--r--compilerplugins/clang/reservedid.cxx15
-rw-r--r--compilerplugins/clang/sharedvisitor/generator.cxx563
-rw-r--r--compilerplugins/clang/sharedvisitor/sharedvisitor.cxx964
-rw-r--r--compilerplugins/clang/simplifyconstruct.cxx10
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial1.cxx2
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2.cxx2
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial3.cxx2
-rw-r--r--compilerplugins/clang/stringstatic.cxx25
-rw-r--r--compilerplugins/clang/subtlezeroinit.cxx15
-rw-r--r--compilerplugins/clang/unnecessaryoverride.cxx33
-rw-r--r--compilerplugins/clang/unnecessaryparen.cxx20
-rw-r--r--compilerplugins/clang/unreffun.cxx24
-rw-r--r--compilerplugins/clang/unusedvariablecheck.cxx6
-rw-r--r--compilerplugins/clang/vclwidgets.cxx6
-rw-r--r--compilerplugins/clang/weakobject.cxx11
36 files changed, 1860 insertions, 81 deletions
diff --git a/compilerplugins/Makefile-clang.mk b/compilerplugins/Makefile-clang.mk
index 36784fbb4f14..af61c14e1664 100644
--- a/compilerplugins/Makefile-clang.mk
+++ b/compilerplugins/Makefile-clang.mk
@@ -22,6 +22,10 @@ else
CLANGCXXFLAGS=-O2 -Wall -Wextra -Wundef -g
endif
+# Whether to make plugins use one shared ASTRecursiveVisitor (plugins run faster).
+# By default enabled, disable if you work on an affected plugin (re-generating takes time).
+LO_CLANG_SHARED_PLUGINS=1
+
# The uninteresting rest.
include $(SRCDIR)/solenv/gbuild/gbuild.mk
@@ -50,6 +54,8 @@ else
CLANGINCLUDES=$(if $(filter /usr,$(CLANGDIR)),,-isystem $(CLANGDIR)/include)
endif
+LLVMCONFIG=$(CLANGDIR)/bin/llvm-config
+
# Clang/LLVM libraries are intentionally not linked in, they are usually built as static libraries, which means the resulting
# plugin would be big (even though the clang binary already includes it all) and it'd be necessary to explicitly specify
# also all the dependency libraries.
@@ -59,6 +65,10 @@ CLANGINDIR=$(SRCDIR)/compilerplugins/clang
# plugin will cause cache misses with ccache.
CLANGOUTDIR=$(BUILDDIR)/compilerplugins/obj
+ifdef LO_CLANG_SHARED_PLUGINS
+CLANGCXXFLAGS+=-DLO_CLANG_SHARED_PLUGINS
+endif
+
QUIET=$(if $(verbose),,@)
ifneq ($(ENABLE_WERROR),)
@@ -72,8 +82,13 @@ endif
compilerplugins: compilerplugins-build
+ifdef LO_CLANG_SHARED_PLUGINS
+# The shared source, intentionally put first in the list because it takes the longest to build.
+CLANGSRC=sharedvisitor/sharedvisitor.cxx
+endif
# The list of source files, generated automatically (all files in clang/, but not subdirs).
-CLANGSRC=$(foreach src,$(wildcard $(CLANGINDIR)/*.cxx), $(notdir $(src)))
+CLANGSRC+=$(foreach src,$(wildcard $(CLANGINDIR)/*.cxx), $(notdir $(src)))
+
# Remember the sources and if they have changed, force plugin relinking.
CLANGSRCCHANGED= \
$(shell mkdir -p $(CLANGOUTDIR) ; \
@@ -152,4 +167,35 @@ endif
$(CLANGOUTDIR)/clang-timestamp: $(CLANGDIR)/bin/clang$(CLANG_EXE_EXT)
$(QUIET)touch $@
+
+ifdef LO_CLANG_SHARED_PLUGINS
+# Update the shared visitor source if needed. It is intentionally included in the sources and generated only when
+# needed, because the generating takes a while.
+# If you want to remake the source with LO_CLANG_SHARED_PLUGINS disabled, run 'make LO_CLANG_SHARED_PLUGINS=1'.
+$(CLANGINDIR)/sharedvisitor/sharedvisitor.cxx: $(shell grep -l "LO_CLANG_SHARED_PLUGINS" $(CLANGINDIR)/*.cxx)
+$(CLANGINDIR)/sharedvisitor/sharedvisitor.cxx: $(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT)
+ $(call gb_Output_announce,$(subst $(SRCDIR)/,,$@),$(true),GEN,1)
+ $(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT) $(shell grep -l "LO_CLANG_SHARED_PLUGINS" $(CLANGINDIR)/*.cxx) \
+ > $(CLANGINDIR)/sharedvisitor/sharedvisitor.cxx
+
+CLANGTOOLLIBS = -lclangTooling -lclangDriver -lclangFrontend -lclangParse -lclangSema -lclangEdit -lclangAnalysis \
+ -lclangAST -lclangLex -lclangSerialization -lclangBasic $(shell $(LLVMCONFIG) --ldflags --libs --system-libs)
+# Path to the clang system headers (no idea if there's a better way to get it).
+CLANGTOOLDEFS = -DCLANGSYSINCLUDE=$(shell $(LLVMCONFIG) --libdir)/clang/$(shell $(LLVMCONFIG) --version | sed 's/svn//')/include
+
+$(CLANGOUTDIR)/sharedvisitor/generator$(CLANG_EXE_EXT): $(CLANGINDIR)/sharedvisitor/generator.cxx
+ $(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,1)
+ $(QUIET)$(COMPILER_PLUGINS_CXX) $(CLANGCXXFLAGS) $(CLANGWERROR) $(CLANGDEFS) $(CLANGTOOLDEFS) $(CLANGINCLUDES) \
+ -DCLANGDIR=$(CLANGDIR) -DBUILDDIR=$(BUILDDIR) -I$(BUILDDIR)/config_host \
+ $< -o $@ -MMD -MT $@ -MP -MF $(CLANGOUTDIR)/sharedvisitor/generator.d $(CLANGTOOLLIBS)
+
+compilerplugins-build: $(CLANGOUTDIR)/sharedvisitor
+
+$(CLANGOUTDIR)/sharedvisitor:
+ mkdir -p $(CLANGOUTDIR)/sharedvisitor
+
+-include $(CLANGOUTDIR)/sharedvisitor/generator.d
+# TODO WNT version
+endif
+
# vim: set noet sw=4 ts=4:
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: */