1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
16 // Find places where we are returning a pointer to something, where we can be returning a reference.
21 // X* getX() { return &x; }
24 // X& getX() { return x; }
29 public RecursiveASTVisitor
<ReturnByRef
>, public loplugin::Plugin
32 explicit ReturnByRef(InstantiationData
const & data
): Plugin(data
) {}
34 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
36 bool VisitCXXMethodDecl(const CXXMethodDecl
* decl
);
39 bool ReturnByRef::VisitCXXMethodDecl(const CXXMethodDecl
* functionDecl
) {
40 if (ignoreLocation(functionDecl
)) {
43 if (functionDecl
->isVirtual()) {
46 if (!functionDecl
->isInstance()) {
49 if (!functionDecl
->hasBody()) {
52 // ignore stuff that forms part of the stable URE interface
53 if (isInUnoIncludeFile(compiler
.getSourceManager().getSpellingLoc(
54 functionDecl
->getCanonicalDecl()->getNameInfo().getLoc()))) {
57 QualType t1
{ compat::getReturnType(*functionDecl
) };
58 if (!t1
->isPointerType()) {
62 // operator vcl::Window *(){ return &m_rWindow; }
63 if (dyn_cast
< CXXConversionDecl
>( functionDecl
) != nullptr) {
68 The AST here looks like:
76 const CompoundStmt
* compoundStmt
= dyn_cast
< CompoundStmt
>( functionDecl
->getBody() );
77 if (compoundStmt
== nullptr || compoundStmt
->body_begin() == compoundStmt
->body_end()) {
80 const ReturnStmt
* returnStmt
= dyn_cast
<ReturnStmt
>(*compoundStmt
->child_begin());
81 if (returnStmt
== nullptr) {
85 const Stmt
* nextStmt
= dyn_cast
<Expr
>(*returnStmt
->child_begin())->IgnoreParens();
86 const UnaryOperator
* unaryOperator
= dyn_cast
<UnaryOperator
>(nextStmt
);
87 if (unaryOperator
== nullptr || unaryOperator
->getOpcode() != UO_AddrOf
) {
91 nextStmt
= dyn_cast
<Expr
>(*unaryOperator
->child_begin())->IgnoreParens();
92 const MemberExpr
* memberExpr
= dyn_cast
<MemberExpr
>(nextStmt
);
93 if (memberExpr
== nullptr) {
97 nextStmt
= dyn_cast
<Expr
>(*memberExpr
->child_begin())->IgnoreParens();
98 const CXXThisExpr
* cXXThisExpr
= dyn_cast
<CXXThisExpr
>(nextStmt
);
99 if (cXXThisExpr
== nullptr) {
104 DiagnosticsEngine::Warning
,
105 "rather return by reference",
106 functionDecl
->getSourceRange().getBegin())
107 << functionDecl
->getSourceRange();
108 // display the location of the class member declaration so I don't have to search for it by hand
110 DiagnosticsEngine::Note
,
111 "rather return by reference",
112 functionDecl
->getCanonicalDecl()->getSourceRange().getBegin())
113 << functionDecl
->getCanonicalDecl()->getSourceRange();
118 loplugin::Plugin::Registration
< ReturnByRef
> X("returnbyref");
122 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */