bool TraverseFunctionDecl(FunctionDecl* decl)
{ bool ret = true; if (PreTraverseFunctionDecl(decl))
{
ret = FilteringPlugin::TraverseFunctionDecl(decl);
PostTraverseFunctionDecl(decl, ret);
} return ret;
}
bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr* expr)
{ if (ignoreLocation(expr))
{ returntrue;
} if (expr->getOperator() != OO_LessLess)
{ returntrue;
}
assert(expr->getNumArgs() == 2); if (!loplugin::TypeCheck(expr->getArg(0)->getType())
.ClassOrStruct("basic_ostream")
.StdNamespace()) //TODO: check template args
{ returntrue;
} autoconst arg1 = expr->getArg(1); autoconst e = dyn_cast<CXXMemberCallExpr>(arg1->IgnoreParenImpCasts()); if (e == nullptr)
{ returntrue;
} bool castToVoid = false; if (isa<ImplicitCastExpr>(arg1))
{ if (loplugin::TypeCheck(arg1->getType()).Pointer().Void())
{
castToVoid = true;
}
} autoconst t = e->getObjectType(); autoconst tc = loplugin::TypeCheck(t); if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace()
|| tc.Class("OUString").Namespace("rtl").GlobalNamespace()
|| (castToVoid
&& (tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()
|| tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()))))
{ returntrue;
} if (!loplugin::DeclCheck(e->getMethodDecl()).Function("getStr"))
{ returntrue;
} if (castToVoid)
{
report(DiagnosticsEngine::Warning,
("suspicious use of 'getStr' on an object of type %0; the result is implicitly" " cast to a void pointer in a call of 'operator <<'"),
e->getExprLoc())
<< t.getLocalUnqualifiedType() << expr->getSourceRange(); returntrue;
} if (!functions_.empty())
{ // Filter out occurrences of `s << t.getStr()` in the implementation of // `operator <<(std::basic_ostream<...> & s, T const & t)`: autoconst fd = functions_.top(); if (fd->getOverloadedOperator() == OO_LessLess)
{
assert(fd->getNumParams() == 2); if (loplugin::TypeCheck(fd->getParamDecl(0)->getType())
.LvalueReference()
.NonConstVolatile()
.TemplateSpecializationClass()
.ClassOrStruct("basic_ostream")
.StdNamespace()) //TODO: check template args
{ if (autoconst t2
= fd->getParamDecl(1)->getType()->getAs<LValueReferenceType>())
{ autoconst t3 = t2->getPointeeType(); if (t3.isConstQualified() && !t3.isVolatileQualified()
&& (t3.getCanonicalType().getTypePtr()
== t.getCanonicalType().getTypePtr()))
{ returntrue;
}
}
}
}
}
report(DiagnosticsEngine::Warning,
("directly use object of type %0 in a call of 'operator <<', instead of calling" " 'getStr' first"),
e->getExprLoc())
<< t.getLocalUnqualifiedType() << expr->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.