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/.
15 /** Look for static OUString and OUString[], they can be more efficiently declared as:
17 static const OUStringLiteral our_aLBEntryMap[] = {" ", ", "};
18 static const OUStringLiteral sName("name");
20 which is more efficient at startup time.
25 : public clang::RecursiveASTVisitor
<StringStatic
>
26 , public loplugin::Plugin
30 explicit StringStatic(loplugin::InstantiationData
const& rData
):
34 bool VisitVarDecl(VarDecl
const*);
35 bool VisitReturnStmt(ReturnStmt
const*);
37 std::set
<VarDecl
const *> potentialVars
;
38 std::set
<VarDecl
const *> excludeVars
;
41 void StringStatic::run()
43 StringRef
fn( compiler
.getSourceManager().getFileEntryForID(
44 compiler
.getSourceManager().getMainFileID())->getName() );
45 // passing around pointers to global OUString
46 if (loplugin::hasPathnamePrefix(fn
, SRCDIR
"/filter/source/svg/"))
48 // has a mix of literals and refs to external OUStrings
49 if (loplugin::isSamePathname(fn
, SRCDIR
"/ucb/source/ucp/webdav-neon/ContentProperties.cxx"))
52 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
54 for (auto const & pVarDecl
: excludeVars
) {
55 potentialVars
.erase(pVarDecl
);
57 for (auto const & varDecl
: potentialVars
) {
58 report(DiagnosticsEngine::Warning
,
59 "rather declare this using OUStringLiteral or char[]",
60 varDecl
->getLocation())
61 << varDecl
->getSourceRange();
65 bool StringStatic::VisitVarDecl(VarDecl
const* varDecl
)
67 if (ignoreLocation(varDecl
)) {
70 QualType qt
= varDecl
->getType();
71 if (!varDecl
->hasGlobalStorage()
72 || !varDecl
->isThisDeclarationADefinition()
73 || !qt
.isConstQualified()) {
76 if (qt
->isArrayType()) {
77 qt
= qt
->getAsArrayTypeUnsafe()->getElementType();
79 if (!loplugin::TypeCheck(qt
).Class("OUString").Namespace("rtl").GlobalNamespace()) {
82 if (varDecl
->hasInit()) {
83 Expr
const * expr
= varDecl
->getInit();
85 if (ExprWithCleanups
const * exprWithCleanups
= dyn_cast
<ExprWithCleanups
>(expr
)) {
86 expr
= exprWithCleanups
->getSubExpr();
88 else if (CastExpr
const * castExpr
= dyn_cast
<CastExpr
>(expr
)) {
89 expr
= castExpr
->getSubExpr();
91 else if (MaterializeTemporaryExpr
const * materializeExpr
= dyn_cast
<MaterializeTemporaryExpr
>(expr
)) {
92 expr
= materializeExpr
->GetTemporaryExpr();
94 else if (CXXBindTemporaryExpr
const * bindExpr
= dyn_cast
<CXXBindTemporaryExpr
>(expr
)) {
95 expr
= bindExpr
->getSubExpr();
97 else if (CXXConstructExpr
const * constructExpr
= dyn_cast
<CXXConstructExpr
>(expr
)) {
98 if (constructExpr
->getNumArgs() != 1) {
101 expr
= constructExpr
->getArg(0);
102 } else if (isa
<CallExpr
>(expr
)) {
109 potentialVars
.insert(varDecl
);
114 bool StringStatic::VisitReturnStmt(ReturnStmt
const * returnStmt
)
116 if (ignoreLocation(returnStmt
)) {
119 if (!returnStmt
->getRetValue()) {
122 DeclRefExpr
const * declRef
= dyn_cast
<DeclRefExpr
>(returnStmt
->getRetValue());
126 VarDecl
const * varDecl
= dyn_cast
<VarDecl
>(declRef
->getDecl());
128 excludeVars
.insert(varDecl
);
133 loplugin::Plugin::Registration
<StringStatic
> X("stringstatic");
137 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */