Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / stringstatic.cxx
blob00f1c9f6eab1cd2d1831dde4b705bf3016110001
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <set>
12 #include "check.hxx"
13 #include "plugin.hxx"
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.
22 namespace {
24 class StringStatic
25 : public clang::RecursiveASTVisitor<StringStatic>
26 , public loplugin::Plugin
29 public:
30 explicit StringStatic(loplugin::InstantiationData const& rData):
31 Plugin(rData) {}
33 void run() override;
34 bool VisitVarDecl(VarDecl const*);
35 bool VisitReturnStmt(ReturnStmt const*);
36 private:
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/"))
47 return;
48 // has a mix of literals and refs to external OUStrings
49 if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/webdav-neon/ContentProperties.cxx"))
50 return;
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)) {
68 return true;
70 QualType qt = varDecl->getType();
71 if (!varDecl->hasGlobalStorage()
72 || !varDecl->isThisDeclarationADefinition()
73 || !qt.isConstQualified()) {
74 return true;
76 if (qt->isArrayType()) {
77 qt = qt->getAsArrayTypeUnsafe()->getElementType();
79 if (!loplugin::TypeCheck(qt).Class("OUString").Namespace("rtl").GlobalNamespace()) {
80 return true;
82 if (varDecl->hasInit()) {
83 Expr const * expr = varDecl->getInit();
84 while (true) {
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) {
99 return true;
101 expr = constructExpr->getArg(0);
102 } else if (isa<CallExpr>(expr)) {
103 return true;
104 } else {
105 break;
109 potentialVars.insert(varDecl);
111 return true;
114 bool StringStatic::VisitReturnStmt(ReturnStmt const * returnStmt)
116 if (ignoreLocation(returnStmt)) {
117 return true;
119 if (!returnStmt->getRetValue()) {
120 return true;
122 DeclRefExpr const * declRef = dyn_cast<DeclRefExpr>(returnStmt->getRetValue());
123 if (!declRef) {
124 return true;
126 VarDecl const * varDecl = dyn_cast<VarDecl>(declRef->getDecl());
127 if (varDecl) {
128 excludeVars.insert(varDecl);
130 return true;
133 loplugin::Plugin::Registration<StringStatic> X("stringstatic");
135 } // namespace
137 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */