1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
10 #ifndef LO_CLANG_SHARED_PLUGINS
22 // (for the rtl string classes) that can be written as just
28 class GetStr final
: public loplugin::FilteringPlugin
<GetStr
>
31 explicit GetStr(loplugin::InstantiationData
const& data
)
32 : FilteringPlugin(data
)
36 bool PreTraverseFunctionDecl(FunctionDecl
* decl
)
38 functions_
.push(decl
);
42 bool PostTraverseFunctionDecl(FunctionDecl
*, bool)
44 assert(!functions_
.empty());
49 bool TraverseFunctionDecl(FunctionDecl
* decl
)
52 if (PreTraverseFunctionDecl(decl
))
54 ret
= FilteringPlugin::TraverseFunctionDecl(decl
);
55 PostTraverseFunctionDecl(decl
, ret
);
60 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr
* expr
)
62 if (ignoreLocation(expr
))
66 if (expr
->getOperator() != OO_LessLess
)
70 assert(expr
->getNumArgs() == 2);
71 if (!loplugin::TypeCheck(expr
->getArg(0)->getType())
72 .ClassOrStruct("basic_ostream")
73 .StdNamespace()) //TODO: check template args
77 auto const arg1
= expr
->getArg(1);
78 auto const e
= dyn_cast
<CXXMemberCallExpr
>(arg1
->IgnoreParenImpCasts());
83 bool castToVoid
= false;
84 if (auto const ic
= dyn_cast
<ImplicitCastExpr
>(arg1
))
86 if (loplugin::TypeCheck(arg1
->getType()).Pointer().Void())
91 auto const t
= e
->getObjectType();
92 auto const tc
= loplugin::TypeCheck(t
);
93 if (!(tc
.Class("OString").Namespace("rtl").GlobalNamespace()
94 || tc
.Class("OUString").Namespace("rtl").GlobalNamespace()
96 && (tc
.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()
97 || tc
.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()))))
101 if (!loplugin::DeclCheck(e
->getMethodDecl()).Function("getStr"))
107 report(DiagnosticsEngine::Warning
,
108 ("suspicious use of 'getStr' on an object of type %0; the result is implicitly"
109 " cast to a void pointer in a call of 'operator <<'"),
111 << t
.getLocalUnqualifiedType() << expr
->getSourceRange();
114 if (!functions_
.empty())
116 // Filter out occurrences of `s << t.getStr()` in the implementation of
117 // `operator <<(std::basic_ostream<...> & s, T const & t)`:
118 auto const fd
= functions_
.top();
119 if (fd
->getOverloadedOperator() == OO_LessLess
)
121 assert(fd
->getNumParams() == 2);
122 if (loplugin::TypeCheck(fd
->getParamDecl(0)->getType())
125 .TemplateSpecializationClass()
126 .ClassOrStruct("basic_ostream")
127 .StdNamespace()) //TODO: check template args
130 = fd
->getParamDecl(1)->getType()->getAs
<LValueReferenceType
>())
132 auto const t3
= t2
->getPointeeType();
133 if (t3
.isConstQualified() && !t3
.isVolatileQualified()
134 && (t3
.getCanonicalType().getTypePtr()
135 == t
.getCanonicalType().getTypePtr()))
143 report(DiagnosticsEngine::Warning
,
144 ("directly use object of type %0 in a call of 'operator <<', instead of calling"
147 << t
.getLocalUnqualifiedType() << expr
->getSourceRange();
151 bool preRun() override
{ return compiler
.getLangOpts().CPlusPlus
; }
154 std::stack
<FunctionDecl
*> functions_
;
160 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
165 loplugin::Plugin::Registration
<GetStr
> getstr("getstr");
170 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */