[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [clazy] /: Introduce returning-data-from-temporary
From:       Sergio Martins <smartins () kde ! org>
Date:       2016-11-18 19:28:12
Message-ID: E1c7opY-0005XZ-H6 () code ! kde ! org
[Download RAW message or body]

Git commit 7c08c53449869bd8958f6de63273dec205f3ef57 by Sergio Martins.
Committed on 18/11/2016 at 19:27.
Pushed by smartins into branch 'master'.

Introduce returning-data-from-temporary

Catches stuff like return localByteArray.data() or
function().data(), which return the byte array's data before
it gets out of scope.

M  +1    -0    CMakeLists.txt
A  +12   -0    checks/level1/README-returning-data-from-temporary.md
A  +117  -0    checks/level1/returning-data-from-temporary.cpp     [License: LGPL \
(v2+)] A  +44   -0    checks/level1/returning-data-from-temporary.h     [License: \
LGPL (v2+)] M  +8    -7    tests/clazy/test_requested_checks.sh.expected
A  +7    -0    tests/returning-data-from-temporary/config.json
A  +90   -0    tests/returning-data-from-temporary/main.cpp     [License: UNKNOWN]  *
A  +3    -0    tests/returning-data-from-temporary/main.cpp.expected

The files marked with a * at the end have a non valid license. Please read: \
http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are \
listed at that page.


http://commits.kde.org/clazy/7c08c53449869bd8958f6de63273dec205f3ef57

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9783e5d..e31063f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -167,6 +167,7 @@ set(SRC_FILES
   checks/level1/qdeleteall.cpp
   checks/level1/qstring-left.cpp
   checks/level1/range-loop.cpp
+  checks/level1/returning-data-from-temporary.cpp
   checks/level1/ruleoftwosoft.cpp
   checks/level1/post-event.cpp
   checks/level2/container-inside-loop.cpp
diff --git a/checks/level1/README-returning-data-from-temporary.md \
b/checks/level1/README-returning-data-from-temporary.md new file mode 100644
index 0000000..20c7317
--- /dev/null
+++ b/checks/level1/README-returning-data-from-temporary.md
@@ -0,0 +1,12 @@
+# returning-data-from-temporary
+
+Warns when returning `QByteArray::data()` from a byte array that will soon be \
destroyed. +
+## Examples
+```
+QByteArray b = ...;
+return b.data();
+```
+```
+return funcReturningByteArray().data();
+```
diff --git a/checks/level1/returning-data-from-temporary.cpp \
b/checks/level1/returning-data-from-temporary.cpp new file mode 100644
index 0000000..b10ce8f
--- /dev/null
+++ b/checks/level1/returning-data-from-temporary.cpp
@@ -0,0 +1,117 @@
+/*
+  This file is part of the clazy static checker.
+
+  Copyright (C) 2016 Sergio Martins <smartins@kde.org>
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Library General Public
+  License as published by the Free Software Foundation; either
+  version 2 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Library General Public License for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; see the file COPYING.LIB.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+*/
+
+#include "returning-data-from-temporary.h"
+#include "Utils.h"
+#include "HierarchyUtils.h"
+#include "QtUtils.h"
+#include "TypeUtils.h"
+#include "checkmanager.h"
+
+#include <clang/AST/AST.h>
+
+using namespace clang;
+using namespace std;
+
+
+ReturningDataFromTemporary::ReturningDataFromTemporary(const std::string &name, \
const clang::CompilerInstance &ci) +    : CheckBase(name, ci)
+{
+}
+
+
+void ReturningDataFromTemporary::VisitStmt(clang::Stmt *stmt)
+{
+    auto returnStmt = dyn_cast<ReturnStmt>(stmt);
+    if (!returnStmt)
+        return;
+
+    CXXMemberCallExpr *memberCall = \
HierarchyUtils::unpeal<CXXMemberCallExpr>(HierarchyUtils::getFirstChild(returnStmt), \
HierarchyUtils::IgnoreExprWithCleanups | +                                            \
HierarchyUtils::IgnoreImplicitCasts); +    if (!memberCall)
+        return;
+
+    CXXMethodDecl *method = memberCall->getMethodDecl();
+    if (!method)
+        return;
+
+    const auto methodName = method->getQualifiedNameAsString();
+    const bool isData = methodName == "QByteArray::data";
+    const bool isConstData = methodName == "QByteArray::constData";
+
+    if (isData) {
+        handleDataCall(memberCall);
+    } else if (isConstData) {
+        handleConstDataCall();
+    }
+}
+
+void ReturningDataFromTemporary::handleDataCall(CXXMemberCallExpr *memberCall)
+{
+    // Handles:
+    // return myLocalByteArray.data();
+    // return myTemporaryByteArray().data();
+
+    // Doesn't care about constData() calls, since the byte array might be shared.
+
+    Expr *obj = memberCall->getImplicitObjectArgument();
+    Stmt *t = obj;
+    DeclRefExpr *declRef = nullptr;
+    CXXBindTemporaryExpr *temporaryExpr = nullptr;
+
+    while (t) {
+        if (dyn_cast<ImplicitCastExpr>(t)) {
+            t = HierarchyUtils::getFirstChild(t);
+            continue;
+        }
+
+        declRef = dyn_cast<DeclRefExpr>(t);
+        if (declRef)
+            break;
+
+        temporaryExpr = dyn_cast<CXXBindTemporaryExpr>(t);
+        if (temporaryExpr)
+            break;
+
+        break;
+    }
+
+    if (!temporaryExpr && !declRef)
+        return;
+
+    if (declRef) {
+        VarDecl *varDecl = dyn_cast<VarDecl>(declRef->getDecl());
+        if (!varDecl || varDecl->isStaticLocal() || \
TypeUtils::valueIsConst(varDecl->getType())) +            return;
+    } else if (temporaryExpr) {
+        if (TypeUtils::valueIsConst(temporaryExpr->getType()))
+            return;
+    }
+
+    emitWarning(memberCall, "Returning data of local QByteArray");
+}
+
+void ReturningDataFromTemporary::handleConstDataCall()
+{
+    // TODO
+}
+
+REGISTER_CHECK_WITH_FLAGS("returning-data-from-temporary", \
                ReturningDataFromTemporary, CheckLevel1)
diff --git a/checks/level1/returning-data-from-temporary.h \
b/checks/level1/returning-data-from-temporary.h new file mode 100644
index 0000000..c32011c
--- /dev/null
+++ b/checks/level1/returning-data-from-temporary.h
@@ -0,0 +1,44 @@
+/*
+  This file is part of the clazy static checker.
+
+  Copyright (C) 2016 Sergio Martins <smartins@kde.org>
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Library General Public
+  License as published by the Free Software Foundation; either
+  version 2 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Library General Public License for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; see the file COPYING.LIB.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+*/
+
+#ifndef CLAZY_RETURNING_DATA_FROM_TEMPORARY_H
+#define CLAZY_RETURNING_DATA_FROM_TEMPORARY_H
+
+#include "checkbase.h"
+
+namespace clang {
+    class CXXMemberCallExpr;
+}
+
+/**
+ * See README-returning-data-from-temporary for more info.
+ */
+class ReturningDataFromTemporary : public CheckBase
+{
+public:
+    explicit ReturningDataFromTemporary(const std::string &name, const \
clang::CompilerInstance &ci); +    void VisitStmt(clang::Stmt *stmt) override;
+private:
+    void handleDataCall(clang::CXXMemberCallExpr *memberCall);
+    void handleConstDataCall();
+};
+
+#endif
diff --git a/tests/clazy/test_requested_checks.sh.expected \
b/tests/clazy/test_requested_checks.sh.expected index 92915bf..ab07842 100644
--- a/tests/clazy/test_requested_checks.sh.expected
+++ b/tests/clazy/test_requested_checks.sh.expected
@@ -1,6 +1,6 @@
-Requested checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, rule-of-two-soft, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic +Requested \
checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, returning-data-from-temporary, \
rule-of-two-soft, temporary-iterator, unused-non-trivial-variable, \
writing-to-temporary, wrong-qglobalstatic  Invalid check: foo
-Requested checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, rule-of-two-soft, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic +Requested \
checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, returning-data-from-temporary, \
rule-of-two-soft, temporary-iterator, unused-non-trivial-variable, \
writing-to-temporary, wrong-qglobalstatic  Requested checks: foreach
 Requested checks: foreach, writing-to-temporary
 Invalid check: foo
@@ -8,16 +8,16 @@ Requested checks: foreach, writing-to-temporary
 Requested checks: old-style-connect
 Requested checks: old-style-connect
 Requested checks: foreach, old-style-connect
-Requested checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, container-inside-loop, copyable-polymorphic, \
ctor-missing-parent-argument, detaching-temporary, foreach, function-args-by-ref, \
function-args-by-value, global-const-char-pointer, implicit-casts, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, missing-typeinfo, \
mutable-container-key, non-pod-global-static, old-style-connect, post-event, \
qdatetime-utc, qdeleteall, qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, \
qstring-allocations, qstring-arg, qstring-insensitive-allocation, qstring-left, \
qstring-ref, qvariant-template-instantiation, range-loop, reserve-candidates, \
rule-of-three, rule-of-two-soft, temporary-iterator, unused-non-trivial-variable, \
virtual-call-ctor, writing-to-temporary, wrong-qglobalstatic +Requested checks: \
auto-unexpected-qstringbuilder, child-event-qobject-cast, container-anti-pattern, \
container-inside-loop, copyable-polymorphic, ctor-missing-parent-argument, \
detaching-temporary, foreach, function-args-by-ref, function-args-by-value, \
global-const-char-pointer, implicit-casts, inefficient-qlist-soft, lambda-in-connect, \
missing-qobject-macro, missing-typeinfo, mutable-container-key, \
non-pod-global-static, old-style-connect, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-allocations, \
qstring-arg, qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, reserve-candidates, \
returning-data-from-temporary, rule-of-three, rule-of-two-soft, temporary-iterator, \
unused-non-trivial-variable, virtual-call-ctor, writing-to-temporary, \
wrong-qglobalstatic  Requested checks: implicit-casts
 Requested checks: foreach, implicit-casts
 Requested checks: old-style-connect
 Requested checks: container-anti-pattern, lambda-in-connect, mutable-container-key, \
qdatetime-utc, qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-ref, qvariant-template-instantiation, \
temporary-iterator, unused-non-trivial-variable, writing-to-temporary, \
                wrong-qglobalstatic
-Requested checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, rule-of-two-soft, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic +Requested \
checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, returning-data-from-temporary, \
rule-of-two-soft, temporary-iterator, unused-non-trivial-variable, \
writing-to-temporary, wrong-qglobalstatic  Requested checks: container-anti-pattern, \
lambda-in-connect, mutable-container-key, qdatetime-utc, qenums, qfileinfo-exists, \
qgetenv, qmap-with-pointer-key, qstring-arg, qstring-insensitive-allocation, \
qstring-ref, qvariant-template-instantiation, reserve-candidates, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic  Requested \
checks: container-anti-pattern, lambda-in-connect, mutable-container-key, \
qdatetime-utc, qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-ref, qvariant-template-instantiation, \
temporary-iterator, unused-non-trivial-variable, writing-to-temporary, \
wrong-qglobalstatic  Requested checks: container-anti-pattern, foreach, \
implicit-casts, lambda-in-connect, mutable-container-key, qdatetime-utc, qenums, \
qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-ref, qvariant-template-instantiation, \
temporary-iterator, unused-non-trivial-variable, writing-to-temporary, \
                wrong-qglobalstatic
-Requested checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, rule-of-two-soft, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic +Requested \
checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, returning-data-from-temporary, \
rule-of-two-soft, temporary-iterator, unused-non-trivial-variable, \
writing-to-temporary, wrong-qglobalstatic  Requested checks: container-anti-pattern, \
lambda-in-connect, mutable-container-key, qdatetime-utc, qenums, qfileinfo-exists, \
qgetenv, qmap-with-pointer-key, qstring-arg, qstring-insensitive-allocation, \
qstring-ref, qvariant-template-instantiation, reserve-candidates, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic  Requested \
checks: container-anti-pattern, implicit-casts, lambda-in-connect, \
mutable-container-key, qdatetime-utc, qenums, qfileinfo-exists, qgetenv, \
qmap-with-pointer-key, qstring-arg, qstring-insensitive-allocation, qstring-ref, \
qvariant-template-instantiation, reserve-candidates, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic  Requested \
checks: implicit-casts @@ -56,6 +56,7 @@ Checks from level1:
     qdeleteall
     qstring-left
     range-loop
+    returning-data-from-temporary
     rule-of-two-soft
 
 Checks from level2:
@@ -96,6 +97,6 @@ Backup your code before running them.
 Requested checks: container-anti-pattern, lambda-in-connect, mutable-container-key, \
qdatetime-utc, qfileinfo-exists, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-ref, qvariant-template-instantiation, \
temporary-iterator, unused-non-trivial-variable, writing-to-temporary, \
wrong-qglobalstatic  Requested checks: implicit-casts
 Requested checks: implicit-casts
-Requested checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, rule-of-two-soft, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic +Requested \
checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qenums, qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, returning-data-from-temporary, \
rule-of-two-soft, temporary-iterator, unused-non-trivial-variable, \
writing-to-temporary, wrong-qglobalstatic  Requested checks: container-anti-pattern, \
lambda-in-connect, mutable-container-key, qdatetime-utc, qfileinfo-exists, \
qmap-with-pointer-key, qstring-arg, qstring-insensitive-allocation, qstring-ref, \
qvariant-template-instantiation, temporary-iterator, unused-non-trivial-variable, \
                writing-to-temporary, wrong-qglobalstatic
-Requested checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, rule-of-two-soft, temporary-iterator, \
unused-non-trivial-variable, writing-to-temporary, wrong-qglobalstatic +Requested \
checks: auto-unexpected-qstringbuilder, child-event-qobject-cast, \
container-anti-pattern, copyable-polymorphic, detaching-temporary, foreach, \
inefficient-qlist-soft, lambda-in-connect, missing-qobject-macro, \
mutable-container-key, non-pod-global-static, post-event, qdatetime-utc, qdeleteall, \
qfileinfo-exists, qgetenv, qmap-with-pointer-key, qstring-arg, \
qstring-insensitive-allocation, qstring-left, qstring-ref, \
qvariant-template-instantiation, range-loop, returning-data-from-temporary, \
rule-of-two-soft, temporary-iterator, unused-non-trivial-variable, \
                writing-to-temporary, wrong-qglobalstatic
diff --git a/tests/returning-data-from-temporary/config.json \
b/tests/returning-data-from-temporary/config.json new file mode 100644
index 0000000..e7e6e0c
--- /dev/null
+++ b/tests/returning-data-from-temporary/config.json
@@ -0,0 +1,7 @@
+{
+    "tests" : [
+        {
+            "filename" : "main.cpp"
+        }
+    ]
+}
diff --git a/tests/returning-data-from-temporary/main.cpp \
b/tests/returning-data-from-temporary/main.cpp new file mode 100644
index 0000000..640cc87
--- /dev/null
+++ b/tests/returning-data-from-temporary/main.cpp
@@ -0,0 +1,90 @@
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+
+QByteArray returnsByteArray()
+{
+    return QByteArray();
+}
+
+const QByteArray returnsConstByteArray()
+{
+    return QByteArray();
+}
+
+struct A
+{
+    QByteArray member;
+    const char * returnsFromMember()
+    {
+        return member.data(); // OK
+    }
+
+    const char * returnsFromMember2()
+    {
+        return member.constData(); // OK
+    }
+};
+
+const char * returnsFromLocal()
+{
+    QByteArray b;
+    return b.data(); // Warn
+}
+
+const char * returnsFromLocal2()
+{
+    QByteArray b;
+    return b.constData(); // OK
+}
+
+const char * returnsFromConstLocal()
+{
+    const QByteArray b;
+    return b.data(); // OK
+}
+
+const char * returnsFromConstLocalPtr()
+{
+    const QByteArray *b;
+    return b->data(); // OK
+}
+
+const char * returnsFromConstLocalPtr2()
+{
+    QByteArray *const b = nullptr;
+    return b->data(); // Warn
+}
+
+const char * returnsFromConstLocal2()
+{
+    const QByteArray b;
+    return b.constData(); // OK
+}
+
+const char * returnsFromStaticLocal()
+{
+    static QByteArray b;
+    return b.data(); // OK
+}
+
+const char * returnsFromStaticLocal2()
+{
+    static QByteArray b;
+    return b.constData(); // OK
+}
+
+const char * returnsFromTemporary()
+{
+    return returnsByteArray().data(); // Warn
+}
+
+const char * returnsFromTemporary2()
+{
+    return returnsConstByteArray().data(); // Ok
+}
+
+const char * returnsFromTemporary3()
+{
+    QString s;
+    return s.toUtf8().constData(); // Warn
+}
diff --git a/tests/returning-data-from-temporary/main.cpp.expected \
b/tests/returning-data-from-temporary/main.cpp.expected new file mode 100644
index 0000000..49d3312
--- /dev/null
+++ b/tests/returning-data-from-temporary/main.cpp.expected
@@ -0,0 +1,3 @@
+returning-data-from-temporary/main.cpp:31:12: warning: Returning data of local \
QByteArray [-Wclazy-returning-data-from-temporary] \
+returning-data-from-temporary/main.cpp:55:12: warning: Returning data of local \
QByteArray [-Wclazy-returning-data-from-temporary] \
+returning-data-from-temporary/main.cpp:78:12: warning: Returning data of local \
QByteArray [-Wclazy-returning-data-from-temporary]


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic