diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2014-07-01 15:45:52 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2014-07-01 15:45:52 +0200 |
commit | e50ef195bc95f3f410119f623928382cb88b45d2 (patch) | |
tree | 0897c005806c84d7e2add9f4a2d407ff4fe911a5 /compilerplugins/clang | |
parent | 363e39d63621b6c7017854ca5bb2f7668bb35846 (diff) |
New loplugin:stringconcat
Change-Id: Id7c517fb37bc28797c45fc0dde83e866f2aa4aac
Diffstat (limited to 'compilerplugins/clang')
-rw-r--r-- | compilerplugins/clang/stringconcat.cxx | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/compilerplugins/clang/stringconcat.cxx b/compilerplugins/clang/stringconcat.cxx new file mode 100644 index 000000000000..43907e927cb3 --- /dev/null +++ b/compilerplugins/clang/stringconcat.cxx @@ -0,0 +1,82 @@ +/* -*- 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 "plugin.hxx" + +namespace { + +class StringConcat: + public RecursiveASTVisitor<StringConcat>, public loplugin::Plugin +{ +public: + explicit StringConcat(InstantiationData const & data): Plugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCallExpr(CallExpr const * expr); +}; + +bool StringConcat::VisitCallExpr(CallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + FunctionDecl const * fdecl = expr->getDirectCallee(); + if (fdecl == nullptr) { + return true; + } + OverloadedOperatorKind oo = fdecl->getOverloadedOperator(); + if ((oo != OverloadedOperatorKind::OO_Plus + && oo != OverloadedOperatorKind::OO_LessLess) + || fdecl->getNumParams() != 2 || expr->getNumArgs() != 2 + || !isa<StringLiteral>(expr->getArg(1)->IgnoreParenImpCasts())) + { + return true; + } + CallExpr const * left = dyn_cast<CallExpr>( + expr->getArg(0)->IgnoreParenImpCasts()); + if (left == nullptr) { + return true; + } + FunctionDecl const * ldecl = left->getDirectCallee(); + if (ldecl == nullptr) { + return true; + } + OverloadedOperatorKind loo = ldecl->getOverloadedOperator(); + if ((loo != OverloadedOperatorKind::OO_Plus + && loo != OverloadedOperatorKind::OO_LessLess) + || ldecl->getNumParams() != 2 || left->getNumArgs() != 2 + || !isa<StringLiteral>(left->getArg(1)->IgnoreParenImpCasts())) + { + return true; + } + StringRef name { + compiler.getSourceManager().getFilename( + compiler.getSourceManager().getSpellingLoc(expr->getLocStart())) }; + if (name == SRCDIR "/sal/qa/rtl/strings/test_ostring_concat.cxx" + || name == SRCDIR "/sal/qa/rtl/strings/test_oustring_concat.cxx") + { + return true; + } + CXXOperatorCallExpr const * op = dyn_cast<CXXOperatorCallExpr>(expr); + report( + DiagnosticsEngine::Warning, + "replace '%0' between string literals with juxtaposition", + op == nullptr ? expr->getExprLoc() : op->getOperatorLoc()) + << (oo == OverloadedOperatorKind::OO_Plus ? "+" : "<<") + << SourceRange( + left->getArg(1)->getLocStart(), expr->getArg(1)->getLocEnd()); + return true; +} + +loplugin::Plugin::Registration<StringConcat> X("stringconcat"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |