[en_US] Added 13 autocorrect words
[LibreOffice.git] / compilerplugins / clang / conststringvar.cxx
blob99cfb01c06f7a37f7e79c084bd8f8eceb917e662
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 */
9 #ifndef LO_CLANG_SHARED_PLUGINS
11 #include <set>
12 #include <stack>
14 #include "check.hxx"
15 #include "plugin.hxx"
17 // Find non-const vars of 'char const *' type initialized with a const expr,
18 // that could likely be const (and will then probably trigger further
19 // loplugin:stringconstant findings).
21 namespace {
23 class ConstStringVar:
24 public loplugin::FilteringPlugin<ConstStringVar>
26 public:
27 explicit ConstStringVar(loplugin::InstantiationData const & data):
28 FilteringPlugin(data) {}
30 bool preRun() override {
31 return compiler.getLangOpts().CPlusPlus;
32 // clang::Expr::isCXX11ConstantExpr only works for C++
35 void postRun() override {
36 for (auto v: vars_) {
37 report(
38 DiagnosticsEngine::Warning,
39 "variable is only used as rvalue, should be const",
40 v->getLocation())
41 << v->getSourceRange();
45 void run() override {
46 if (preRun() && TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) {
47 postRun();
51 bool PreTraverseImplicitCastExpr(ImplicitCastExpr * expr) {
52 bool match;
53 switch (expr->getCastKind()) {
54 case CK_NoOp:
55 // OString CharPtrDetector ctor:
56 match = bool(
57 loplugin::TypeCheck(expr->getType()).Const().Pointer().Const()
58 .Char());
59 break;
60 case CK_LValueToRValue:
61 match = true;
62 break;
63 default:
64 match = false;
65 break;
67 bool pushed = false;
68 if (match) {
69 if (auto dr = dyn_cast<DeclRefExpr>(
70 expr->getSubExpr()->IgnoreParenImpCasts()))
72 if (auto vd = dyn_cast<VarDecl>(dr->getDecl())) {
73 if (vars_.find(vd->getCanonicalDecl()) != vars_.end()) {
74 casted_.push(dr);
75 pushed = true;
80 pushed_.push(pushed);
81 return true;
83 bool PostTraverseImplicitCastExpr(ImplicitCastExpr *, bool) {
84 bool pushed = pushed_.top();
85 pushed_.pop();
86 if (pushed) {
87 casted_.pop();
89 return true;
91 bool TraverseImplicitCastExpr(ImplicitCastExpr * expr) {
92 bool ret = true;
93 if (PreTraverseImplicitCastExpr(expr))
95 ret = FilteringPlugin::TraverseImplicitCastExpr(expr);
96 PostTraverseImplicitCastExpr(expr, ret);
98 return ret;
101 bool VisitVarDecl(VarDecl const * decl) {
102 if (ignoreLocation(decl)) {
103 return true;
105 if (decl != decl->getCanonicalDecl()) {
106 return true;
108 if (isa<ParmVarDecl>(decl) || loplugin::hasExternalLinkage(decl)) {
109 return true;
111 if (!loplugin::TypeCheck(decl->getType()).NonConstVolatile().Pointer()
112 .Const().Char())
114 return true;
116 auto init = decl->getAnyInitializer();
117 if (init == nullptr) {
118 return true;
120 if (init->isInstantiationDependent()) {
121 // avoid problems with isCXX11ConstantExpr in template code
122 return true;
124 APValue v;
125 if (!init->isCXX11ConstantExpr(compiler.getASTContext(), &v)) {
126 return true;
128 vars_.insert(decl);
129 return true;
132 bool VisitDeclRefExpr(DeclRefExpr const * expr) {
133 if (!casted_.empty() && expr == casted_.top()) {
134 return true;
136 auto vd = dyn_cast<VarDecl>(expr->getDecl());
137 if (vd == nullptr) {
138 return true;
140 vars_.erase(vd->getCanonicalDecl());
141 return true;
144 private:
145 std::set<VarDecl const *> vars_;
146 std::stack<DeclRefExpr const *> casted_;
147 std::stack<bool> pushed_;
150 loplugin::Plugin::Registration<ConstStringVar> conststringvar("conststringvar");
154 #endif // LO_CLANG_SHARED_PLUGINS
156 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */