// try to limit the voluminous output a little static std::multimap<const FunctionDecl*, const FunctionDecl*> callMap; static std::set<MyFuncInfo> definitionSet;
class MethodCycles : public RecursiveASTVisitor<MethodCycles>, public loplugin::Plugin
{ public: explicit MethodCycles(loplugin::InstantiationData const& data)
: Plugin(data)
{
}
bool MethodCycles::isLocationMine(SourceLocation loc)
{
SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc(loc); if (compiler.getSourceManager().isInSystemHeader(expansionLoc)) returnfalse; constchar* bufferName = compiler.getSourceManager().getPresumedLoc(expansionLoc).getFilename(); if (bufferName == NULL) returnfalse; if (loplugin::hasPathnamePrefix(bufferName, WORKDIR "/")
|| loplugin::hasPathnamePrefix(bufferName, BUILDDIR "/")
|| loplugin::hasPathnamePrefix(bufferName, SRCDIR "/")) returntrue; // ok returnfalse;
}
void MethodCycles::logCallToRootMethods(const FunctionDecl* functionDeclFrom, const FunctionDecl* functionDeclTo)
{ if (!functionDeclFrom)
{ // template magic mostly, but also things called from initialisers return;
}
functionDeclFrom = functionDeclFrom->getCanonicalDecl();
functionDeclTo = functionDeclTo->getCanonicalDecl();
for (autoconst& from : fromRoots) for (autoconst& to : toRoots)
callMap.insert({ from, to });
}
void MethodCycles::findRoots(const FunctionDecl* functionDecl,
std::unordered_set<const FunctionDecl*>& roots)
{ bool bCalledSuperMethod = false; if (auto methodDecl = dyn_cast<CXXMethodDecl>(functionDecl))
{ // For virtual/overriding methods, we need to pretend we called from/to root method(s), // so that they get marked as used. for (auto it = methodDecl->begin_overridden_methods();
it != methodDecl->end_overridden_methods(); ++it)
{
findRoots(*it, roots);
bCalledSuperMethod = true;
}
} if (!bCalledSuperMethod)
{ while (functionDecl->getTemplateInstantiationPattern())
functionDecl = functionDecl->getTemplateInstantiationPattern(); if (functionDecl->getLocation().isValid())
roots.insert(functionDecl);
}
}
bool MethodCycles::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) // ignore recursive calls
logCallToRootMethods(currentFunctionDecl, calleeFunctionDecl);
returntrue;
}
bool MethodCycles::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
bool MethodCycles::VisitFunctionDecl(const FunctionDecl* functionDecl)
{ const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); if (functionDecl->isDeleted()) returntrue; // don't care about compiler-generated functions if (functionDecl->isImplicit()) returntrue; if (!canonicalFunctionDecl->getLocation().isValid()) 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 (!isLocationMine(canonicalFunctionDecl->getLocation())) 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.