bump product version to 6.3.0.0.beta1
[LibreOffice.git] / compilerplugins / clang / store / returnbyref.cxx
blob697ab752909dd4e06eaf193bd56285e80756e80a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <string>
11 #include <set>
13 #include "plugin.hxx"
15 // Find places where we are returning a pointer to something, where we can be returning a reference.
16 // e.g.
17 // class A {
18 // struct X x;
19 // public:
20 // X* getX() { return &x; }
21 // }
22 // which can be:
23 // X& getX() { return x; }
25 namespace {
27 class ReturnByRef:
28 public loplugin::FilteringPlugin<ReturnByRef>
30 public:
31 explicit ReturnByRef(InstantiationData const & data): FilteringPlugin(data) {}
33 virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
35 bool VisitCXXMethodDecl(const CXXMethodDecl * decl);
36 private:
37 std::string getFilename(SourceLocation loc);
40 bool ReturnByRef::VisitCXXMethodDecl(const CXXMethodDecl * functionDecl) {
41 if (ignoreLocation(functionDecl)) {
42 return true;
44 if (functionDecl->isVirtual()) {
45 return true;
47 if (!functionDecl->isInstance()) {
48 return true;
50 if (!functionDecl->hasBody()) {
51 return true;
53 // ignore stuff that forms part of the stable URE interface
54 if (isInUnoIncludeFile(functionDecl)) {
55 return true;
57 QualType t1 { functionDecl->getReturnType() };
58 if (!t1->isPointerType()) {
59 return true;
61 // Ignore stuff like:
62 // operator vcl::Window *(){ return &m_rWindow; }
63 if (dyn_cast< CXXConversionDecl >( functionDecl ) != nullptr) {
64 return true;
67 std::string aFilename = getFilename(functionDecl->getCanonicalDecl()->getLocStart());
68 if (aFilename == SRCDIR "/include/o3tl/cow_wrapper.hxx")
70 return true;
72 if ( functionDecl->getNameAsString() == "operator->") {
73 return true;
75 std::string aFunctionName = functionDecl->getQualifiedNameAsString();
76 if (aFunctionName == "SbxValue::data") {
77 return true;
80 std::string aParentName = functionDecl->getParent()->getQualifiedNameAsString();
81 std::string fqn = aParentName + "::" + functionDecl->getNameAsString();
82 if (aFilename == "TextCharAttribList::GetAttrib") {
83 return true;
84 }*/
87 The AST here looks like:
88 -CompoundStmt
89 `-ReturnStmt
90 `-UnaryOperator
93 const CompoundStmt* compoundStmt = dyn_cast< CompoundStmt >( functionDecl->getBody() );
94 if (compoundStmt == nullptr || compoundStmt->body_begin() == compoundStmt->body_end()) {
95 return true;
97 const ReturnStmt* returnStmt = dyn_cast<ReturnStmt>(*compoundStmt->child_begin());
98 if (returnStmt == nullptr) {
99 return true;
102 const Stmt* nextStmt = dyn_cast<Expr>(*returnStmt->child_begin())->IgnoreParens();
103 const UnaryOperator* unaryOperator = dyn_cast<UnaryOperator>(nextStmt);
104 if (unaryOperator == nullptr || unaryOperator->getOpcode() != UO_AddrOf) {
105 return true;
107 nextStmt->dump();
108 report(
109 DiagnosticsEngine::Warning,
110 "rather return by reference ",
111 functionDecl->getSourceRange().getBegin())
112 << functionDecl->getSourceRange();
114 // display the location of the class member declaration so I don't have to search for it by hand
115 auto otherLoc = functionDecl->getCanonicalDecl()->getSourceRange().getBegin();
116 if (otherLoc != functionDecl->getSourceRange().getBegin())
118 report(
119 DiagnosticsEngine::Note,
120 "rather return by reference",
121 functionDecl->getCanonicalDecl()->getSourceRange().getBegin())
122 << functionDecl->getCanonicalDecl()->getSourceRange();
125 return true;
128 std::string ReturnByRef::getFilename(SourceLocation loc)
130 SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc);
131 return compiler.getSourceManager().getFilename(spellingLocation);
134 loplugin::Plugin::Registration< ReturnByRef > X("returnbyref");
138 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */