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
17 Expr
const * stripCtor(Expr
const * expr
) {
19 if (auto const e
= dyn_cast
<CXXFunctionalCastExpr
>(e1
)) {
20 e1
= e
->getSubExpr()->IgnoreParenImpCasts();
22 if (auto const e
= dyn_cast
<CXXBindTemporaryExpr
>(e1
)) {
23 e1
= e
->getSubExpr()->IgnoreParenImpCasts();
25 auto const e2
= dyn_cast
<CXXConstructExpr
>(e1
);
29 auto qt
= loplugin::DeclCheck(e2
->getConstructor());
30 if (qt
.MemberFunction().Class("OStringLiteral").Namespace("rtl").GlobalNamespace()
31 || qt
.MemberFunction().Class("OUStringLiteral").Namespace("rtl").GlobalNamespace())
33 if (e2
->getNumArgs() == 1) {
34 return e2
->getArg(0)->IgnoreParenImpCasts();
38 if (!((qt
.MemberFunction().Class("OString").Namespace("rtl")
40 || (qt
.MemberFunction().Class("OUString").Namespace("rtl")
45 if (e2
->getNumArgs() != 2) {
48 return e2
->getArg(0)->IgnoreParenImpCasts();
51 class StringConcatLiterals
:
52 public loplugin::FilteringPlugin
<StringConcatLiterals
>
55 explicit StringConcatLiterals(loplugin::InstantiationData
const & data
):
56 FilteringPlugin(data
) {}
59 { TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
61 bool VisitCallExpr(CallExpr
const * expr
);
64 bool isStringLiteral(Expr
const * expr
);
67 bool StringConcatLiterals::VisitCallExpr(CallExpr
const * expr
) {
68 if (ignoreLocation(expr
)) {
71 FunctionDecl
const * fdecl
= expr
->getDirectCallee();
72 if (fdecl
== nullptr) {
75 OverloadedOperatorKind oo
= fdecl
->getOverloadedOperator();
76 if ((oo
!= OverloadedOperatorKind::OO_Plus
77 && oo
!= OverloadedOperatorKind::OO_LessLess
)
78 || fdecl
->getNumParams() != 2 || expr
->getNumArgs() != 2
79 || !isStringLiteral(expr
->getArg(1)->IgnoreParenImpCasts()))
83 SourceLocation leftLoc
;
84 auto const leftExpr
= expr
->getArg(0)->IgnoreParenImpCasts();
85 if (isStringLiteral(leftExpr
)) {
86 leftLoc
= compat::getBeginLoc(leftExpr
);
88 CallExpr
const * left
= dyn_cast
<CallExpr
>(leftExpr
);
89 if (left
== nullptr) {
92 FunctionDecl
const * ldecl
= left
->getDirectCallee();
93 if (ldecl
== nullptr) {
96 OverloadedOperatorKind loo
= ldecl
->getOverloadedOperator();
97 if ((loo
!= OverloadedOperatorKind::OO_Plus
98 && loo
!= OverloadedOperatorKind::OO_LessLess
)
99 || ldecl
->getNumParams() != 2 || left
->getNumArgs() != 2
100 || !isStringLiteral(left
->getArg(1)->IgnoreParenImpCasts()))
104 leftLoc
= compat::getBeginLoc(left
->getArg(1));
107 // We add an extra " " in the TOOLS_WARN_EXCEPTION macro, which triggers this plugin
108 if (loplugin::isSamePathname(
109 getFilenameOfLocation(
110 compiler
.getSourceManager().getSpellingLoc(
111 compiler
.getSourceManager().getImmediateMacroCallerLoc(
112 compiler
.getSourceManager().getImmediateMacroCallerLoc(
113 compiler
.getSourceManager().getImmediateMacroCallerLoc(
114 compat::getBeginLoc(expr
)))))),
115 SRCDIR
"/include/tools/diagnose_ex.h"))
119 getFilenameOfLocation(
120 compiler
.getSourceManager().getSpellingLoc(compat::getBeginLoc(expr
))) };
121 if (loplugin::isSamePathname(
122 name
, SRCDIR
"/sal/qa/rtl/oustringbuffer/test_oustringbuffer_assign.cxx")
123 || loplugin::isSamePathname(
124 name
, SRCDIR
"/sal/qa/rtl/strings/test_ostring_concat.cxx")
125 || loplugin::isSamePathname(
126 name
, SRCDIR
"/sal/qa/rtl/strings/test_oustring_concat.cxx"))
130 CXXOperatorCallExpr
const * op
= dyn_cast
<CXXOperatorCallExpr
>(expr
);
132 DiagnosticsEngine::Warning
,
133 "replace '%0' between string literals with juxtaposition",
134 op
== nullptr ? expr
->getExprLoc() : op
->getOperatorLoc())
135 << (oo
== OverloadedOperatorKind::OO_Plus
? "+" : "<<")
136 << SourceRange(leftLoc
, compat::getEndLoc(expr
->getArg(1)));
140 bool StringConcatLiterals::isStringLiteral(Expr
const * expr
) {
141 expr
= stripCtor(expr
);
142 if (!isa
<clang::StringLiteral
>(expr
)) {
148 loplugin::Plugin::Registration
<StringConcatLiterals
> stringconcatliterals("stringconcatliterals");
152 #endif // LO_CLANG_SHARED_PLUGINS
154 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */