// Find classes that derive from css::uno::XAggregation, but which implement queryInterface in // violation of the protocol laid out in the documentation at // udkapi/com/sun/star/uno/XAggregation.idl (which implies that such a class either doesn't actually // make use of the deprecated XAggregation mechanism, which should thus be removed from that class // hierarchy, or that its implementation of queryInterface needs to be fixed).
// Return true if decl is an implementation of css::uno::XInterface::queryInterface in a class // derived from css::uno::XAggregation: bool isXAggregationQueryInterface(CXXMethodDecl const* decl)
{ return isQueryInterface(decl) && derivesFromXAggregation(decl->getParent(), false);
}
bool basesHaveOnlyPureQueryInterface(CXXRecordDecl const* decl)
{ for (autoconst& b : decl->bases())
{ autoconst d1 = b.getType()->getAsCXXRecordDecl(); if (!derivesFromXAggregation(d1, true))
{ continue;
} for (autoconst d2 : d1->methods())
{ if (!isQueryInterface(d2))
{ continue;
} if (!compat::isPureVirtual(d2))
{ returnfalse;
}
} if (!basesHaveOnlyPureQueryInterface(d1))
{ returnfalse;
}
} returntrue;
}
class UnoAggregation final : public loplugin::FilteringPlugin<UnoAggregation>
{ public: explicit UnoAggregation(loplugin::InstantiationData const& data)
: FilteringPlugin(data)
{
}
void run() override
{ if (preRun())
{
TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
}
}
bool VisitCXXMethodDecl(CXXMethodDecl const* decl)
{ if (ignoreLocation(decl))
{ returntrue;
} if (!decl->isThisDeclarationADefinition())
{ returntrue;
} autoconst parent = decl->getParent(); if (parent->getDescribedClassTemplate() != nullptr)
{ // For class templates with dependent base classes, loplugin::isDerivedFrom as used in // isXAggregationQueryInterface would always return true; work around that by not // looking at any templates at all, which is OK due to // shouldVisitTemplateInstantiations: returntrue;
} if (!isXAggregationQueryInterface(decl))
{ returntrue;
} if (decl->isDeleted())
{ // Whether or not a deleted queryInterface makes sense, just leave those alone: returntrue;
} autoconst body = decl->getBody();
assert(body != nullptr); // Check whether the implementation forwards to one of the base classes that derive from // XAggregation: if (autoconst s1 = dyn_cast<CompoundStmt>(body))
{ if (s1->size() == 1)
{ if (autoconst s2 = dyn_cast<ReturnStmt>(s1->body_front()))
{ if (autoconst e1 = s2->getRetValue())
{ if (autoconst e2
= dyn_cast<CXXMemberCallExpr>(e1->IgnoreImplicit()->IgnoreParens()))
{ returntrue; if (e2->getImplicitObjectArgument() == nullptr)
{ if (isXAggregationQueryInterface(e2->getMethodDecl()))
{ // e2 will thus necessarily be a call of a base class's // queryInterface (or a recursive call of the given decl itself, // but which would cause the code to have undefined behavior // anyway, so don't bother to rule that out): returntrue;
}
}
}
} elseif (isDebugMode())
{
report(DiagnosticsEngine::Warning, "suspicious implementation of queryInterface containing a return " "statement with no operand",
decl->getLocation())
<< decl->getSourceRange();
}
}
}
} // As a crude approximation (but which appears to work OK), if all of the base classes that // derive from XAggregation only ever declare queryInterface as pure, assume that this is // the base implementation of queryInterface (which will necessarily not match the above // check for a forwarding implementation): if (basesHaveOnlyPureQueryInterface(parent))
{ returntrue;
} if (suppressWarningAt(decl->getBeginLoc()))
{ returntrue;
}
report(DiagnosticsEngine::Warning, "%0 derives from XAggregation, but its implementation of queryInterface does not " "delegate to an appropriate base class queryInterface",
decl->getLocation())
<< parent << decl->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.