compilerplugins/clang/rangedforcopy.cxx       |    4 +
 compilerplugins/clang/reftotemp.cxx           |   87 ++++++++++++++++++++++++++
 compilerplugins/clang/test/reftotemp.cxx      |   25 +++++++
 dbaccess/source/ui/control/charsetlistbox.cxx |    2 
 solenv/CompilerTest_compilerplugins_clang.mk  |    1 
 sw/source/core/text/itrform2.cxx              |    2 
 sw/source/core/text/porlay.cxx                |    4 -
 7 files changed, 121 insertions(+), 4 deletions(-)

New commits:
commit fb745b54d223acc480a1f024c42806eadd0c5708
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Mon Nov 4 08:15:21 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Wed Nov 13 13:08:16 2024 +0100

    new loplugin:reftotemp
    
    look for places where we are taking a reference (i.e. "&") to a
    temporary object, which is misleading.
    
    Change-Id: Id0eb4dce3f1ca559f86e02edcbea3ca17bea8e76
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175978
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/compilerplugins/clang/rangedforcopy.cxx 
b/compilerplugins/clang/rangedforcopy.cxx
index 3ad407c358bb..16e7746afdcb 100644
--- a/compilerplugins/clang/rangedforcopy.cxx
+++ b/compilerplugins/clang/rangedforcopy.cxx
@@ -56,6 +56,10 @@ bool RangedForCopy::VisitCXXForRangeStmt( const 
CXXForRangeStmt* stmt )
     if (!type->isRecordType() || type->isReferenceType() || 
type->isPointerType())
         return true;
 
+    if (auto exprWithCleanups = dyn_cast<ExprWithCleanups>(varDecl->getInit()))
+        if 
(dyn_cast<CXXBindTemporaryExpr>(exprWithCleanups->getSubExpr()->IgnoreImpCasts()))
+            return true;
+
     if 
(loplugin::TypeCheck(type).Class("__bit_const_reference").StdNamespace())
     {
         // With libc++ without 
_LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL,
diff --git a/compilerplugins/clang/reftotemp.cxx 
b/compilerplugins/clang/reftotemp.cxx
new file mode 100644
index 000000000000..bd430d74fc6a
--- /dev/null
+++ b/compilerplugins/clang/reftotemp.cxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef LO_CLANG_SHARED_PLUGINS
+
+#include <cassert>
+#include <stack>
+
+#include "check.hxx"
+#include "plugin.hxx"
+#include "config_clang.h"
+
+/**
+look for places where we take a reference (i.e. "&") to a temporary value.
+
+Which is rather dodgy.
+
+*/
+namespace
+{
+class RefToTemp final : public loplugin::FilteringPlugin<RefToTemp>
+{
+public:
+    explicit RefToTemp(loplugin::InstantiationData const& data)
+        : FilteringPlugin(data)
+    {
+    }
+
+    bool VisitVarDecl(const VarDecl* varDecl)
+    {
+        if (ignoreLocation(varDecl))
+            return true;
+        // reference parameters might have a default temporary value, which is 
ok
+        if (isa<ParmVarDecl>(varDecl))
+            return true;
+        if (!varDecl->getType()->isReferenceType())
+            return true;
+        if (!varDecl->getInit())
+            return true;
+        if (!isTemporaryValue(varDecl->getInit()))
+            return true;
+        report(DiagnosticsEngine::Warning, "taking reference to temporary 
value",
+               varDecl->getBeginLoc())
+            << varDecl->getSourceRange();
+        return true;
+    }
+
+    bool isTemporaryValue(const Expr* expr)
+    {
+        if (dyn_cast<MaterializeTemporaryExpr>(expr))
+            return true;
+        if (auto exprWithCleanups = dyn_cast<ExprWithCleanups>(expr))
+            if (dyn_cast_or_null<MaterializeTemporaryExpr>(
+                    exprWithCleanups->getSubExpr()->IgnoreImpCasts()))
+                return true;
+        return false;
+    }
+
+    bool preRun() override
+    {
+        if (!compiler.getLangOpts().CPlusPlus)
+            return false;
+        return true;
+    }
+
+private:
+    void run() override
+    {
+        if (preRun())
+        {
+            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
+        }
+    }
+};
+
+loplugin::Plugin::Registration<RefToTemp> reftotemp("reftotemp");
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/compilerplugins/clang/test/reftotemp.cxx 
b/compilerplugins/clang/test/reftotemp.cxx
new file mode 100644
index 000000000000..2d5d3fd969f8
--- /dev/null
+++ b/compilerplugins/clang/test/reftotemp.cxx
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+
+namespace test1
+{
+OUString getString();
+void f()
+{
+    // expected-error@+1 {{taking reference to temporary value 
[loplugin:reftotemp]}}
+    const OUString& rToTemp = getString();
+    (void)rToTemp;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/dbaccess/source/ui/control/charsetlistbox.cxx 
b/dbaccess/source/ui/control/charsetlistbox.cxx
index f9866905c3ea..ba2f2943fcdb 100644
--- a/dbaccess/source/ui/control/charsetlistbox.cxx
+++ b/dbaccess/source/ui/control/charsetlistbox.cxx
@@ -28,7 +28,7 @@ namespace dbaui
     CharSetListBox::CharSetListBox(std::unique_ptr<weld::ComboBox> xControl)
         : m_xControl(std::move(xControl))
     {
-        for (auto const& charset : m_aCharSets)
+        for (auto const charset : m_aCharSets)
         {
             m_xControl->append_text(charset.getDisplayName());
         }
diff --git a/solenv/CompilerTest_compilerplugins_clang.mk 
b/solenv/CompilerTest_compilerplugins_clang.mk
index f365f0050154..5ae22fc2d634 100644
--- a/solenv/CompilerTest_compilerplugins_clang.mk
+++ b/solenv/CompilerTest_compilerplugins_clang.mk
@@ -71,6 +71,7 @@ $(eval $(call 
gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
     compilerplugins/clang/test/redundantpreprocessor \
     compilerplugins/clang/test/refcounting \
     compilerplugins/clang/test/referencecasting \
+    compilerplugins/clang/test/reftotemp \
     compilerplugins/clang/test/returnconstval \
     compilerplugins/clang/test/salcall \
     compilerplugins/clang/test/sallogareas \
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 678517f029d6..96a09b14adff 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1272,7 +1272,7 @@ SwTextPortion *SwTextFormatter::WhichTextPor( 
SwTextFormatInfo &rInf ) const
                     rtl::Reference<SwXTextDocument> 
xDocumentMetadataAccess(pShell->GetBaseModel());
 
                     const css::uno::Reference<css::rdf::XResource> 
xSubject(xRet, uno::UNO_QUERY);
-                    const uno::Reference<rdf::XRepository>& xRepository =
+                    const uno::Reference<rdf::XRepository> xRepository =
                         xDocumentMetadataAccess->getRDFRepository();
                     const uno::Reference<container::XEnumeration> xEnum(
                         xRepository->getStatements(xSubject, xODF_SHADING, 
nullptr), uno::UNO_SET_THROW);
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index cc2dbd379d13..742749621ca5 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -891,7 +891,7 @@ static Color getBookmarkColor(const SwTextNode& rNode, 
const sw::mark::Bookmark*
             static uno::Reference< rdf::XURI > xODF_SHADING(
                 rdf::URI::createKnown(xContext, rdf::URIs::LO_EXT_SHADING), 
uno::UNO_SET_THROW);
 
-            const uno::Reference<rdf::XRepository>& xRepository =
+            const uno::Reference<rdf::XRepository> xRepository =
                 xModel->getRDFRepository();
             const uno::Reference<container::XEnumeration> xEnum(
                 xRepository->getStatements(xSubject, xODF_SHADING, nullptr), 
uno::UNO_SET_THROW);
@@ -935,7 +935,7 @@ static OUString getBookmarkType(const SwTextNode& rNode, 
const sw::mark::Bookmar
 
             uno::Reference<rdf::XDocumentMetadataAccess> 
xDocumentMetadataAccess(
                 pShell->GetBaseModel());
-            const uno::Reference<rdf::XRepository>& xRepository =
+            const uno::Reference<rdf::XRepository> xRepository =
                 xDocumentMetadataAccess->getRDFRepository();
             const uno::Reference<container::XEnumeration> xEnum(
                 xRepository->getStatements(xSubject, xODF_PREFIX, nullptr), 
uno::UNO_SET_THROW);

Reply via email to