libreoffice/compilerplugins/clang/stringconcatauto.cxx
Stephan Bergmann ce1d8e20a7 Adapt to "[ADT] Make StringRef's std::string conversion operator explicit"
...<https://github.com/llvm/llvm-project/commit/
777180a32b61070a10dd330b4f038bf24e916af1>.  This is just a quick fix to get
copmilerplugins buiding again with latest LLVM/Clang trunk.  Ideally, we should
get rid of as many of those (potentially expensive) conversions from
llvm::StringRef to std::string as possible.

Change-Id: I18e185e0022a06fd8e3b983a3c4f80e1f3b96746
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87682
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2020-01-29 14:14:04 +01:00

115 lines
4.0 KiB
C++

/* -*- 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: */