diff options
Diffstat (limited to 'compilerplugins/clang/implicitboolconversion.cxx')
-rw-r--r-- | compilerplugins/clang/implicitboolconversion.cxx | 198 |
1 files changed, 98 insertions, 100 deletions
diff --git a/compilerplugins/clang/implicitboolconversion.cxx b/compilerplugins/clang/implicitboolconversion.cxx index 14574e3cd420..64bc97ff4999 100644 --- a/compilerplugins/clang/implicitboolconversion.cxx +++ b/compilerplugins/clang/implicitboolconversion.cxx @@ -17,8 +17,6 @@ #include "clang/Basic/Builtins.h" -#include "config_clang.h" - #include "check.hxx" #include "compat.hxx" #include "plugin.hxx" @@ -32,7 +30,7 @@ Expr const * ignoreParenAndTemporaryMaterialization(Expr const * expr) { if (e == nullptr) { return expr; } - expr = compat::getSubExpr(e); + expr = e->getSubExpr(); } } @@ -65,14 +63,15 @@ QualType reconstructTemplateArgumentType( SubstTemplateTypeParmType const * parmType) { TemplateParameterList const * ps = decl->getTemplateParameters(); - auto i = std::find(ps->begin(), ps->end(), parmType->getReplacedParameter()->getDecl()); + auto i = std::find(ps->begin(), ps->end(), compat::getReplacedParameter(parmType)); if (i == ps->end()) { return {}; } - if (ps->size() != specializationType->getNumArgs()) { //TODO + auto const args = specializationType->template_arguments(); + if (ps->size() != args.size()) { //TODO return {}; } - TemplateArgument const & arg = specializationType->getArg(i - ps->begin()); + TemplateArgument const & arg = args[i - ps->begin()]; if (arg.getKind() != TemplateArgument::Type) { return {}; } @@ -181,15 +180,24 @@ bool isBoolExpr(Expr const * expr) { (void)op; TemplateDecl const * d = t->getTemplateName().getAsTemplateDecl(); - if (d == nullptr - || (d->getQualifiedNameAsString() - != "com::sun::star::uno::Sequence") - || t->getNumArgs() != 1 - || t->getArg(0).getKind() != TemplateArgument::Type) + if (d == nullptr) { + break; + } + auto const dc = loplugin::DeclCheck(d->getTemplatedDecl()); + auto const args = t->template_arguments(); + if (dc.ClassOrStruct("array").StdNamespace() && args.size() >= 2 + && args[0].getKind() == TemplateArgument::Type) { + ty = args[0].getAsType(); + } else if (dc.Class("Sequence").Namespace("uno").Namespace("star").Namespace("sun") + .Namespace("com").GlobalNamespace() + && args.size() == 1 + && args[0].getKind() == TemplateArgument::Type) + { + ty = args[0].getAsType(); + } else { break; } - ty = t->getArg(0).getAsType(); } stack.pop(); if (stack.empty()) { @@ -253,28 +261,9 @@ public: bool TraverseBinaryOperator(BinaryOperator * expr); -#if CLANG_VERSION < 110000 - bool TraverseBinLT(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } - bool TraverseBinLE(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } - bool TraverseBinGT(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } - bool TraverseBinGE(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } - bool TraverseBinEQ(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } - bool TraverseBinNE(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } - bool TraverseBinAssign(BinaryOperator * expr) { return TraverseBinaryOperator(expr); } -#endif - bool TraverseCompoundAssignOperator(CompoundAssignOperator * expr); -#if CLANG_VERSION < 110000 - bool TraverseBinAndAssign(CompoundAssignOperator * expr) - { return TraverseCompoundAssignOperator(expr); } - bool TraverseBinOrAssign(CompoundAssignOperator * expr) - { return TraverseCompoundAssignOperator(expr); } - bool TraverseBinXorAssign(CompoundAssignOperator * expr) - { return TraverseCompoundAssignOperator(expr); } -#endif - - bool TraverseCXXStdInitializerListExpr(CXXStdInitializerListExpr * expr); + bool TraverseInitListExpr(InitListExpr * expr); bool TraverseReturnStmt(ReturnStmt * stmt); @@ -425,9 +414,10 @@ bool ImplicitBoolConversion::TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) = ct->getTemplateName().getAsTemplateDecl(); if (td != nullptr) { //TODO: fix this superficial nonsense check: - if (ct->getNumArgs() >= 1 - && ct->getArg(0).getKind() == TemplateArgument::Type - && (loplugin::TypeCheck(ct->getArg(0).getAsType()) + auto const args = ct->template_arguments(); + if (args.size() >= 1 + && args[0].getKind() == TemplateArgument::Type + && (loplugin::TypeCheck(args[0].getAsType()) .AnyBoolean())) { continue; @@ -613,7 +603,7 @@ bool ImplicitBoolConversion::TraverseCompoundAssignOperator(CompoundAssignOperat { report( DiagnosticsEngine::Warning, "mix of %0 and %1 in operator %2", - compat::getBeginLoc(expr->getRHS())) + expr->getRHS()->getBeginLoc()) << expr->getLHS()->getType() << expr->getRHS()->IgnoreParenImpCasts()->getType() << expr->getOpcodeStr() @@ -626,36 +616,15 @@ bool ImplicitBoolConversion::TraverseCompoundAssignOperator(CompoundAssignOperat } } -bool ImplicitBoolConversion::TraverseCXXStdInitializerListExpr( - CXXStdInitializerListExpr * expr) -{ - // Must be some std::initializer_list<T>; check whether T is sal_Bool (i.e., - // unsigned char) [TODO: check for real sal_Bool instead]: - auto t = expr->getType(); - if (auto et = dyn_cast<ElaboratedType>(t)) { - t = et->desugar(); - } - auto ts = t->getAs<TemplateSpecializationType>(); - if (ts == nullptr - || !ts->getArg(0).getAsType()->isSpecificBuiltinType( - clang::BuiltinType::UChar)) - { - return RecursiveASTVisitor::TraverseCXXStdInitializerListExpr(expr); - } - // Avoid warnings for code like - // - // Sequence<sal_Bool> arBool({true, false, true}); - // - auto e = dyn_cast<InitListExpr>( - ignoreParenAndTemporaryMaterialization(expr->getSubExpr())); - if (e == nullptr) { - return RecursiveASTVisitor::TraverseCXXStdInitializerListExpr(expr); - } +bool ImplicitBoolConversion::TraverseInitListExpr(InitListExpr * expr) { nested.push(std::vector<ImplicitCastExpr const *>()); - bool ret = RecursiveASTVisitor::TraverseCXXStdInitializerListExpr(expr); + auto const e = expr->isSemanticForm() ? expr : expr->getSemanticForm(); + auto const ret = TraverseSynOrSemInitListExpr(e, nullptr); assert(!nested.empty()); for (auto i: nested.top()) { - if (std::find(e->begin(), e->end(), i) == e->end()) { + if (std::find(e->begin(), e->end(), i) == e->end() + || !i->getType()->isSpecificBuiltinType(clang::BuiltinType::UChar)) + { reportWarning(i); } } @@ -722,13 +691,33 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr( if (isBool(compat::getSubExprAsWritten(expr)) && !isBool(expr)) { // Ignore NoOp from 'sal_Bool' (aka 'unsigned char') to 'const unsigned // char' in makeAny(b) with b of type sal_Bool: - if (expr->getCastKind() != CK_NoOp) { - if (nested.empty()) { - reportWarning(expr); - } else { - nested.top().push_back(expr); + if (expr->getCastKind() == CK_NoOp) { + return true; + } + // Ignore implicit conversions from bool to int in + // + // #define _G_STR_NONNULL(x) (x + !x) + // + // from + // <https://gitlab.gnome.org/GNOME/glib/-/commit/48730d2b30473c5eeda2badf9a65d380304477c3> + // "gstrfuncs: Add back x + !x warning workaround": + if (auto const sub = dyn_cast<UnaryOperator>(compat::getSubExprAsWritten(expr))) { + if (sub->getOpcode() == UO_LNot) { + auto const l = expr->getBeginLoc(); + if (compiler.getSourceManager().isMacroBodyExpansion(l) + && Lexer::getImmediateMacroName( + l, compiler.getSourceManager(), compiler.getLangOpts()) + == "_G_STR_NONNULL") + { + return true; + } } } + if (nested.empty()) { + reportWarning(expr); + } else { + nested.top().push_back(expr); + } return true; } if (auto const sub = dyn_cast<ExplicitCastExpr>( @@ -750,7 +739,7 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr( DiagnosticsEngine::Warning, ("explicit conversion (%0) from %1 to %2 implicitly cast back" " to %3"), - compat::getBeginLoc(expr)) + expr->getBeginLoc()) << sub->getCastKindName() << subsub->getType() << sub->getType() << expr->getType() << expr->getSourceRange(); return true; @@ -767,7 +756,7 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr( report( DiagnosticsEngine::Warning, "implicit conversion (%0) of call argument from %1 to %2", - compat::getBeginLoc(expr)) + expr->getBeginLoc()) << expr->getCastKindName() << expr->getSubExpr()->getType() << expr->getType() << expr->getSourceRange(); return true; @@ -782,7 +771,7 @@ bool ImplicitBoolConversion::VisitMaterializeTemporaryExpr( if (ignoreLocation(expr)) { return true; } - if (auto const sub = dyn_cast<ExplicitCastExpr>(compat::getSubExpr(expr))) { + if (auto const sub = dyn_cast<ExplicitCastExpr>(expr->getSubExpr())) { auto const subsub = compat::getSubExprAsWritten(sub); if (subsub->getType().IgnoreParens() == expr->getType().IgnoreParens() && isBool(subsub)) @@ -791,7 +780,7 @@ bool ImplicitBoolConversion::VisitMaterializeTemporaryExpr( DiagnosticsEngine::Warning, ("explicit conversion (%0) from %1 to %2 implicitly converted" " back to %3"), - compat::getBeginLoc(expr)) + expr->getBeginLoc()) << sub->getCastKindName() << subsub->getType() << sub->getType() << expr->getType() << expr->getSourceRange(); return true; @@ -857,31 +846,39 @@ void ImplicitBoolConversion::checkCXXConstructExpr( if (j != expr->arg_end()) { TemplateSpecializationType const * t1 = expr->getType()-> getAs<TemplateSpecializationType>(); - SubstTemplateTypeParmType const * t2 = nullptr; - CXXConstructorDecl const * d = expr->getConstructor(); - if (d->getNumParams() == expr->getNumArgs()) { //TODO: better check - t2 = getAsSubstTemplateTypeParmType( - d->getParamDecl(j - expr->arg_begin())->getType() - .getNonReferenceType()); - } - if (t1 != nullptr && t2 != nullptr) { - TemplateDecl const * td - = t1->getTemplateName().getAsTemplateDecl(); - if (td != nullptr) { - TemplateParameterList const * ps - = td->getTemplateParameters(); - auto i = std::find( - ps->begin(), ps->end(), - t2->getReplacedParameter()->getDecl()); - if (i != ps->end()) { - if (ps->size() == t1->getNumArgs()) { //TODO - TemplateArgument const & arg = t1->getArg( - i - ps->begin()); - if (arg.getKind() == TemplateArgument::Type - && (loplugin::TypeCheck(arg.getAsType()) - .AnyBoolean())) - { - continue; + if (t1 == nullptr) { + //TODO: + if (i->getType()->isSpecificBuiltinType(clang::BuiltinType::UChar)) { + continue; + } + } else { + SubstTemplateTypeParmType const * t2 = nullptr; + CXXConstructorDecl const * d = expr->getConstructor(); + if (d->getNumParams() == expr->getNumArgs()) { //TODO: better check + t2 = getAsSubstTemplateTypeParmType( + d->getParamDecl(j - expr->arg_begin())->getType() + .getNonReferenceType()); + } + if (t2 != nullptr) { + TemplateDecl const * td + = t1->getTemplateName().getAsTemplateDecl(); + if (td != nullptr) { + TemplateParameterList const * ps + = td->getTemplateParameters(); + auto k = std::find( + ps->begin(), ps->end(), + compat::getReplacedParameter(t2)); + if (k != ps->end()) { + auto const args = t1->template_arguments(); + if (ps->size() == args.size()) { //TODO + TemplateArgument const & arg = args[ + k - ps->begin()]; + if (arg.getKind() == TemplateArgument::Type + && (loplugin::TypeCheck(arg.getAsType()) + .AnyBoolean())) + { + continue; + } } } } @@ -897,8 +894,9 @@ void ImplicitBoolConversion::reportWarning(ImplicitCastExpr const * expr) { if (expr->getCastKind() == CK_ConstructorConversion) { auto const t1 = expr->getType(); if (auto const t2 = t1->getAs<TemplateSpecializationType>()) { - assert(t2->getNumArgs() >= 1); - auto const a = t2->getArg(0); + auto const args = t2->template_arguments(); + assert(args.size() >= 1); + auto const a = args[0]; if (a.getKind() == TemplateArgument::Type && a.getAsType()->isBooleanType() && (loplugin::TypeCheck(t1).TemplateSpecializationClass() .ClassOrStruct("atomic").StdNamespace())) @@ -909,7 +907,7 @@ void ImplicitBoolConversion::reportWarning(ImplicitCastExpr const * expr) { } report( DiagnosticsEngine::Warning, - "implicit conversion (%0) from %1 to %2", compat::getBeginLoc(expr)) + "implicit conversion (%0) from %1 to %2", expr->getBeginLoc()) << expr->getCastKindName() << expr->getSubExprAsWritten()->getType() << expr->getType() << expr->getSourceRange(); } |