/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ #ifndef LO_CLANG_SHARED_PLUGINS
/** Check for (*) calls to CPPUNIT_ASSERT when it should be using CPPUNIT_ASSERT_EQUALS (*) calls to CPPUNIT_ASSERT_EQUALS where the constant is the second param
*/
namespace {
class CppunitAssertEquals: public loplugin::FilteringPlugin<CppunitAssertEquals>
{ public: explicit CppunitAssertEquals(loplugin::InstantiationData const & data):
FilteringPlugin(data) {}
bool CppunitAssertEquals::VisitCallExpr(const CallExpr* callExpr)
{ autoconst decl = callExpr->getDirectCallee(); if (!decl) returntrue; /* calls to CPPUNIT_ASSERT when it should be using CPPUNIT_ASSERT_EQUALS
*/ if (loplugin::DeclCheck(decl).Function("failIf").Struct("Asserter")
.Namespace("CppUnit").GlobalNamespace())
{ // Don't use callExpr->getLocStart() or callExpr->getExprLoc(), as those // fall into a nested use of the CPPUNIT_NS macro; CallExpr::getRParenLoc // happens to be readily available and cause good results: auto loc = callExpr->getRParenLoc(); while (compiler.getSourceManager().isMacroArgExpansion(loc)) {
loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc);
} if (!compiler.getSourceManager().isMacroBodyExpansion(loc)
|| ignoreLocation(
compiler.getSourceManager().getImmediateMacroCallerLoc(loc)))
{ returntrue;
} auto name = Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(), compiler.getLangOpts()); if (name != "CPPUNIT_ASSERT" && name != "CPPUNIT_ASSERT_MESSAGE") { returntrue;
} if (decl->getNumParams() != 3) {
report(
DiagnosticsEngine::Warning,
("TODO: suspicious CppUnit::Asserter::failIf call with %0" " parameters"),
callExpr->getExprLoc())
<< decl->getNumParams() << callExpr->getSourceRange(); returntrue;
} autoconst e1 = callExpr->getArg(0)->IgnoreParenImpCasts();
Expr const * e2 = nullptr; if (autoconst e3 = dyn_cast<UnaryOperator>(e1)) { if (e3->getOpcode() == UO_LNot) {
e2 = e3->getSubExpr();
}
} elseif (autoconst e4 = dyn_cast<CXXOperatorCallExpr>(e1)) { if (e4->getOperator() == OO_Exclaim) {
e2 = e4->getArg(0);
}
} if (e2 == nullptr) {
report(
DiagnosticsEngine::Warning,
("TODO: suspicious CppUnit::Asserter::failIf call not wrapping" " !(...)"),
callExpr->getExprLoc())
<< callExpr->getSourceRange(); returntrue;
} auto range = compat::getImmediateExpansionRange(compiler.getSourceManager(), loc);
checkExpr(
SourceRange(range.first, range.second), name,
e2->IgnoreParenImpCasts(), false);
}
/** Check for calls to CPPUNIT_ASSERT_EQUALS where the constant is the second param
*/ if (loplugin::DeclCheck(decl).Function("assertEquals"). Namespace("CppUnit").GlobalNamespace())
{ // can happen in template test code that both params are compile time constants if (isCompileTimeConstant(callExpr->getArg(0))) returntrue; if (isCompileTimeConstant(callExpr->getArg(1)))
report(
DiagnosticsEngine::Warning, "CPPUNIT_ASSERT_EQUALS parameters look switched, expected value should be first param",
callExpr->getExprLoc())
<< callExpr->getSourceRange();
} if (loplugin::DeclCheck(decl).Function("assertDoubleEquals"). Namespace("CppUnit").GlobalNamespace())
{ // can happen in template test code that both params are compile time constants if (isCompileTimeConstant(callExpr->getArg(0))) returntrue; if (isCompileTimeConstant(callExpr->getArg(1)))
report(
DiagnosticsEngine::Warning, "CPPUNIT_ASSERT_DOUBLES_EQUALS parameters look switched, expected value should be first param",
callExpr->getExprLoc())
<< callExpr->getSourceRange();
} if (loplugin::DeclCheck(decl).Function("assertLess"). Namespace("CppUnit").GlobalNamespace())
{ // can happen in template test code that both params are compile time constants if (isCompileTimeConstant(callExpr->getArg(0))) returntrue; if (isCompileTimeConstant(callExpr->getArg(1)))
report(
DiagnosticsEngine::Warning, "CPPUNIT_ASSERT_LESS parameters look switched, expected value should be first param",
callExpr->getExprLoc())
<< callExpr->getSourceRange();
} if (loplugin::DeclCheck(decl).Function("assertLessEqual"). Namespace("CppUnit").GlobalNamespace())
{ // can happen in template test code that both params are compile time constants if (isCompileTimeConstant(callExpr->getArg(0))) returntrue; if (isCompileTimeConstant(callExpr->getArg(1)))
report(
DiagnosticsEngine::Warning, "CPPUNIT_ASSERT_LESSEQUAL parameters look switched, expected value should be first param",
callExpr->getExprLoc())
<< callExpr->getSourceRange();
} if (loplugin::DeclCheck(decl).Function("assertGreater"). Namespace("CppUnit").GlobalNamespace())
{ // can happen in template test code that both params are compile time constants if (isCompileTimeConstant(callExpr->getArg(0))) returntrue; if (isCompileTimeConstant(callExpr->getArg(1)))
report(
DiagnosticsEngine::Warning, "CPPUNIT_ASSERT_GREATER parameters look switched, expected value should be first param",
callExpr->getExprLoc())
<< callExpr->getSourceRange();
} if (loplugin::DeclCheck(decl).Function("assertGreaterEqual"). Namespace("CppUnit").GlobalNamespace())
{ // can happen in template test code that both params are compile time constants if (isCompileTimeConstant(callExpr->getArg(0))) returntrue; if (isCompileTimeConstant(callExpr->getArg(1)))
report(
DiagnosticsEngine::Warning, "CPPUNIT_ASSERT_GREATEREQUAL parameters look switched, expected value should be first param",
callExpr->getExprLoc())
<< callExpr->getSourceRange();
} returntrue;
}
// copied from stringconcat.cxx
Expr const * stripConstructor(Expr const * expr) { auto e0 = expr; autoconst e1 = dyn_cast<CXXFunctionalCastExpr>(e0); if (e1 != nullptr) {
e0 = e1->getSubExpr()->IgnoreParenImpCasts();
} autoconst e2 = dyn_cast<CXXBindTemporaryExpr>(e0); if (e2 == nullptr) { return expr;
} autoconst e3 = dyn_cast<CXXConstructExpr>(
e2->getSubExpr()->IgnoreParenImpCasts()); if (e3 == nullptr) { return expr;
} auto qt = loplugin::DeclCheck(e3->getConstructor()); if (!((qt.MemberFunction().Class("OString").Namespace("rtl")
.GlobalNamespace())
|| (qt.MemberFunction().Class("OUString").Namespace("rtl")
.GlobalNamespace())))
{ return expr;
} if (e3->getNumArgs() != 2) { return expr;
} return e3->getArg(0)->IgnoreParenImpCasts();
}
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 ist noch experimentell.