diff options
Diffstat (limited to 'compilerplugins/clang/convertlong.cxx')
-rw-r--r-- | compilerplugins/clang/convertlong.cxx | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/compilerplugins/clang/convertlong.cxx b/compilerplugins/clang/convertlong.cxx new file mode 100644 index 000000000..87b65a43f --- /dev/null +++ b/compilerplugins/clang/convertlong.cxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <memory> +#include <cassert> +#include <string> +#include <iostream> +#include <fstream> +#include <set> +#include "config_clang.h" +#include "plugin.hxx" +#include "check.hxx" + +/** + plugin to help to when converting code from + + sal_uIntPtr/sal_uLong/sal_Long/long/unsigned long + + to something more precise. + */ +namespace +{ +class ConvertLong : public loplugin::FilteringPlugin<ConvertLong> +{ +public: + explicit ConvertLong(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // using sal_uIntPtr as in-between type when converting void* to rtl_TextEncoding + if (fn == SRCDIR "/sal/osl/unx/thread.cxx") + return; + // too much magic + if (fn == SRCDIR "/sal/rtl/alloc_arena.cxx") + return; + if (fn == SRCDIR "/sal/rtl/alloc_cache.cxx") + return; + // TODO not sure what is going on here + if (fn == SRCDIR "/tools/source/generic/bigint.cxx") + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitVarDecl(VarDecl const*); + bool TraverseFunctionDecl(FunctionDecl*); + +private: + bool isInterestingType(QualType qt); +}; + +bool ConvertLong::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + // ignore template stuff + if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + { + return true; + } + return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); +} + +bool ConvertLong::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + StringRef fileName{ getFilenameOfLocation(varDecl->getLocation()) }; + if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/bigint.hxx")) + return true; + if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/solar.h")) + return true; + if (!varDecl->hasInit()) + return true; + if (isa<IntegerLiteral>(varDecl->getInit()->IgnoreParenImpCasts())) + return true; + // ignore int x = -1; + if (isa<UnaryOperator>(varDecl->getInit()->IgnoreParenImpCasts())) + return true; + auto lhsType = varDecl->getType(); + auto rhsType = varDecl->getInit()->IgnoreParenImpCasts()->getType(); + if (lhsType.getLocalUnqualifiedType() == rhsType) + return true; + if (!rhsType.getTypePtrOrNull()) + return true; + if (isInterestingType(rhsType)) + return true; + if (!isInterestingType(lhsType)) + return true; + if (rhsType->isFloatingType()) // TODO + return true; + report(DiagnosticsEngine::Warning, "rather replace type of decl %0 with %1", + varDecl->getLocation()) + << lhsType << rhsType << varDecl->getSourceRange(); + //lhsType->dump(); + //varDecl->dump(); + return true; +} + +bool ConvertLong::isInterestingType(QualType qt) +{ + auto tc = loplugin::TypeCheck(qt); + if (tc.Typedef()) + { + TypedefType const* typedefType = qt->getAs<TypedefType>(); + auto name = typedefType->getDecl()->getName(); + if (name == "sal_uLong") + return true; + // because this is a typedef to long on 64-bit Linux + if (name == "sal_Int64" || name == "sal_uInt64" || name.find("size_t") != StringRef::npos) + return false; + } + if (isa<AutoType>(qt.getTypePtr())) + return false; + auto unqual = qt.getUnqualifiedType(); + if (unqual->isSpecificBuiltinType(BuiltinType::Kind::Long) + || unqual->isSpecificBuiltinType(BuiltinType::Kind::ULong)) + { + return true; + } + if (!tc.Typedef()) + return false; + TypedefType const* typedefType = qt->getAs<TypedefType>(); + auto name = typedefType->getDecl()->getName(); + return name == "sal_uIntPtr" || name == "sal_IntPtr"; +} + +loplugin::Plugin::Registration<ConvertLong> X("convertlong", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |