1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #ifndef LO_CLANG_SHARED_PLUGINS
17 // Warn about checks whether a container is empty done via an (expensive) call to obtain the
18 // container's size. For now only handles cases involving strlen.
22 BinaryOperatorKind
revert(BinaryOperatorKind op
)
42 class Empty
: public loplugin::FilteringPlugin
<Empty
>
45 explicit Empty(loplugin::InstantiationData
const& data
)
46 : FilteringPlugin(data
)
50 bool VisitBinLT(BinaryOperator
const* expr
)
52 visitComparison(expr
);
56 bool VisitBinGT(BinaryOperator
const* expr
)
58 visitComparison(expr
);
62 bool VisitBinLE(BinaryOperator
const* expr
)
64 visitComparison(expr
);
68 bool VisitBinGE(BinaryOperator
const* expr
)
70 visitComparison(expr
);
74 bool VisitBinEQ(BinaryOperator
const* expr
)
76 visitComparison(expr
);
80 bool VisitBinNE(BinaryOperator
const* expr
)
82 visitComparison(expr
);
87 void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
89 void visitComparison(BinaryOperator
const* expr
, CallExpr
const* lhs
, Expr
const* rhs
,
90 BinaryOperatorKind op
)
92 auto const fdecl
= lhs
->getDirectCallee();
97 loplugin::DeclCheck
dc(fdecl
);
98 if (!(dc
.Function("strlen").StdNamespace() || dc
.Function("strlen").GlobalNamespace()))
103 if (rhs
->isValueDependent() || !rhs
->isIntegerConstantExpr(val
, compiler
.getASTContext()))
110 if (val
.getExtValue() == 1)
112 report(DiagnosticsEngine::Warning
,
113 "replace a comparison like 'strlen(e) < 1' with 'e[0] == '\\0''",
115 << expr
->getSourceRange();
119 if (val
.getExtValue() == 0)
121 report(DiagnosticsEngine::Warning
,
122 "replace a comparison like 'strlen(e) > 0' with 'e[0] != '\\0''",
124 << expr
->getSourceRange();
128 if (val
.getExtValue() == 0)
130 report(DiagnosticsEngine::Warning
,
131 "replace a comparison like 'strlen(e) <= 0' with 'e[0] == '\\0''",
133 << expr
->getSourceRange();
137 if (val
.getExtValue() == 1)
139 report(DiagnosticsEngine::Warning
,
140 "replace a comparison like 'strlen(e) >= 1' with 'e[0] != '\\0''",
142 << expr
->getSourceRange();
146 if (val
.getExtValue() == 0)
148 report(DiagnosticsEngine::Warning
,
149 "replace a comparison like 'strlen(e) == 0' with 'e[0] == '\\0''",
151 << expr
->getSourceRange();
155 if (val
.getExtValue() == 0)
157 report(DiagnosticsEngine::Warning
,
158 "replace a comparison like 'strlen(e) != 0' with 'e[0] != '\\0''",
160 << expr
->getSourceRange();
168 void visitComparison(BinaryOperator
const* expr
)
170 if (ignoreLocation(expr
))
174 if (auto const call
= dyn_cast
<CallExpr
>(expr
->getLHS()->IgnoreParenImpCasts()))
176 visitComparison(expr
, call
, expr
->getRHS(), expr
->getOpcode());
178 else if (auto const call
= dyn_cast
<CallExpr
>(expr
->getRHS()->IgnoreParenImpCasts()))
180 visitComparison(expr
, call
, expr
->getLHS(), revert(expr
->getOpcode()));
185 loplugin::Plugin::Registration
<Empty
> emptyRegistration("empty");
188 #endif // LO_CLANG_SHARED_PLUGINS
190 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */