staticbool isAssignmentOp(clang::BinaryOperatorKind op)
{ // We ignore BO_ShrAssign i.e. >>= because we use that everywhere for // extracting data from css::uno::Any return op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign || op == BO_RemAssign
|| op == BO_AddAssign || op == BO_SubAssign || op == BO_ShlAssign || op == BO_AndAssign
|| op == BO_XorAssign || op == BO_OrAssign;
}
staticbool isAssignmentOp(clang::OverloadedOperatorKind Opc)
{ // Same logic as CXXOperatorCallExpr::isAssignmentOp(), which our supported clang // doesn't have yet. // Except that we ignore OO_GreaterGreaterEqual i.e. >>= because we use that everywhere for // extracting data from css::uno::Any return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual || Opc == OO_PercentEqual
|| Opc == OO_PlusEqual || Opc == OO_MinusEqual || Opc == OO_LessLessEqual
|| Opc == OO_AmpEqual || Opc == OO_CaretEqual || Opc == OO_PipeEqual;
}
bool BuriedAssign::VisitBinaryOperator(BinaryOperator const* binaryOp)
{ if (ignoreLocation(binaryOp)) returntrue; if (binaryOp->getBeginLoc().isMacroID()) returntrue; if (!isAssignmentOp(binaryOp->getOpcode())) returntrue; auto expr = IgnoreImplicitAndConversionOperator(binaryOp->getRHS()); if (auto rhs = dyn_cast<BinaryOperator>(expr))
{ // Ignore chained assignment. // TODO limit this to only ordinary assignment if (isAssignmentOp(rhs->getOpcode()))
m_handled.insert(rhs);
} elseif (auto rhs = dyn_cast<CXXOperatorCallExpr>(expr))
{ // Ignore chained assignment. // TODO limit this to only ordinary assignment if (isAssignmentOp(rhs->getOperator()))
m_handled.insert(rhs);
} elseif (auto cxxConstruct = dyn_cast<CXXConstructExpr>(expr))
{ if (cxxConstruct->getNumArgs() == 1)
MarkIfAssignment(cxxConstruct->getArg(0));
} if (!m_handled.insert(binaryOp).second) returntrue;
// assignment in constructor
StringRef aFileName = getFilenameOfLocation(
compiler.getSourceManager().getSpellingLoc(binaryOp->getBeginLoc())); if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/comphelper/flagguard.hxx")) returntrue;
report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line",
binaryOp->getBeginLoc())
<< binaryOp->getSourceRange(); //getParentStmt(getParentStmt(getParentStmt(getParentStmt(getParentStmt(getParentStmt(binaryOp))))))->dump(); returntrue;
}
bool BuriedAssign::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOper)
{ if (ignoreLocation(cxxOper)) returntrue; if (cxxOper->getBeginLoc().isMacroID()) returntrue; if (!isAssignmentOp(cxxOper->getOperator())) returntrue; auto expr = IgnoreImplicitAndConversionOperator(cxxOper->getArg(1)); if (auto rhs = dyn_cast<BinaryOperator>(expr))
{ // Ignore chained assignment. // TODO limit this to only ordinary assignment if (isAssignmentOp(rhs->getOpcode()))
m_handled.insert(rhs);
} elseif (auto rhs = dyn_cast<CXXOperatorCallExpr>(expr))
{ // Ignore chained assignment. // TODO limit this to only ordinary assignment if (isAssignmentOp(rhs->getOperator()))
m_handled.insert(rhs);
} elseif (auto cxxConstruct = dyn_cast<CXXConstructExpr>(expr))
{ if (cxxConstruct->getNumArgs() == 1)
MarkIfAssignment(cxxConstruct->getArg(0));
} if (!m_handled.insert(cxxOper).second) returntrue;
report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line",
cxxOper->getBeginLoc())
<< cxxOper->getSourceRange(); //getParentStmt(getParentStmt(getParentStmt(getParentStmt(getParentStmt(cxxOper)))))->dump(); returntrue;
}
bool BuriedAssign::VisitCompoundStmt(CompoundStmt const* compoundStmt)
{ if (ignoreLocation(compoundStmt)) returntrue; for (auto i = compoundStmt->child_begin(); i != compoundStmt->child_end(); ++i)
{ if (auto expr = dyn_cast<Expr>(*i))
{
expr = expr->IgnoreImplicit(); if (auto binaryOp = dyn_cast<BinaryOperator>(expr))
{ // ignore comma-chained statements at this level if (binaryOp->getOpcode() == BO_Comma)
{
MarkIfAssignment(binaryOp->getLHS());
MarkIfAssignment(binaryOp->getRHS()); continue;
}
}
MarkIfAssignment(expr);
}
} returntrue;
}
void BuriedAssign::MarkIfAssignment(Stmt const* stmt)
{ if (auto expr = dyn_cast_or_null<Expr>(stmt))
{
expr = expr->IgnoreImplicit(); if (auto binaryOp = dyn_cast<BinaryOperator>(expr))
{ if (isAssignmentOp(binaryOp->getOpcode()))
{
m_handled.insert(expr);
MarkIfAssignment(binaryOp->getRHS()); // in case it is chained
} elseif (binaryOp->getOpcode() == BO_Comma)
{
MarkIfAssignment(binaryOp->getLHS());
MarkIfAssignment(binaryOp->getRHS());
}
} elseif (auto cxxOper = dyn_cast<CXXOperatorCallExpr>(expr))
{ if (isAssignmentOp(cxxOper->getOperator()))
{
m_handled.insert(expr);
MarkIfAssignment(cxxOper->getArg(1)); // in case it is chained
}
}
}
}
void BuriedAssign::MarkAll(Stmt const* stmt)
{
m_handled.insert(stmt); for (auto it = stmt->child_begin(); it != stmt->child_end(); ++it)
MarkAll(*it);
}
if (auto binaryOp = dyn_cast<BinaryOperator>(expr))
{ if (isAssignmentOp(binaryOp->getOpcode()))
{
report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line",
expr->getBeginLoc())
<< expr->getSourceRange();
} elseif (binaryOp->isComparisonOp())
{ if (auto binaryOp2
= dyn_cast<BinaryOperator>(binaryOp->getLHS()->IgnoreParenImpCasts()))
{ if (!binaryOp->getRHS()->isValueDependent()
&& binaryOp->getRHS()->isCXX11ConstantExpr(compiler.getASTContext())
&& isAssignmentOp(binaryOp2->getOpcode()))
report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line",
expr->getBeginLoc())
<< expr->getSourceRange();
} if (auto binaryOp2
= dyn_cast<BinaryOperator>(binaryOp->getRHS()->IgnoreParenImpCasts()))
{ if (!binaryOp->getLHS()->isValueDependent()
&& binaryOp->getLHS()->isCXX11ConstantExpr(compiler.getASTContext())
&& isAssignmentOp(binaryOp2->getOpcode()))
report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line",
expr->getBeginLoc())
<< expr->getSourceRange();
}
} elseif (binaryOp->isLogicalOp())
{ if (auto binaryOp2
= dyn_cast<BinaryOperator>(binaryOp->getLHS()->IgnoreParenImpCasts()))
{ if (isAssignmentOp(binaryOp2->getOpcode()))
report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line",
expr->getBeginLoc())
<< expr->getSourceRange();
}
}
} elseif (auto operCall = dyn_cast<CXXOperatorCallExpr>(expr))
{ // Ignore chained assignment. // TODO limit this to only ordinary assignment if (isAssignmentOp(operCall->getOperator()))
{
report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line",
expr->getBeginLoc())
<< expr->getSourceRange();
}
}
/** stuff like *while((x=foo()) *and *while((x=foo()<0) *isconsideredidiomatic.
*/ void BuriedAssign::MarkConditionForControlLoops(Expr const* expr)
{ if (!expr) return;
expr = expr->IgnoreImplicit();
if (auto binaryOp = dyn_cast<BinaryOperator>(expr))
{ // ignore comma-chained statements at this level if (binaryOp->getOpcode() == BO_Comma)
{
MarkConditionForControlLoops(binaryOp->getLHS());
MarkConditionForControlLoops(binaryOp->getRHS()); return;
}
}
// unwrap conversion to bool if (auto memberCall = dyn_cast<CXXMemberCallExpr>(expr))
{ if (memberCall->getMethodDecl() && isa<CXXConversionDecl>(memberCall->getMethodDecl()))
{ // TODO check that the conversion is converting to bool
expr = memberCall->getImplicitObjectArgument()->IgnoreImplicit();
}
}
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.