in src/checks/manuallevel/unneeded-cast.cpp [84:130]
bool UnneededCast::handleNamedCast(CXXNamedCastExpr *namedCast)
{
if (!namedCast) {
return false;
}
const bool isDynamicCast = isa<CXXDynamicCastExpr>(namedCast);
const bool isStaticCast = isDynamicCast ? false : isa<CXXStaticCastExpr>(namedCast);
if (!isDynamicCast && !isStaticCast) {
return false;
}
if (namedCast->getBeginLoc().isMacroID()) {
return false;
}
CXXRecordDecl *castFrom = namedCast ? Utils::namedCastInnerDecl(namedCast) : nullptr;
if (!castFrom || !castFrom->hasDefinition() || std::distance(castFrom->bases_begin(), castFrom->bases_end()) > 1) {
return false;
}
if (isStaticCast) {
if (auto *implicitCast = dyn_cast<ImplicitCastExpr>(namedCast->getSubExpr())) {
if (implicitCast->getCastKind() == CK_NullToPointer) {
// static_cast<Foo*>(0) is OK, and sometimes needed
return false;
}
}
// static_cast to base is needed in ternary operators
if (clazy::getFirstParentOfType<ConditionalOperator>(m_context->parentMap, namedCast) != nullptr) {
return false;
}
}
if (isDynamicCast && !isOptionSet("prefer-dynamic-cast-over-qobject") && clazy::isQObject(castFrom)) {
emitWarning(namedCast->getBeginLoc(), "Use qobject_cast rather than dynamic_cast");
}
CXXRecordDecl *castTo = Utils::namedCastOuterDecl(namedCast);
if (!castTo) {
return false;
}
return maybeWarn(namedCast, castFrom, castTo);
}