1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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 );<--- Class 'StringConcatAuto' has a constructor with 1 argument that is not explicit. [+]Class 'StringConcatAuto' has a constructor with 1 argument that is not explicit. Such constructors should in general be explicit for type safety reasons. Using the explicit keyword in the constructor means some mistakes when using the class can be avoided.
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: */
|