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/.
20 plugin to help to when converting code from
22 sal_uIntPtr/sal_uLong/sal_Long/long/unsigned long
24 to something more precise.
28 class ConvertLong
: public RecursiveASTVisitor
<ConvertLong
>, public loplugin::Plugin
31 explicit ConvertLong(loplugin::InstantiationData
const& data
)
36 virtual void run() override
38 std::string
fn(compiler
.getSourceManager()
39 .getFileEntryForID(compiler
.getSourceManager().getMainFileID())
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")
46 if (fn
== SRCDIR
"/sal/rtl/alloc_arena.cxx")
48 if (fn
== SRCDIR
"/sal/rtl/alloc_cache.cxx")
50 // TODO not sure what is going on here
51 if (fn
== SRCDIR
"/tools/source/generic/bigint.cxx")
53 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
56 bool VisitVarDecl(VarDecl
const*);
57 bool TraverseFunctionDecl(FunctionDecl
*);
60 bool isInterestingType(QualType qt
);
63 bool ConvertLong::TraverseFunctionDecl(FunctionDecl
* functionDecl
)
65 // ignore template stuff
66 if (functionDecl
->getTemplatedKind() != FunctionDecl::TK_NonTemplate
)
70 return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl
);
73 bool ConvertLong::VisitVarDecl(VarDecl
const* varDecl
)
75 if (ignoreLocation(varDecl
))
77 StringRef fileName
{ compiler
.getSourceManager().getFilename(varDecl
->getLocation()) };
78 if (loplugin::isSamePathname(fileName
, SRCDIR
"/include/tools/bigint.hxx"))
80 if (loplugin::isSamePathname(fileName
, SRCDIR
"/include/tools/solar.h"))
82 if (loplugin::isSamePathname(fileName
, SRCDIR
"/include/o3tl/string_view.hxx"))
84 if (!varDecl
->hasInit())
86 if (isa
<IntegerLiteral
>(varDecl
->getInit()->IgnoreParenImpCasts()))
89 if (isa
<UnaryOperator
>(varDecl
->getInit()->IgnoreParenImpCasts()))
91 auto lhsType
= varDecl
->getType();
92 auto rhsType
= varDecl
->getInit()->IgnoreParenImpCasts()->getType();
93 if (lhsType
.getLocalUnqualifiedType() == rhsType
)
95 if (!rhsType
.getTypePtrOrNull())
97 if (isInterestingType(rhsType
))
99 if (!isInterestingType(lhsType
))
101 if (rhsType
->isFloatingType()) // TODO
103 report(DiagnosticsEngine::Warning
, "rather replace type of decl %0 with %1",
104 varDecl
->getLocation())
105 << lhsType
<< rhsType
<< varDecl
->getSourceRange();
111 bool ConvertLong::isInterestingType(QualType qt
)
113 auto tc
= loplugin::TypeCheck(qt
);
116 TypedefType
const* typedefType
= qt
->getAs
<TypedefType
>();
117 auto name
= typedefType
->getDecl()->getName();
118 if (name
== "sal_uLong")
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
)
124 if (isa
<AutoType
>(qt
.getTypePtr()))
126 auto unqual
= qt
.getUnqualifiedType();
127 if (unqual
->isSpecificBuiltinType(BuiltinType::Kind::Long
)
128 || unqual
->isSpecificBuiltinType(BuiltinType::Kind::ULong
))
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: */