void CheckUnusedParams::run()
{
StringRef fn(handler.getMainFileName()); if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/")) return; // Taking pointer to function if (loplugin::isSamePathname(fn, SRCDIR "/l10ntools/source/xmlparse.cxx")) return; // macro magic which declares something needed by an external library if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/misc/gridprinter.cxx")) return;
// valid test/qa code if (loplugin::hasPathnamePrefix(fn, SRCDIR "/compilerplugins/clang/test/")) return; if (loplugin::isSamePathname(fn, SRCDIR "/cppu/qa/test_reference.cxx")) return;
// leave this alone for now if (loplugin::hasPathnamePrefix(fn, SRCDIR "/libreofficekit/")) return; // this has a certain pattern to its code which appears to include lots of unused params if (loplugin::hasPathnamePrefix(fn, SRCDIR "/xmloff/")) return; // I believe someone is busy working on this chunk of code if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/dataprovider.cxx")) return; // I think erack is working on stuff here if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xiformula.cxx")) return; // lots of callbacks here if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/lotus/op.cxx")) return; // template magic if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/html/htmlpars.cxx")) return;
bool CheckUnusedParams::VisitCallExpr(CallExpr const * callExpr) { if (m_phase != PluginPhase::FindAddressOf) returntrue; for (auto arg : callExpr->arguments())
checkForFunctionDecl(arg); returntrue;
}
bool CheckUnusedParams::VisitCXXConstructExpr(CXXConstructExpr const * constructExpr) { if (m_phase != PluginPhase::FindAddressOf) returntrue; for (auto arg : constructExpr->arguments())
checkForFunctionDecl(arg); returntrue;
}
bool CheckUnusedParams::VisitInitListExpr(InitListExpr const * initListExpr) { if (m_phase != PluginPhase::FindAddressOf) returntrue; for (auto subStmt : *initListExpr)
checkForFunctionDecl(dyn_cast<Expr>(subStmt)); returntrue;
}
void CheckUnusedParams::checkForFunctionDecl(Expr const * expr, bool bCheckOnly) { auto e1 = expr->IgnoreParenCasts(); auto declRef = dyn_cast<DeclRefExpr>(e1); if (!declRef) return; auto functionDecl = dyn_cast<FunctionDecl>(declRef->getDecl()); if (!functionDecl) return; if (bCheckOnly)
getParentStmt(expr)->dump(); else
m_addressOfSet.insert(functionDecl->getCanonicalDecl());
}
staticint noFieldsInRecord(RecordType const * recordType) { auto recordDecl = recordType->getDecl(); // if it's complicated, let's just assume it has fields if (isa<ClassTemplateSpecializationDecl>(recordDecl)) return1; return std::distance(recordDecl->field_begin(), recordDecl->field_end());
} staticbool startswith(const std::string& rStr, constchar* pSubStr) { return rStr.compare(0, strlen(pSubStr), pSubStr) == 0;
} staticbool endswith(const std::string& rStr, constchar* pSubStr) { auto len = strlen(pSubStr); if (len > rStr.size()) returnfalse; return rStr.compare(rStr.size() - len, rStr.size(), pSubStr) == 0;
}
bool CheckUnusedParams::VisitFunctionDecl(FunctionDecl const * decl) { if (m_phase != PluginPhase::Warning) returntrue; if (m_addressOfSet.find(decl->getCanonicalDecl()) != m_addressOfSet.end()) returntrue; if (ignoreLocation(decl)) returntrue; if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) returntrue;
auto cxxMethodDecl = dyn_cast<CXXMethodDecl>(decl); if (cxxMethodDecl) { if (cxxMethodDecl->isVirtual()) returntrue; auto cxxConstructorDecl = dyn_cast<CXXConstructorDecl>(cxxMethodDecl); if (cxxConstructorDecl && cxxConstructorDecl->isCopyOrMoveConstructor()) returntrue;
} if (!decl->isThisDeclarationADefinition()) returntrue; if (decl->isFunctionTemplateSpecialization()) returntrue; if (decl->isDeleted()) returntrue; if (decl->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate) returntrue; if (decl->isOverloadedOperator()) returntrue; if (decl->isExternC()) returntrue;
//TODO, filtering out any functions relating to class templates for now:
CXXRecordDecl const * r = dyn_cast<CXXRecordDecl>(decl->getDeclContext()); if (r != nullptr
&& (r->getTemplateSpecializationKind() != TSK_Undeclared
|| r->isDependentContext()))
{ returntrue;
}
FunctionDecl const * canon = decl->getCanonicalDecl();
std::string fqn = canon->getQualifiedNameAsString(); // because sometimes clang returns nonsense for the filename of canon if (ignoreLocation(canon)) returntrue; if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(canon->getLocation()))) returntrue;
StringRef fn = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(canon->getBeginLoc())); // Some backwards compat magic. // TODO Can probably be removed, but need to do some checking if (loplugin::isSamePathname(fn, SRCDIR "/include/sax/fshelper.hxx")) returntrue; // Platform-specific code if (loplugin::isSamePathname(fn, SRCDIR "/include/svl/svdde.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/svmain.hxx")) returntrue; // passing pointer to function if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/BitmapReadAccess.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtkobject.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtksalframe.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtkframe.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/extensions/source/propctrlr/propertyeditor.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/solar/inc/navtoolbar.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/grammar.cxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/lexer.cxx")) returntrue; // marked with a TODO/FIXME if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/sallayout.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/accessibility/inc/standard/vclxaccessiblelist.hxx")) returntrue; // these are "extern C" but clang doesn't seem to report that accurately if (loplugin::isSamePathname(fn, SRCDIR "/sax/source/fastparser/fastparser.cxx")) returntrue; // these all follow the same pattern, seems a pity to break that if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/graphicfilter.hxx")) returntrue; // looks like work in progress if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/ipdf/pdfdocument.cxx")) returntrue; // macro magic if (loplugin::isSamePathname(fn, SRCDIR "/basctl/source/inc/basidesh.hxx")) returntrue; // template magic if (loplugin::hasPathnamePrefix(fn, SRCDIR "/canvas/")) returntrue; if (loplugin::hasPathnamePrefix(fn, SRCDIR "/include/canvas/")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/include/comphelper/unwrapargs.hxx")) returntrue; // this looks like vaguely useful code (ParseError) that I'm loathe to remove if (loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/inc/RowFunctionParser.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/include/svx/EnhancedCustomShapeFunctionParser.hxx")) returntrue; // TODO marker parameter in constructor, should probably be using an enum if (loplugin::isSamePathname(fn, SRCDIR "/framework/inc/uielement/uicommanddescription.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/SlideTransitionPane.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/animations/CustomAnimationPane.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/table/TableDesignPane.hxx")) returntrue; // debug stuff if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/core/data/column2.cxx")) returntrue; // weird stuff if (loplugin::isSamePathname(fn, SRCDIR "/scaddins/source/analysis/analysishelper.hxx")) returntrue; // SFX_DECL_CHILDWINDOWCONTEXT macro stuff if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/NavigatorChildWindow.hxx")) returntrue; // TODO, need to remove this from the .sdi file too if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/SlideSorterViewShell.hxx")) returntrue; if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/OutlineViewShell.hxx")) returntrue; // SFX_DECL_INTERFACE macro stuff if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/ViewShellBase.hxx")) returntrue; // debug stuff if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/ppt/pptinanimations.hxx")) returntrue; // takes pointer to fn if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/shell.hxx")) returntrue; // TODO, need to remove this from the .sdi file too if (fqn == "SfxObjectShell::StateView_Impl") returntrue; // SFX_DECL_CHILDWINDOW_WITHID macro if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/infobar.hxx")) returntrue; // this looks like vaguely useful code (ParseError) that I'm loathe to remove if (loplugin::isSamePathname(fn, SRCDIR "/slideshow/source/inc/slideshowexceptions.hxx")) returntrue; // SFX_DECL_VIEWFACTORY macro if (loplugin::isSamePathname(fn, SRCDIR "/starmath/inc/view.hxx")) returntrue; // debugging if (fqn == "BrowseBox::DoShowCursor" || fqn == "BrowseBox::DoHideCursor") returntrue; // if I change this one, it then overrides a superclass virtual method if (fqn == "GalleryBrowser2::KeyInput") returntrue; // takes pointer to function if (fqn == "cmis::AuthProvider::onedriveAuthCodeFallback" || fqn == "cmis::AuthProvider::gdriveAuthCodeFallback") returntrue; if (fqn == "ooo_mount_operation_ask_password") returntrue; // TODO tricky to remove because of default params if (fqn == "xmloff::OAttribute2Property::addBooleanProperty") returntrue; // taking pointer to function if (fqn == "sw::DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl"
|| fqn == "sw::DocumentContentOperationsManager::DeleteRangeImpl"
|| fqn == "SwTableFormula::GetFormulaBoxes"
|| fqn == "SwFEShell::Drag"
|| fqn == "GetASCWriter" || fqn == "GetHTMLWriter" || fqn == "GetXMLWriter"
|| fqn == "SwWrtShell::UpdateLayoutFrame" || fqn == "SwWrtShell::DefaultDrag"
|| fqn == "SwWrtShell::DefaultEndDrag"
|| startswith(fqn, "SwWW8ImplReader::Read_")) returntrue; // WIN32 only if (fqn == "SwFntObj::GuessLeading") returntrue; // SFX_DECL_CHILDWINDOW_WITHID macro if (fqn == "SwSpellDialogChildWindow::SwSpellDialogChildWindow"
|| fqn == "SwFieldDlgWrapper::SwFieldDlgWrapper"
|| fqn == "SwInputChild::SwInputChild") returntrue; // SFX_DECL_VIEWFACTORY macro if (fqn == "SwSrcView::SwSrcView") returntrue; // Serves to disambiguate two very similar methods if (fqn == "MSWordStyles::BuildGetSlot") returntrue; // TODO there are just too many default params to make this worth fixing right now if (fqn == "ScDocument::CopyMultiRangeFromClip") returntrue; // TODO looks like this needs fixing? if (fqn == "ScTable::ExtendPrintArea") returntrue; // there is a FIXME in the code if (fqn == "ScRangeUtil::IsAbsTabArea") returntrue; // SFX_DECL_CHILDWINDOW_WITHID if (fqn == "ScInputWindowWrapper::ScInputWindowWrapper"
|| fqn == "sc::SearchResultsDlgWrapper::SearchResultsDlgWrapper") returntrue; // ExecMethod in .sdi file if (fqn == "ScChartShell::ExecuteExportAsGraphic") returntrue; // bool marker parameter if (fqn == "SvxIconReplacementDialog::SvxIconReplacementDialog") returntrue; // used as pointer to fn if (endswith(fqn, "_createInstance")) returntrue; // callback if (startswith(fqn, "SbRtl_")) returntrue; // takes pointer to fn if (fqn == "migration::BasicMigration_create" || fqn == "migration::WordbookMigration_create"
|| fqn == "comp_CBlankNode::_create" || fqn == "comp_CURI::_create"
|| fqn == "comp_CLiteral::_create" || fqn == "CDocumentBuilder::_getInstance"
|| fqn == "DOM::CDocumentBuilder::_getInstance"
|| fqn == "xml_security::serial_number_adapter::create"
|| fqn == "desktop::splash::create" || fqn == "ScannerManager_CreateInstance"
|| fqn == "formula::FormulaOpCodeMapperObj::create"
|| fqn == "(anonymous namespace)::createInstance"
|| fqn == "x_error_handler"
|| fqn == "warning_func"
|| fqn == "error_func"
|| fqn == "ScaDateAddIn_CreateInstance"
|| fqn == "ScaPricingAddIn_CreateInstance"
|| fqn == "(anonymous namespace)::PDFSigningPKCS7PasswordCallback"
|| fqn == "ContextMenuEventLink"
|| fqn == "DelayedCloseEventLink"
|| fqn == "GDIMetaFile::ImplColMonoFnc"
|| fqn == "vcl::getGlyph0"
|| fqn == "vcl::getGlyph6"
|| fqn == "vcl::getGlyph12"
|| fqn == "setPasswordCallback"
|| fqn == "VCLExceptionSignal_impl"
|| fqn == "getFontTable"
|| fqn == "textconversiondlgs::ChineseTranslation_UnoDialog::create"
|| fqn == "pcr::DefaultHelpProvider::Create"
|| fqn == "pcr::DefaultFormComponentInspectorModel::Create"
|| fqn == "pcr::ObjectInspectorModel::Create"
|| fqn == "GraphicExportFilter::GraphicExportFilter"
|| fqn == "CertificateContainer::CertificateContainer"
|| startswith(fqn, "ParseCSS1_")
) returntrue; // TODO if (fqn == "FontSubsetInfo::CreateFontSubsetFromType1") returntrue; // used in template magic if (fqn == "MtfRenderer::MtfRenderer" || fqn == "shell::sessioninstall::SyncDbusSessionHelper::SyncDbusSessionHelper"
|| fqn == "dp_gui::LicenseDialog::LicenseDialog"
|| fqn == "(anonymous namespace)::OGLTransitionFactoryImpl::OGLTransitionFactoryImpl") returntrue; // FIXME if (fqn == "GtkSalDisplay::filterGdkEvent" || fqn == "SvXMLEmbeddedObjectHelper::ImplReadObject"
|| fqn == "chart::CachedDataSequence::CachedDataSequence") returntrue; // used via macro if (fqn == "framework::MediaTypeDetectionHelper::MediaTypeDetectionHelper"
|| fqn == "framework::UriAbbreviation::UriAbbreviation"
|| fqn == "framework::DispatchDisabler::DispatchDisabler"
|| fqn == "framework::DispatchRecorderSupplier::DispatchRecorderSupplier") returntrue; // TODO Armin Le Grand is still working on this if (fqn == "svx::frame::CreateDiagFrameBorderPrimitives"
|| fqn == "svx::frame::CreateBorderPrimitives") returntrue; // marked with a TODO if (fqn == "pcr::FormLinkDialog::getExistingRelation"
|| fqn == "ooo::vba::DebugHelper::basicexception"
|| fqn == "ScPrintFunc::DrawToDev") returntrue; // macros at work if (fqn == "msfilter::lcl_PrintDigest") returntrue; // TODO something wrong here, the method that calls this (Normal::GenSlidingWindowFunction) cannot be correct if (fqn == "sc::opencl::OpBase::Gen") returntrue; // Can't change this without conflicting with another constructor with the same signature if (fqn == "XclExpSupbook::XclExpSupbook") returntrue; // ignore the LINK macros from include/tools/link.hxx if (decl->getLocation().isMacroID()) returntrue; // debug code in sw/ if (fqn == "lcl_dbg_out") returntrue;
for( auto it = decl->param_begin(); it != decl->param_end(); ++it) { auto param = *it; if (param->hasAttr<UnusedAttr>()) continue; if (!param->getName().empty()) continue; // ignore params which are enum types with only a single enumerator, these are marker/tag types auto paramType = param->getType(); if (paramType->isEnumeralType()) { auto enumType = paramType->getAs<EnumType>(); int cnt = std::distance(enumType->getDecl()->enumerator_begin(), enumType->getDecl()->enumerator_end()); if (cnt == 1) continue;
} // ignore params which are a reference to a struct which has no fields. // These are either // (a) marker/tag types // (b) selective "friend" access if (paramType->isReferenceType()) { auto referenceType = paramType->getAs<ReferenceType>(); if (referenceType->getPointeeType()->isRecordType()) { auto recordType = referenceType->getPointeeType()->getAs<RecordType>(); if (noFieldsInRecord(recordType) == 0) continue;
}
} elseif (paramType->isRecordType()) { if (noFieldsInRecord(paramType->getAs<RecordType>()) == 0) continue;
}
report( DiagnosticsEngine::Warning, "unused param %0 in %1", param->getBeginLoc())
<< param->getSourceRange()
<< param->getName()
<< fqn; if (canon != decl)
{ unsigned idx = param->getFunctionScopeIndex(); const ParmVarDecl* pOther = canon->getParamDecl(idx);
report( DiagnosticsEngine::Note, "declaration is here",
pOther->getBeginLoc())
<< pOther->getSourceRange();
}
} returntrue;
}
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.