class ManualRefCount: public RecursiveASTVisitor<ManualRefCount>, public loplugin::Plugin
{ public: explicit ManualRefCount(InstantiationData const & data): Plugin(data) {}
// old code, no point in updating if (loplugin::isSamePathname(fn, SRCDIR "/store/source/store.cxx")) return;
// TODO ----------------------------- if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/registry.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/regimpl.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/reflread.cxx")) return; // TODO MenuAttributes::CreateAttribute if (loplugin::isSamePathname(fn, SRCDIR "/framework/source/fwe/xml/menuconfiguration.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/app/apphdl.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/core/dataaccess/ModelImpl.cxx")) return; // need a better replacement for vcl::EventPoster if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/acceleratorexecute.cxx")) return; // PostUserEvent stuff if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxwindow.cxx")) return; // playing games with pointers passed into combobox entries if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfgutil.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfg.cxx")) return; // END TODO -----------------------------
// can't fix these without breaking stable ABI if (fn.startswith(SRCDIR "/sal/")) return; if (fn.startswith(SRCDIR "/salhelper/")) return; if (fn.startswith(SRCDIR "/cppu/")) return; if (fn.startswith(SRCDIR "/cppuhelper/")) return; if (fn.startswith(SRCDIR "/bridges/")) return;
// lots of magic here if (fn.startswith(SRCDIR "/stoc/")) return; if (fn.startswith(SRCDIR "/testtools/")) return;
// mutex games if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/scheduler.cxx")) return; // opengl games if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/svdata.cxx")) return;
// passing the pointer through PostUserEvent if (loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/gstreamer/gstplayer.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/form/fmscriptingenv.cxx")) return;
// thread games if (loplugin::isSamePathname(fn, SRCDIR "/io/source/stm/opump.cxx")) return;
// ??? no idea what this code is up to if (loplugin::isSamePathname(fn, SRCDIR "/extensions/source/scanner/scanunx.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/stoc/source/invocation_adapterfactory/iafactory.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/fpicker/source/office/asyncfilepicker.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/FormComponent.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/bc.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/filprp.cxx")) return;
// implementing css::uno::XInterface if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/animations/motionpathtag.cxx")) return; // UNO factory methods if (fn.startswith(SRCDIR "/comphelper/")) return; if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/convdiclist.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/dlistimp.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/gciterator.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngsvcmgr.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngopt.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/gdi/gcach_xpeer.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/spellcheck/spell/sspellimp.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/thesaurus/libnth/nthesimp.cxx")) return;
// some kind of complicated listener nonsense if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/framework/tools/FrameworkHelper.cxx")) return; // more listener nonsense if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/uno/unomailmerge.cxx")) return; // playing games with it's listener list if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/cellsuno.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/chart2uno.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/dapiuno.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/datauno.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/linkuno.cxx")) return; // PostUserEvent if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbaeventshelper.cxx")) return; // thread holding itself if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/EventThread.cxx")) return;
bool ManualRefCount::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl)
{ if (ignoreCallerClass(cxxMethodDecl->getParent())) returntrue; // disambiguating forwarding methods for XInterface subclasses if (cxxMethodDecl->getIdentifier() && (cxxMethodDecl->getName() == "acquire" || cxxMethodDecl->getName() == "release")) returntrue; return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl);
}
bool ManualRefCount::TraverseFunctionDecl(FunctionDecl* functionDecl)
{ auto tc = loplugin::DeclCheck(functionDecl); if (tc.Function("make_shared_from_UNO").Namespace("comphelper").GlobalNamespace()) returntrue; return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl);
}
bool ManualRefCount::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxMethodDecl)
{ if (ignoreCallerClass(cxxMethodDecl->getParent())) returntrue; return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl);
}
bool ManualRefCount::TraverseCXXDestructorDecl(CXXDestructorDecl*)
{ // just ignore destructors, tons of places like to call acquire() on themselves in their destructor // supposedly to prevent recursively calling the destructor returntrue;
} bool ManualRefCount::TraverseCXXConversionDecl(CXXConversionDecl* cxxMethodDecl)
{ if (ignoreCallerClass(cxxMethodDecl->getParent())) returntrue; return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl);
} bool ManualRefCount::TraverseCXXRecordDecl(CXXRecordDecl* cxxRecordDecl)
{ if (ignoreCallerClass(cxxRecordDecl)) returntrue; return RecursiveASTVisitor::TraverseCXXRecordDecl(cxxRecordDecl);
}
bool ManualRefCount::TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl* templateDecl)
{ if (ignoreCallerClass(templateDecl)) returntrue; return RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(templateDecl);
}
bool ManualRefCount::TraverseLinkageSpecDecl(LinkageSpecDecl *)
{ // ignore methods inside "extern ""C""" blocks, these are normally UNO constructors, which // are required to raise the reference count before returning returntrue;
}
bool ManualRefCount::ignoreCallerClass(CXXRecordDecl* cxxRecordDecl)
{ auto tc = loplugin::TypeCheck(cxxRecordDecl); return
tc.Class("Reference").Namespace("rtl").GlobalNamespace()
|| tc.Class("cow_wrapper").Namespace("o3tl").GlobalNamespace()
|| tc.Class("Reference").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()
|| tc.Class("ShareGuard").Namespace("framework").GlobalNamespace()
|| tc.Class("ControlModelLock").Namespace("frm").GlobalNamespace()
|| tc.Struct("ReleaseFunc").Namespace("detail").Namespace("comphelper").GlobalNamespace() // TODO no idea what this is up to
|| tc.Class("SfxModelSubComponent").GlobalNamespace()
|| tc.Class("OSubComponent").Namespace("mysqlc").Namespace("connectivity").GlobalNamespace()
|| tc.Class("OSubComponent").Namespace("connectivity").GlobalNamespace() // TODO do we really need this?
|| tc.Class("ShareableMutex").Namespace("framework").GlobalNamespace()
|| tc.Class("ObservableThread").GlobalNamespace()
;
}
bool ManualRefCount::VisitCXXMemberCallExpr(const CXXMemberCallExpr* cxxMemberCallExpr)
{ if (ignoreLocation(cxxMemberCallExpr)) returntrue; if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(cxxMemberCallExpr->getLocStart()))) returntrue;
// first, use some heuristics to find the right kind of acquire()/release() calls
CXXMethodDecl const * calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); if (!calleeMethodDecl || !calleeMethodDecl->getIdentifier()) returntrue; if (calleeMethodDecl->getName() != "acquire" && calleeMethodDecl->getName() != "release") returntrue; if (calleeMethodDecl->getNumParams() != 0) returntrue; // std::unique_ptr::release() and similar methods if (calleeMethodDecl->getName() == "release" && loplugin::TypeCheck(calleeMethodDecl->getReturnType()).Pointer()) returntrue;
// these are OK auto calleeRecordTC = loplugin::TypeCheck(calleeMethodDecl->getParent()); if (calleeRecordTC.Struct("ResourceHolder").Namespace("store").GlobalNamespace()) returntrue; if (calleeRecordTC.Class("Module").Namespace("osl").GlobalNamespace()) returntrue; if (calleeRecordTC.Class("Mutex").Namespace("osl").GlobalNamespace()) returntrue; if (calleeRecordTC.Class("multi_type_vector").Namespace("mdds").GlobalNamespace()) returntrue;
// while (calleeMethodDecl->size_overridden_methods() > 0) // calleeMethodDecl = *calleeMethodDecl->begin_overridden_methods(); // auto tc2 = loplugin::TypeCheck(calleeMethodDecl->getParent()); // if (tc2.Class("XInterface").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) // return true;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.