/* -*- 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/.
*/
/** Look for virtual methods where we never call the defining virtual method, and only call the overriding virtual methods, which indicates a places where the virtual-ness is unwarranted, normally a result of premature abstraction.
The process goes something like this: $ make check $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='VirtualDown' check $ ./compilerplugins/clang/VirtualDown.py
@TODO for some reason, we get false+ for operator== methods @TODO some templates confuse it and we get false+
bool VirtualDown::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
{ if (ignoreLocation(methodDecl))
{ returntrue;
} if (!methodDecl->isThisDeclarationADefinition() || !methodDecl->isVirtual()
|| methodDecl->isDeleted())
{ returntrue;
}
methodDecl = methodDecl->getCanonicalDecl(); // ignore stuff that forms part of the stable URE interface if (isInUnoIncludeFile(methodDecl))
{ returntrue;
}
std::string aNiceName = niceName(methodDecl);
if (isa<CXXDestructorDecl>(methodDecl)) returntrue; if (isa<CXXConstructorDecl>(methodDecl)) returntrue;
if (methodDecl->size_overridden_methods() == 0)
definitionSet.insert({ aNiceName, toString(methodDecl->getLocation()) });
returntrue;
}
bool VirtualDown::VisitCXXMemberCallExpr(CXXMemberCallExpr const* 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 const* calleeFunctionDecl = expr->getDirectCallee(); if (calleeFunctionDecl == nullptr)
{
Expr const* callee = expr->getCallee()->IgnoreParenImpCasts();
DeclRefExpr const* dr = dyn_cast<DeclRefExpr>(callee); if (dr)
{
calleeFunctionDecl = dyn_cast<FunctionDecl>(dr->getDecl()); if (calleeFunctionDecl) goto gotfunc;
} returntrue;
}
gotfunc:
// ignore recursive calls if (currentFunctionDecl == calleeFunctionDecl) returntrue;
auto cxxMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl); if (!cxxMethodDecl) returntrue;
while (cxxMethodDecl->getTemplateInstantiationPattern())
cxxMethodDecl = dyn_cast<CXXMethodDecl>(cxxMethodDecl->getTemplateInstantiationPattern()); while (cxxMethodDecl->getInstantiatedFromMemberFunction())
cxxMethodDecl = dyn_cast<CXXMethodDecl>(cxxMethodDecl->getInstantiatedFromMemberFunction()); if (cxxMethodDecl->getLocation().isValid() && !ignoreLocation(cxxMethodDecl))
callSet.insert(niceName(cxxMethodDecl));
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.