1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
9 #ifndef LO_CLANG_SHARED_PLUGINS
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).
24 public loplugin::FilteringPlugin
<ConstStringVar
>
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
{
38 DiagnosticsEngine::Warning
,
39 "variable is only used as rvalue, should be const",
41 << v
->getSourceRange();
46 if (preRun() && TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl())) {
51 bool PreTraverseImplicitCastExpr(ImplicitCastExpr
* expr
) {
53 switch (expr
->getCastKind()) {
55 // OString CharPtrDetector ctor:
57 loplugin::TypeCheck(expr
->getType()).Const().Pointer().Const()
60 case CK_LValueToRValue
:
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()) {
83 bool PostTraverseImplicitCastExpr(ImplicitCastExpr
*, bool) {
84 bool pushed
= pushed_
.top();
91 bool TraverseImplicitCastExpr(ImplicitCastExpr
* expr
) {
93 if (PreTraverseImplicitCastExpr(expr
))
95 ret
= FilteringPlugin::TraverseImplicitCastExpr(expr
);
96 PostTraverseImplicitCastExpr(expr
, ret
);
101 bool VisitVarDecl(VarDecl
const * decl
) {
102 if (ignoreLocation(decl
)) {
105 if (decl
!= decl
->getCanonicalDecl()) {
108 if (isa
<ParmVarDecl
>(decl
) || loplugin::hasExternalLinkage(decl
)) {
111 if (!loplugin::TypeCheck(decl
->getType()).NonConstVolatile().Pointer()
116 auto init
= decl
->getAnyInitializer();
117 if (init
== nullptr) {
120 if (init
->isInstantiationDependent()) {
121 // avoid problems with isCXX11ConstantExpr in template code
125 if (!init
->isCXX11ConstantExpr(compiler
.getASTContext(), &v
)) {
132 bool VisitDeclRefExpr(DeclRefExpr
const * expr
) {
133 if (!casted_
.empty() && expr
== casted_
.top()) {
136 auto vd
= dyn_cast
<VarDecl
>(expr
->getDecl());
140 vars_
.erase(vd
->getCanonicalDecl());
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: */