summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2015-06-25 12:38:02 +0200
committerStephan Bergmann <sbergman@redhat.com>2015-06-25 12:38:40 +0200
commitaf333e81037b106702fc4c4d68b0653f80d2fb1b (patch)
tree521c07b2c2606fe391f0c68e0b5e48ad2c94bb18 /compilerplugins
parent94c1ea92ce7653f3cf91cfd0efe9546bbdb47ad3 (diff)
loplugin:stringconstant: Flag more inefficiencies
Change-Id: I47726315f12ef05714bea248d79cc503fb99b23c
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/stringconstant.cxx133
1 files changed, 133 insertions, 0 deletions
diff --git a/compilerplugins/clang/stringconstant.cxx b/compilerplugins/clang/stringconstant.cxx
index 12bf173bc4f1..9c869218f6cb 100644
--- a/compilerplugins/clang/stringconstant.cxx
+++ b/compilerplugins/clang/stringconstant.cxx
@@ -98,6 +98,9 @@ private:
std::string const & qname, std::string const & replacement,
TreatEmpty treatEmpty);
+ void handleOUStringCtor(
+ CallExpr const * expr, unsigned arg, std::string const & qname);
+
std::stack<Expr const *> calls_;
};
@@ -292,6 +295,68 @@ bool StringConstant::VisitCallExpr(CallExpr const * expr) {
TreatEmpty::Error);
return true;
}
+ if (qname == "rtl::OUString::reverseCompareTo"
+ && fdecl->getNumParams() == 1)
+ {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::equalsIgnoreAsciiCase"
+ && fdecl->getNumParams() == 1)
+ {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::match" && fdecl->getNumParams() == 2) {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::matchIgnoreAsciiCase"
+ && fdecl->getNumParams() == 2)
+ {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::startsWith" && fdecl->getNumParams() == 2) {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::startsWithIgnoreAsciiCase"
+ && fdecl->getNumParams() == 2)
+ {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::endsWith" && fdecl->getNumParams() == 2) {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::endsWithIgnoreAsciiCase"
+ && fdecl->getNumParams() == 2)
+ {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::indexOf" && fdecl->getNumParams() == 2) {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::lastIndexOf" && fdecl->getNumParams() == 1) {
+ handleOUStringCtor(expr, 0, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::replaceFirst" && fdecl->getNumParams() == 3) {
+ handleOUStringCtor(expr, 0, qname);
+ handleOUStringCtor(expr, 1, qname);
+ return true;
+ }
+ if (qname == "rtl::OUString::replaceAll"
+ && (fdecl->getNumParams() == 2 || fdecl->getNumParams() == 3))
+ {
+ handleOUStringCtor(expr, 0, qname);
+ handleOUStringCtor(expr, 1, qname);
+ return true;
+ }
if (qname == "rtl::OUString::equals" && fdecl->getNumParams() == 1) {
unsigned n;
bool non;
@@ -451,6 +516,7 @@ bool StringConstant::VisitCallExpr(CallExpr const * expr) {
<< expr->getSourceRange();
return true;
}
+ return true;
}
return true;
}
@@ -1089,6 +1155,73 @@ void StringConstant::handleCharLen(
reportChange(expr, ChangeKind::CharLen, qname, repl, PassThrough::No);
}
+void StringConstant::handleOUStringCtor(
+ CallExpr const * expr, unsigned arg, std::string const & qname)
+{
+ auto e0 = expr->getArg(arg)->IgnoreParenImpCasts();
+ auto e1 = dyn_cast<CXXFunctionalCastExpr>(e0);
+ if (e1 != nullptr) {
+ e0 = e1->getSubExpr()->IgnoreParenImpCasts();
+ }
+ auto e2 = dyn_cast<CXXBindTemporaryExpr>(e0);
+ if (e2 == nullptr) {
+ return;
+ }
+ auto e3 = dyn_cast<CXXConstructExpr>(
+ e2->getSubExpr()->IgnoreParenImpCasts());
+ if (e3 == nullptr) {
+ return;
+ }
+ if (e3->getConstructor()->getQualifiedNameAsString()
+ != "rtl::OUString::OUString")
+ {
+ return;
+ }
+ if (e3->getNumArgs() == 0) {
+ report(
+ DiagnosticsEngine::Warning,
+ ("in call of %0, replace default-constructed OUString with an empty"
+ " string literal"),
+ e3->getExprLoc())
+ << qname << expr->getSourceRange();
+ return;
+ }
+ APSInt res;
+ if (e3->getNumArgs() == 1
+ && e3->getArg(0)->IgnoreParenImpCasts()->isIntegerConstantExpr(
+ res, compiler.getASTContext()))
+ {
+ if (res > 0 && res <= 127) {
+ report(
+ DiagnosticsEngine::Warning,
+ ("in call of %0, replace OUString constructed from a (non-NUL)"
+ " ASCII char constant with a string literal"),
+ e3->getExprLoc())
+ << qname << expr->getSourceRange();
+ }
+ return;
+ }
+ if (e3->getNumArgs() != 2) {
+ return;
+ }
+ unsigned n;
+ bool non;
+ bool emb;
+ bool trm;
+ if (!isStringConstant(
+ e3->getArg(0)->IgnoreParenImpCasts(), &n, &non, &emb, &trm))
+ {
+ return;
+ }
+ //TODO: non, emb, trm
+ report(
+ DiagnosticsEngine::Warning,
+ ("in call of %0, replace OUString constructed from a string literal"
+ " directly with the string literal"),
+ e3->getExprLoc())
+ << qname << expr->getSourceRange();
+}
+
loplugin::Plugin::Registration< StringConstant > X("stringconstant");
}