1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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 
10 #include <string>
11 #include <set>
12 
13 #include "plugin.hxx"
14 
15 // Look for places calling std::find on a standard container where it should be using the container find method, which
16 // is more efficient.
17 //
18 // This lives in /store because the implementation is a hack and is highly dependent on the inwards
19 // of the libc++ library on the machine it runs on.
20 //
21 
22 namespace {
23 
24 class FindOnContainer:
25     public loplugin::FilteringPlugin<FindOnContainer>
26 {
27 public:
FindOnContainer(InstantiationData const & data)28     explicit FindOnContainer(InstantiationData const & data): FilteringPlugin(data) {}
29 
run()30     virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
31 
32     bool VisitCallExpr(const CallExpr * expr);
33 };
34 
VisitCallExpr(const CallExpr * expr)35 bool FindOnContainer::VisitCallExpr(const CallExpr * expr) {
36     if (ignoreLocation(expr)) {
37         return true;
38     }
39     FunctionDecl const * fdecl = expr->getDirectCallee();
40     if (fdecl == nullptr) {
41         return true;
42     }
43     std::string qname { fdecl->getQualifiedNameAsString() };
44     if (qname == "std::find")
45     {
46         std::string tname = expr->getArg(0)->getType().getAsString();
47         if (tname.find("std::_List_iterator") != std::string::npos
48             || tname.find("std::_List_const_iterator") != std::string::npos
49             || tname.find("std::vector") != std::string::npos
50             || tname.find("std::_Deque_iterator") != std::string::npos
51             || tname == "const int *"
52             || tname == "struct std::_Bit_const_iterator"
53             || tname == "const rtl::OUString *"
54             || tname == "class rtl::OUString *"
55             || tname == "const class rtl::OUString *"
56             || tname == "const sal_Int8 *"
57             || tname == "const sal_Int32 *"
58             || tname == "sal_Int32 *"
59             || tname == "sal_uInt16 *" )
60         {
61             return true;
62         }
63         expr->dump();
64         report(
65             DiagnosticsEngine::Warning,
66             ("rather use the more specific find method " + tname),
67             expr->getExprLoc());
68         return true;
69     }
70     return true;
71 }
72 
73 loplugin::Plugin::Registration< FindOnContainer > X("findoncontainer");
74 
75 }
76 
77 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
78