1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
12 #include "config_clang.h"
19 Expr
const * stripCtor(Expr
const * expr
) {
21 if (auto const e
= dyn_cast
<CXXFunctionalCastExpr
>(e1
)) {
22 e1
= e
->getSubExpr()->IgnoreParenImpCasts();
24 if (auto const e
= dyn_cast
<CXXBindTemporaryExpr
>(e1
)) {
25 e1
= e
->getSubExpr()->IgnoreParenImpCasts();
27 auto const e2
= dyn_cast
<CXXConstructExpr
>(e1
);
31 auto qt
= loplugin::DeclCheck(e2
->getConstructor());
32 if (qt
.MemberFunction().Class("OStringLiteral").Namespace("rtl").GlobalNamespace()
33 || qt
.MemberFunction().Class("OUStringLiteral").Namespace("rtl").GlobalNamespace())
35 if (e2
->getNumArgs() == 1) {
36 return e2
->getArg(0)->IgnoreParenImpCasts();
40 if (!((qt
.MemberFunction().Class("OString").Namespace("rtl")
42 || (qt
.MemberFunction().Class("OUString").Namespace("rtl")
47 if (e2
->getNumArgs() != 2) {
50 return e2
->getArg(0)->IgnoreParenImpCasts();
53 class StringConcatLiterals
:
54 public loplugin::FilteringPlugin
<StringConcatLiterals
>
57 explicit StringConcatLiterals(loplugin::InstantiationData
const & data
):
58 FilteringPlugin(data
) {}
61 { TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
63 bool VisitCallExpr(CallExpr
const * expr
);
66 bool isStringLiteral(Expr
const * expr
);
69 bool StringConcatLiterals::VisitCallExpr(CallExpr
const * expr
) {
70 if (ignoreLocation(expr
)) {
73 FunctionDecl
const * fdecl
= expr
->getDirectCallee();
74 if (fdecl
== nullptr) {
77 OverloadedOperatorKind oo
= fdecl
->getOverloadedOperator();
78 if ((oo
!= OverloadedOperatorKind::OO_Plus
79 && oo
!= OverloadedOperatorKind::OO_LessLess
)
80 || fdecl
->getNumParams() != 2 || expr
->getNumArgs() != 2
81 || !isStringLiteral(expr
->getArg(1)->IgnoreParenImpCasts()))
85 SourceLocation leftLoc
;
86 auto const leftExpr
= expr
->getArg(0)->IgnoreParenImpCasts();
87 if (isStringLiteral(leftExpr
)) {
88 leftLoc
= leftExpr
->getBeginLoc();
90 CallExpr
const * left
= dyn_cast
<CallExpr
>(leftExpr
);
91 if (left
== nullptr) {
94 FunctionDecl
const * ldecl
= left
->getDirectCallee();
95 if (ldecl
== nullptr) {
98 OverloadedOperatorKind loo
= ldecl
->getOverloadedOperator();
99 if ((loo
!= OverloadedOperatorKind::OO_Plus
100 && loo
!= OverloadedOperatorKind::OO_LessLess
)
101 || ldecl
->getNumParams() != 2 || left
->getNumArgs() != 2
102 || !isStringLiteral(left
->getArg(1)->IgnoreParenImpCasts()))
106 leftLoc
= left
->getArg(1)->getBeginLoc();
109 // We add an extra " " in the TOOLS_WARN_EXCEPTION macro, which triggers this plugin
110 if (loplugin::isSamePathname(
111 getFilenameOfLocation(
112 compiler
.getSourceManager().getSpellingLoc(
113 compiler
.getSourceManager().getImmediateMacroCallerLoc(
114 compiler
.getSourceManager().getImmediateMacroCallerLoc(
115 compiler
.getSourceManager().getImmediateMacroCallerLoc(
116 expr
->getBeginLoc()))))),
117 SRCDIR
"/include/comphelper/diagnose_ex.hxx"))
121 getFilenameOfLocation(
122 compiler
.getSourceManager().getSpellingLoc(expr
->getBeginLoc())) };
123 if (loplugin::isSamePathname(
124 name
, SRCDIR
"/sal/qa/rtl/oustringbuffer/test_oustringbuffer_assign.cxx")
125 || loplugin::isSamePathname(
126 name
, SRCDIR
"/sal/qa/rtl/strings/test_ostring_concat.cxx")
127 || loplugin::isSamePathname(
128 name
, SRCDIR
"/sal/qa/rtl/strings/test_oustring_concat.cxx"))
132 CXXOperatorCallExpr
const * op
= dyn_cast
<CXXOperatorCallExpr
>(expr
);
134 DiagnosticsEngine::Warning
,
135 "replace '%0' between string literals with juxtaposition",
136 op
== nullptr ? expr
->getExprLoc() : op
->getOperatorLoc())
137 << (oo
== OverloadedOperatorKind::OO_Plus
? "+" : "<<")
138 << SourceRange(leftLoc
, expr
->getArg(1)->getEndLoc());
142 bool StringConcatLiterals::isStringLiteral(Expr
const * expr
) {
143 expr
= stripCtor(expr
);
144 if (!isa
<clang::StringLiteral
>(expr
)) {
150 loplugin::Plugin::Registration
<StringConcatLiterals
> stringconcatliterals("stringconcatliterals");
154 #endif // LO_CLANG_SHARED_PLUGINS
156 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */