namespace
{ class ShouldReturnBool
: public loplugin::FunctionAddress<loplugin::FilteringPlugin<ShouldReturnBool>>
{ public: explicit ShouldReturnBool(loplugin::InstantiationData const& data)
: FunctionAddress(data)
{
}
virtualvoid run() override
{ if (!compiler.getLangOpts().CPlusPlus) return;
StringRef fn(handler.getMainFileName()); // functions used as function pointers if (loplugin::isSamePathname(fn, SRCDIR "/sal/rtl/alloc_cache.cxx")) return; // false +, slightly odd usage, but not wrong if (loplugin::isSamePathname(fn, SRCDIR "/libreofficekit/qa/tilebench/tilebench.cxx")) return; // template magic if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/gdi/bmpfast.cxx")) return; // fine if (loplugin::isSamePathname(fn, SRCDIR "/svl/unx/source/svdde/ddedummy.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/opengl/OpenGLHelper.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/imap2.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/docrecovery.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/lexer.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/grammar.cxx")) return; if (loplugin::isSamePathname(
fn, SRCDIR "/connectivity/source/drivers/odbc/ODatabaseMetaDataResultSet.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/browser/dsEntriesNoExp.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/explode.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/filter/source/graphicfilter/ipict/ipict.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/core/data/dptabsrc.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/docsh3.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/dlg/masterlayoutdlg.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/ppt/pptinanimations.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/app/i18n_im.cxx")) return;
// callback if (loplugin::isSamePathname(fn, SRCDIR "/sax/source/expatwrap/sax_expat.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/xmlsecurity/source/xmlsec/xmlstreamio.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par2.cxx")) return; if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par5.cxx")) return; // SaxWriterHelper::writeSequence a little weird if (loplugin::isSamePathname(fn, SRCDIR "/sax/source/expatwrap/saxwriter.cxx")) return; // main function if (loplugin::isSamePathname(fn, SRCDIR "/xmlsecurity/workben/pdfverify.cxx")) return;
for (auto functionDecl : problemFunctions)
{ auto canonicalDecl = functionDecl->getCanonicalDecl(); if (getFunctionsWithAddressTaken().find(canonicalDecl)
!= getFunctionsWithAddressTaken().end()) continue;
report(DiagnosticsEngine::Warning, "only returning one or zero is an indication you want to return bool",
functionDecl->getBeginLoc())
<< functionDecl->getSourceRange(); if (canonicalDecl->getLocation() != functionDecl->getLocation())
{
report(DiagnosticsEngine::Note, "canonical function declaration here",
canonicalDecl->getBeginLoc())
<< canonicalDecl->getSourceRange();
}
}
}
bool ShouldReturnBool::TraverseFunctionDecl(FunctionDecl* functionDecl)
{ bool ret; if (IsInteresting(functionDecl))
{
mbInsideFunction = true;
mbFunctionOnlyReturningOneOrZero = true;
ret = FunctionAddress::TraverseFunctionDecl(functionDecl);
mbInsideFunction = false; if (mbFunctionOnlyReturningOneOrZero)
problemFunctions.insert(functionDecl);
} else
ret = FunctionAddress::TraverseFunctionDecl(functionDecl); return ret;
}
bool ShouldReturnBool::TraverseCXXMethodDecl(CXXMethodDecl* methodDecl)
{ bool ret; if (IsInteresting(methodDecl))
{
mbInsideFunction = true;
mbFunctionOnlyReturningOneOrZero = true;
ret = FunctionAddress::TraverseCXXMethodDecl(methodDecl);
mbInsideFunction = false; if (mbFunctionOnlyReturningOneOrZero)
problemFunctions.insert(methodDecl);
} else
ret = FunctionAddress::TraverseCXXMethodDecl(methodDecl); return ret;
}
bool ShouldReturnBool::IsInteresting(FunctionDecl const* functionDecl)
{ if (ignoreLocation(functionDecl)) returnfalse; // ignore stuff that forms part of the stable URE interface if (isInUnoIncludeFile(functionDecl)) returnfalse; if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) returnfalse; if (!functionDecl->isThisDeclarationADefinition()) returnfalse; if (functionDecl->isMain()) returnfalse; if (functionDecl->isExternC() || functionDecl->isInExternCContext()) returnfalse; auto methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); if (methodDecl && methodDecl->isVirtual()) returnfalse; auto tc = loplugin::TypeCheck(functionDecl->getReturnType()); if (tc.AnyBoolean() || tc.Void()) returnfalse; auto returnType = functionDecl->getReturnType(); if (returnType->isEnumeralType() || !returnType->getUnqualifiedDesugaredType()->isIntegerType()) returnfalse; // Ignore functions that contains #ifdef-ery if (containsPreprocessingConditionalInclusion(functionDecl->getSourceRange())) returnfalse;
// not sure what basegfx is doing here
StringRef fileName{ getFilenameOfLocation(functionDecl->getLocation()) }; if (loplugin::isSamePathname(fileName, SRCDIR "/include/basegfx/range/basicrange.hxx")) returnfalse; // false + if (loplugin::isSamePathname(fileName, SRCDIR "/include/svl/macitem.hxx")) returnfalse; if (loplugin::isSamePathname(fileName, SRCDIR "/lotuswordpro/source/filter/lwpcharsetmgr.hxx")) returnfalse; if (loplugin::isSamePathname(fileName, SRCDIR "/sc/inc/dptabsrc.hxx")) returnfalse;
returntrue;
}
bool ShouldReturnBool::VisitReturnStmt(const ReturnStmt* returnStmt)
{ if (!mbInsideFunction) returntrue; if (!returnStmt->getRetValue()) returntrue; if (loplugin::TypeCheck(returnStmt->getRetValue()->getType()).AnyBoolean()) returntrue; if (!isExprOneOrZero(returnStmt->getRetValue()))
mbFunctionOnlyReturningOneOrZero = false; returntrue;
}
bool ShouldReturnBool::isExprOneOrZero(const Expr* arg) const
{
arg = arg->IgnoreParenCasts(); // ignore this, it seems to trigger an infinite recursion if (isa<UnaryExprOrTypeTraitExpr>(arg))
{ returnfalse;
}
APSInt x1; if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext()))
{ return x1 == 1 || x1 == 0;
} returnfalse;
}
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.