summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2013-03-19 10:48:22 +0100
committerStephan Bergmann <sbergman@redhat.com>2013-03-19 11:02:28 +0100
commit24387f1c58b30cae26618c377acd95a336c28380 (patch)
treef14862677b3e53dc11287696f16fe53a82edcd7b /compilerplugins
parentf9e96c364108ddd57f330a7bd52528937aef41e8 (diff)
A plugin to find suboptimal equalsIgnoreAsciiCaseAscii[L] calls
Change-Id: Id2572982ca899223b89016ee7482ccb960032805
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/literalalternative.cxx111
1 files changed, 111 insertions, 0 deletions
diff --git a/compilerplugins/clang/literalalternative.cxx b/compilerplugins/clang/literalalternative.cxx
new file mode 100644
index 000000000000..e90b688ae259
--- /dev/null
+++ b/compilerplugins/clang/literalalternative.cxx
@@ -0,0 +1,111 @@
+/* -*- 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/.
+ */
+
+#include <string>
+
+#include "plugin.hxx"
+
+// Find those calls of rtl::OUString::equalsIgnoreAsciiCaseAscii and
+// rtl::OUString::equalsIgnoreAsciiCaseAsciiL that could be simplified to call
+// rtl::OUString::equalsIgnoreAsciiCase instead:
+
+namespace {
+
+class LiteralAlternative:
+ public RecursiveASTVisitor<LiteralAlternative>, public loplugin::Plugin
+{
+public:
+ explicit LiteralAlternative(ASTContext & context): Plugin(context) {}
+
+ virtual void run() { TraverseDecl(context.getTranslationUnitDecl()); }
+
+ bool VisitCallExpr(CallExpr * expr);
+};
+
+bool LiteralAlternative::VisitCallExpr(CallExpr * expr) {
+ if (ignoreLocation(expr)) {
+ return true;
+ }
+ FunctionDecl const * fdecl = expr->getDirectCallee();
+ if (fdecl == nullptr) {
+ return true;
+ }
+ std::string qname { fdecl->getQualifiedNameAsString() };
+ if (qname == "rtl::OUString::equalsIgnoreAsciiCaseAscii"
+ && fdecl->getNumParams() == 1 && expr->getNumArgs() == 1)
+ {
+ // equalsIgnoreAsciiCaseAscii("foo") -> equalsIngoreAsciiCase("foo"):
+ StringLiteral const * lit
+ = dyn_cast<StringLiteral>(expr->getArg(0)->IgnoreParenImpCasts());
+ if (lit != nullptr) {
+ report(
+ DiagnosticsEngine::Warning,
+ ("rewrite call of rtl::OUString::equalsIgnoreAsciiCaseAscii"
+ " with string literal argument as call of"
+ " rtl::OUString::equalsIgnoreAsciiCase"),
+ expr->getExprLoc());
+ //TODO: a better loc (the "equalsIgnoreAsciiCaseAscii" part)?
+ }
+ return true;
+ }
+ if (qname == "rtl::OUString::equalsIgnoreAsciiCaseAsciiL"
+ && fdecl->getNumParams() == 2 && expr->getNumArgs() == 2)
+ {
+ // equalsIgnoreAsciiCaseAsciiL("foo", 3) -> equalsIngoreAsciiCase("foo")
+ // especially also for
+ // equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("foo")), where
+ // RTL_CONSTASCII_STRINGPARAM expands to complicated expressions
+ // involving (&(X)[0] sub-expressions (and it might or might not be
+ // better to handle that at the level of non-expanded macros instead,
+ // but I have not found out how to do that yet anyway):
+ APSInt res;
+ if (expr->getArg(1)->isIntegerConstantExpr(res, context)) {
+ Expr const * arg0 = expr->getArg(0)->IgnoreParenImpCasts();
+ StringLiteral const * lit = dyn_cast<StringLiteral>(arg0);
+ bool match = false;
+ if (lit != nullptr) {
+ match = res == lit->getLength();
+ } else {
+ UnaryOperator const * op = dyn_cast<UnaryOperator>(arg0);
+ if (op != nullptr && op->getOpcode() == UO_AddrOf) {
+ ArraySubscriptExpr const * subs
+ = dyn_cast<ArraySubscriptExpr>(
+ op->getSubExpr()->IgnoreParenImpCasts());
+ if (subs != nullptr) {
+ lit = dyn_cast<StringLiteral>(
+ subs->getBase()->IgnoreParenImpCasts());
+ match = lit != nullptr
+ && subs->getIdx()->isIntegerConstantExpr(
+ res, context)
+ && res == 0;
+ }
+ }
+ }
+ if (match) {
+ report(
+ DiagnosticsEngine::Warning,
+ ("rewrite call of"
+ " rtl::OUString::equalsIgnoreAsciiCaseAsciiL with string"
+ " literal and matching length arguments as call of"
+ " rtl::OUString::equalsIgnoreAsciiCase"),
+ expr->getExprLoc());
+ //TODO: a better loc (the "equalsIgnoreAsciiCaseAsciiL"
+ // part)?
+ }
+ }
+ return true;
+ }
+ return true;
+}
+
+loplugin::Plugin::Registration< LiteralAlternative > X("literalalternative");
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */