summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/implicitboolconversion.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/implicitboolconversion.cxx')
-rw-r--r--compilerplugins/clang/implicitboolconversion.cxx198
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();
}