// for the "unused method" analysis static std::set<MyFuncInfo> callSet; static std::set<MyFuncInfo> definitionSet; // for the "unused return type" analysis static std::set<MyFuncInfo> usedReturnSet; // for the "can be private" analysis static std::set<MyFuncInfo> calledFromOutsideSet;
class UnusedMethods: public RecursiveASTVisitor<UnusedMethods>, public loplugin::Plugin
{ public: explicit UnusedMethods(loplugin::InstantiationData const & data):
Plugin(data) {}
// For virtual/overriding methods, we need to pretend we called the root method(s), // so that they get marked as used. void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl, std::set<MyFuncInfo>& funcSet)
{
functionDecl = functionDecl->getCanonicalDecl(); bool bCalledSuperMethod = false; if (isa<CXXMethodDecl>(functionDecl)) { const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); for(CXXMethodDecl::method_iterator it = methodDecl->begin_overridden_methods();
it != methodDecl->end_overridden_methods(); ++it)
{
logCallToRootMethods(*it, funcSet);
bCalledSuperMethod = true;
}
} if (!bCalledSuperMethod)
{ while (functionDecl->getTemplateInstantiationPattern())
functionDecl = functionDecl->getTemplateInstantiationPattern(); if (functionDecl->getLocation().isValid() && !ignoreLocation( functionDecl->getBeginLoc() )
&& !functionDecl->isExternC())
funcSet.insert(niceName(functionDecl));
}
}
bool UnusedMethods::VisitCallExpr(CallExpr* expr)
{ // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result // from template instantiation deep inside the STL and other external code
FunctionDecl* calleeFunctionDecl = expr->getDirectCallee(); if (calleeFunctionDecl == nullptr) {
Expr* callee = expr->getCallee()->IgnoreParenImpCasts();
DeclRefExpr* dr = dyn_cast<DeclRefExpr>(callee); if (dr) {
calleeFunctionDecl = dyn_cast<FunctionDecl>(dr->getDecl()); if (calleeFunctionDecl) goto gotfunc;
} returntrue;
}
gotfunc:
if (currentFunctionDecl == calleeFunctionDecl)
; // for "unused method" analysis, ignore recursive calls elseif (currentFunctionDecl
&& currentFunctionDecl->getIdentifier()
&& currentFunctionDecl->getName() == "Clone"
&& currentFunctionDecl->getParent() == calleeFunctionDecl->getParent()
&& isa<CXXConstructorDecl>(calleeFunctionDecl))
; // if we are inside Clone(), ignore calls to the same class's constructor else
logCallToRootMethods(calleeFunctionDecl, callSet);
const Stmt* parent = getParentStmt(expr);
// Now do the checks necessary for the "can be private" analysis
CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl); if (calleeMethodDecl && calleeMethodDecl->getAccess() != AS_private)
{ const FunctionDecl* parentFunctionOfCallSite = getParentFunctionDecl(expr); if (parentFunctionOfCallSite != calleeFunctionDecl) { if (!parentFunctionOfCallSite || !ignoreLocation(parentFunctionOfCallSite->getBeginLoc())) {
calledFromOutsideSet.insert(niceName(calleeFunctionDecl));
}
}
}
// Now do the checks necessary for the "unused return value" analysis if (calleeFunctionDecl->getReturnType()->isVoidType()) { returntrue;
} if (!parent) { // we will get null parent if it's under a CXXConstructExpr node
logCallToRootMethods(calleeFunctionDecl, usedReturnSet); returntrue;
} if (auto attributedStmt = dyn_cast<AttributedStmt>(parent))
parent = attributedStmt->getSubStmt(); if (isa<Expr>(parent) || isa<ReturnStmt>(parent) || isa<DeclStmt>(parent)
|| isa<IfStmt>(parent) || isa<SwitchStmt>(parent) || isa<ForStmt>(parent)
|| isa<WhileStmt>(parent) || isa<DoStmt>(parent)
|| isa<CXXForRangeStmt>(parent))
{
logCallToRootMethods(calleeFunctionDecl, usedReturnSet); returntrue;
} if (isa<CompoundStmt>(parent) || isa<DefaultStmt>(parent) || isa<CaseStmt>(parent)
|| isa<LabelStmt>(parent))
{ returntrue;
}
report(
DiagnosticsEngine::Warning, "unknown parent?",
parent->getBeginLoc());
parent->dump(); returntrue;
}
bool UnusedMethods::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr )
{ // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result // from template instantiation deep inside the STL and other external code
if (!constructorDecl->getLocation().isValid() || ignoreLocation(constructorDecl->getBeginLoc())) { returntrue;
}
logCallToRootMethods(constructorDecl, callSet);
// Now do the checks necessary for the "can be private" analysis if (constructorDecl->getParent() != currentCxxRecordDecl)
calledFromOutsideSet.insert(niceName(constructorDecl));
returntrue;
}
bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl )
{ // ignore stuff that forms part of the stable URE interface if (isInUnoIncludeFile(functionDecl)) { returntrue;
} const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); if (isa<CXXDestructorDecl>(functionDecl)) { returntrue;
} if (functionDecl->isDeleted() || functionDecl->isDefaulted()) { returntrue;
} if (isa<CXXConstructorDecl>(functionDecl)
&& dyn_cast<CXXConstructorDecl>(functionDecl)->isCopyOrMoveConstructor())
{ returntrue;
} if (!canonicalFunctionDecl->getLocation().isValid() || ignoreLocation(canonicalFunctionDecl->getBeginLoc())) { returntrue;
} // ignore method overrides, since the call will show up as being directed to the root method const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); if (methodDecl && (methodDecl->size_overridden_methods() != 0 || methodDecl->hasAttr<OverrideAttr>())) { returntrue;
} if (!functionDecl->isExternC()) {
MyFuncInfo funcInfo = niceName(canonicalFunctionDecl);
definitionSet.insert(funcInfo);
} returntrue;
}
// Now do the checks necessary for the "can be private" analysis const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); if (methodDecl && methodDecl->getAccess() != AS_private)
{ const FunctionDecl* parentFunctionOfCallSite = getParentFunctionDecl(declRefExpr); if (parentFunctionOfCallSite != functionDecl) { if (!parentFunctionOfCallSite || !ignoreLocation(parentFunctionOfCallSite->getBeginLoc())) {
calledFromOutsideSet.insert(niceName(functionDecl));
}
}
}
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.