Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / convertlong.cxx
blobb706d7dffaa4632e2f6ea31a92da3cb429216a7e
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 <memory>
11 #include <cassert>
12 #include <string>
13 #include <iostream>
14 #include <fstream>
15 #include <set>
16 #include "plugin.hxx"
17 #include "check.hxx"
19 /**
20 plugin to help to when converting code from
22 sal_uIntPtr/sal_uLong/sal_Long/long/unsigned long
24 to something more precise.
26 namespace
28 class ConvertLong : public RecursiveASTVisitor<ConvertLong>, public loplugin::Plugin
30 public:
31 explicit ConvertLong(loplugin::InstantiationData const& data)
32 : Plugin(data)
36 virtual void run() override
38 std::string fn(compiler.getSourceManager()
39 .getFileEntryForID(compiler.getSourceManager().getMainFileID())
40 ->getName());
41 loplugin::normalizeDotDotInFilePath(fn);
42 // using sal_uIntPtr as in-between type when converting void* to rtl_TextEncoding
43 if (fn == SRCDIR "/sal/osl/unx/thread.cxx")
44 return;
45 // too much magic
46 if (fn == SRCDIR "/sal/rtl/alloc_arena.cxx")
47 return;
48 if (fn == SRCDIR "/sal/rtl/alloc_cache.cxx")
49 return;
50 // TODO not sure what is going on here
51 if (fn == SRCDIR "/tools/source/generic/bigint.cxx")
52 return;
53 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
56 bool VisitVarDecl(VarDecl const*);
57 bool TraverseFunctionDecl(FunctionDecl*);
59 private:
60 bool isInterestingType(QualType qt);
63 bool ConvertLong::TraverseFunctionDecl(FunctionDecl* functionDecl)
65 // ignore template stuff
66 if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
68 return true;
70 return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl);
73 bool ConvertLong::VisitVarDecl(VarDecl const* varDecl)
75 if (ignoreLocation(varDecl))
76 return true;
77 StringRef fileName{ compiler.getSourceManager().getFilename(varDecl->getLocation()) };
78 if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/bigint.hxx"))
79 return true;
80 if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/solar.h"))
81 return true;
82 if (loplugin::isSamePathname(fileName, SRCDIR "/include/o3tl/string_view.hxx"))
83 return true;
84 if (!varDecl->hasInit())
85 return true;
86 if (isa<IntegerLiteral>(varDecl->getInit()->IgnoreParenImpCasts()))
87 return true;
88 // ignore int x = -1;
89 if (isa<UnaryOperator>(varDecl->getInit()->IgnoreParenImpCasts()))
90 return true;
91 auto lhsType = varDecl->getType();
92 auto rhsType = varDecl->getInit()->IgnoreParenImpCasts()->getType();
93 if (lhsType.getLocalUnqualifiedType() == rhsType)
94 return true;
95 if (!rhsType.getTypePtrOrNull())
96 return true;
97 if (isInterestingType(rhsType))
98 return true;
99 if (!isInterestingType(lhsType))
100 return true;
101 if (rhsType->isFloatingType()) // TODO
102 return true;
103 report(DiagnosticsEngine::Warning, "rather replace type of decl %0 with %1",
104 varDecl->getLocation())
105 << lhsType << rhsType << varDecl->getSourceRange();
106 //lhsType->dump();
107 //varDecl->dump();
108 return true;
111 bool ConvertLong::isInterestingType(QualType qt)
113 auto tc = loplugin::TypeCheck(qt);
114 if (tc.Typedef())
116 TypedefType const* typedefType = qt->getAs<TypedefType>();
117 auto name = typedefType->getDecl()->getName();
118 if (name == "sal_uLong")
119 return true;
120 // because this is a typedef to long on 64-bit Linux
121 if (name == "sal_Int64" || name == "sal_uInt64" || name.find("size_t") != StringRef::npos)
122 return false;
124 if (isa<AutoType>(qt.getTypePtr()))
125 return false;
126 auto unqual = qt.getUnqualifiedType();
127 if (unqual->isSpecificBuiltinType(BuiltinType::Kind::Long)
128 || unqual->isSpecificBuiltinType(BuiltinType::Kind::ULong))
130 return true;
132 if (!tc.Typedef())
133 return false;
134 TypedefType const* typedefType = qt->getAs<TypedefType>();
135 auto name = typedefType->getDecl()->getName();
136 return name == "sal_uIntPtr" || name == "sal_IntPtr";
139 loplugin::Plugin::Registration<ConvertLong> X("convertlong", false);
142 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */