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/.
9 #ifndef LO_CLANG_SHARED_PLUGINS
22 Look for places we are using map[idx] in a bool context, which allocates an entry in the map, which is sometimes a side-effect we don't want.
27 class MapIndex
: public loplugin::FilteringPlugin
<MapIndex
>
30 explicit MapIndex(loplugin::InstantiationData
const& data
)
31 : FilteringPlugin(data
)
35 virtual void run() override
38 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
41 bool VisitImplicitCastExpr(const ImplicitCastExpr
*);
42 bool VisitMemberExpr(const MemberExpr
*);
45 bool MapIndex::VisitMemberExpr(const MemberExpr
* memberExpr
)
47 if (ignoreLocation(memberExpr
))
49 // operator bool conversion
50 auto conversionDecl
= dyn_cast
<CXXConversionDecl
>(memberExpr
->getMemberDecl());
51 if (!conversionDecl
|| !conversionDecl
->getConversionType()->isBooleanType())
53 auto operatorCall
= dyn_cast
<CXXOperatorCallExpr
>(memberExpr
->getBase()->IgnoreCasts());
56 if (operatorCall
->getOperator() != OverloadedOperatorKind::OO_Subscript
)
58 auto tc
= loplugin::TypeCheck(operatorCall
->getArg(0)->getType());
59 if (!tc
.Class("map") && !tc
.Class("unordered_map"))
61 report(DiagnosticsEngine::Warning
,
62 "will create an empty entry in the map, you sure about that, rather use count()1",
63 operatorCall
->getExprLoc());
67 bool MapIndex::VisitImplicitCastExpr(const ImplicitCastExpr
* implicitCastExpr
)
69 if (ignoreLocation(implicitCastExpr
))
74 // first cast is some kind of "ToBoolean" cast
75 auto ck
= implicitCastExpr
->getCastKind();
76 if (ck
!= CK_MemberPointerToBoolean
&& ck
!= CK_PointerToBoolean
&& ck
!= CK_IntegralToBoolean
77 && ck
!= CK_FloatingToBoolean
&& ck
!= CK_FloatingComplexToBoolean
78 && ck
!= CK_IntegralComplexToBoolean
)
81 // second cast is LValueToRValue
82 implicitCastExpr
= dyn_cast
<ImplicitCastExpr
>(implicitCastExpr
->getSubExpr());
83 if (!implicitCastExpr
)
86 if (implicitCastExpr
->getCastKind() != CK_LValueToRValue
)
88 auto operatorCall
= dyn_cast
<CXXOperatorCallExpr
>(implicitCastExpr
->getSubExpr());
91 if (operatorCall
->getOperator() != OverloadedOperatorKind::OO_Subscript
)
93 auto tc
= loplugin::TypeCheck(operatorCall
->getArg(0)->getType());
94 if (!tc
.Class("map") && !tc
.Class("unordered_map"))
96 report(DiagnosticsEngine::Warning
,
97 "will create an empty entry in the map, you sure about that, rather use count()2",
98 implicitCastExpr
->getExprLoc());
102 loplugin::Plugin::Registration
<MapIndex
> mapindex("mapindex");
106 #endif // LO_CLANG_SHARED_PLUGINS
108 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */