diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /compilerplugins/clang/stringconcatauto.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compilerplugins/clang/stringconcatauto.cxx')
-rw-r--r-- | compilerplugins/clang/stringconcatauto.cxx | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/compilerplugins/clang/stringconcatauto.cxx b/compilerplugins/clang/stringconcatauto.cxx new file mode 100644 index 000000000..c7460cfcc --- /dev/null +++ b/compilerplugins/clang/stringconcatauto.cxx @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +/* +This is a compile check. + +Warns about 'auto' declarations becoming rtl::OUStringConcat, such as +auto str = "string" + OUString::number( 10 ); +The type of the expression is rtl::OUStringConcat and those refer to temporaries +and so their lifecycle should not extend the lifecycle of those temporaries. +*/ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "check.hxx" + +namespace loplugin +{ + +class StringConcatAuto + : public FilteringPlugin< StringConcatAuto > + { + public: + StringConcatAuto( const InstantiationData& data ); + virtual void run() override; + bool shouldVisitTemplateInstantiations () const { return true; } + bool VisitVarDecl( const VarDecl* decl ); + bool VisitFunctionDecl( const FunctionDecl* decl ); + private: + enum class Check { Var, Return }; + bool checkDecl( const DeclaratorDecl* decl, const QualType type, const SourceRange& range, Check check ); + }; + +StringConcatAuto::StringConcatAuto( const InstantiationData& data ) + : FilteringPlugin( data ) + { + } + +void StringConcatAuto::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool StringConcatAuto::VisitVarDecl( const VarDecl* decl ) + { + return checkDecl( decl, decl->getType(), + decl->getTypeSourceInfo() + ? decl->getTypeSourceInfo()->getTypeLoc().getSourceRange() + : decl->getSourceRange(), + Check::Var ); + } + +bool StringConcatAuto::VisitFunctionDecl( const FunctionDecl* decl ) + { + return checkDecl( decl, decl->getReturnType(), decl->getReturnTypeSourceRange(), Check::Return ); + } + +bool StringConcatAuto::checkDecl( const DeclaratorDecl* decl, QualType type, const SourceRange& range, Check check ) + { + if( ignoreLocation( decl )) + return true; + if( isa< ParmVarDecl >( decl )) // parameters should be fine, temporaries should exist during the call + return true; + std::string fileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(compat::getBeginLoc(decl))).str(); + loplugin::normalizeDotDotInFilePath(fileName); + if (loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/string.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/ustring.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/strbuf.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/ustrbuf.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/stringconcat.hxx")) + return true; + auto const tc = loplugin::TypeCheck( type.getNonReferenceType().getCanonicalType()); + const char* typeString = nullptr; + if( tc.Struct("OUStringConcat").Namespace("rtl").GlobalNamespace()) + typeString = "OUString"; + else if( tc.Struct("OStringConcat").Namespace("rtl").GlobalNamespace()) + typeString = "OString"; + else if( tc.Struct("OUStringNumber").Namespace("rtl").GlobalNamespace()) + typeString = "OUString"; + else if( tc.Struct("OStringNumber").Namespace("rtl").GlobalNamespace()) + typeString = "OString"; + else + return true; + report( DiagnosticsEngine::Warning, + check == Check::Var + ? "creating a variable of type %0 will make it reference temporaries" + : "returning a variable of type %0 will make it reference temporaries", + decl->getLocation()) + << type; + report( DiagnosticsEngine::Note, + "use %0 instead", + range.getBegin()) + << typeString + << FixItHint::CreateReplacement( range, typeString ); + return true; + } + +static Plugin::Registration< StringConcatAuto > stringconcatauto( "stringconcatauto" ); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |