aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergio Martins <smartins@kde.org>2020-04-06 11:44:39 +0100
committerSergio Martins <smartins@kde.org>2020-04-06 11:44:39 +0100
commit8b171d7bc9ab789a88b8d52cbf18fb29ebc0dd04 (patch)
treebd131efc1355e8bdd42e763e8af213b10149b097
parentbe4f13112f1a92440f6b211bf89f1c429686f41b (diff)
-rw-r--r--Changelog2
-rw-r--r--CheckSources.cmake1
-rw-r--r--README.md1
-rw-r--r--checks.json6
-rw-r--r--docs/checks/README-keeping-unstable-ref.md1
-rw-r--r--readmes.cmake1
-rw-r--r--src/Checks.h2
-rw-r--r--src/checks/manuallevel/keeping-unstable-ref.cpp112
-rw-r--r--src/checks/manuallevel/keeping-unstable-ref.h41
-rw-r--r--tests/keeping-unstable-ref/config.json7
-rw-r--r--tests/keeping-unstable-ref/main.cpp29
-rw-r--r--tests/keeping-unstable-ref/main.cpp.expected0
12 files changed, 203 insertions, 0 deletions
diff --git a/Changelog b/Changelog
index eb66d1b3..66f689d8 100644
--- a/Changelog
+++ b/Changelog
@@ -125,3 +125,5 @@
- New Checks:
- overloaded signal
- qstring-arg warns when using QLatin1String::arg(int), as it casts to QChar
+
+ - <dont forget changelog entry for keeping-unstable-ref>
diff --git a/CheckSources.cmake b/CheckSources.cmake
index 46aafac1..c8569c5c 100644
--- a/CheckSources.cmake
+++ b/CheckSources.cmake
@@ -6,6 +6,7 @@ set(CLAZY_CHECKS_SRCS ${CLAZY_CHECKS_SRCS}
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/ifndef-define-typo.cpp
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/inefficient-qlist.cpp
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/isempty-vs-count.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/keeping-unstable-ref.cpp
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/qhash-with-char-pointer-key.cpp
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/qproperty-type-mismatch.cpp
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/qrequiredresult-candidates.cpp
diff --git a/README.md b/README.md
index ff4876e1..c6e126d4 100644
--- a/README.md
+++ b/README.md
@@ -221,6 +221,7 @@ clazy runs all checks from level1 by default.
- [ifndef-define-typo](docs/checks/README-ifndef-define-typo.md)
- [inefficient-qlist](docs/checks/README-inefficient-qlist.md)
- [isempty-vs-count](docs/checks/README-isempty-vs-count.md)
+ - [keeping-unstable-ref](docs/checks/README-keeping-unstable-ref.md)
- [qhash-with-char-pointer-key](docs/checks/README-qhash-with-char-pointer-key.md)
- [qproperty-type-mismatch](docs/checks/README-qproperty-type-mismatch.md)
- [qrequiredresult-candidates](docs/checks/README-qrequiredresult-candidates.md)
diff --git a/checks.json b/checks.json
index 7fed28e2..7abf3733 100644
--- a/checks.json
+++ b/checks.json
@@ -23,6 +23,12 @@
"visits_decls" : true
},
{
+ "name" : "keeping-unstable-ref",
+ "level" : -1,
+ "categories" : ["bug"],
+ "visits_stmts" : true
+ },
+ {
"name" : "ifndef-define-typo",
"level" : -1,
"categories" : ["bug"]
diff --git a/docs/checks/README-keeping-unstable-ref.md b/docs/checks/README-keeping-unstable-ref.md
new file mode 100644
index 00000000..b163ab48
--- /dev/null
+++ b/docs/checks/README-keeping-unstable-ref.md
@@ -0,0 +1 @@
+# keeping-unstable-ref
diff --git a/readmes.cmake b/readmes.cmake
index 663b2556..f6b49a45 100644
--- a/readmes.cmake
+++ b/readmes.cmake
@@ -6,6 +6,7 @@ SET(README_manuallevel_FILES
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-ifndef-define-typo.md
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-inefficient-qlist.md
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-isempty-vs-count.md
+ ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-keeping-unstable-ref.md
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qhash-with-char-pointer-key.md
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qproperty-type-mismatch.md
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qrequiredresult-candidates.md
diff --git a/src/Checks.h b/src/Checks.h
index 9ae9d580..992ba02f 100644
--- a/src/Checks.h
+++ b/src/Checks.h
@@ -34,6 +34,7 @@
#include "checks/manuallevel/ifndef-define-typo.h"
#include "checks/manuallevel/inefficient-qlist.h"
#include "checks/manuallevel/isempty-vs-count.h"
+#include "checks/manuallevel/keeping-unstable-ref.h"
#include "checks/manuallevel/qhash-with-char-pointer-key.h"
#include "checks/manuallevel/qproperty-type-mismatch.h"
#include "checks/manuallevel/qrequiredresult-candidates.h"
@@ -128,6 +129,7 @@ void CheckManager::registerChecks()
registerCheck(check<IfndefDefineTypo>("ifndef-define-typo", ManualCheckLevel, RegisteredCheck::Option_None));
registerCheck(check<InefficientQList>("inefficient-qlist", ManualCheckLevel, RegisteredCheck::Option_VisitsDecls));
registerCheck(check<IsEmptyVSCount>("isempty-vs-count", ManualCheckLevel, RegisteredCheck::Option_VisitsStmts));
+ registerCheck(check<KeepingUnstableRef>("keeping-unstable-ref", ManualCheckLevel, RegisteredCheck::Option_VisitsStmts));
registerCheck(check<QHashWithCharPointerKey>("qhash-with-char-pointer-key", ManualCheckLevel, RegisteredCheck::Option_VisitsDecls));
registerCheck(check<QPropertyTypeMismatch>("qproperty-type-mismatch", ManualCheckLevel, RegisteredCheck::Option_VisitsDecls));
registerCheck(check<QRequiredResultCandidates>("qrequiredresult-candidates", ManualCheckLevel, RegisteredCheck::Option_VisitsDecls));
diff --git a/src/checks/manuallevel/keeping-unstable-ref.cpp b/src/checks/manuallevel/keeping-unstable-ref.cpp
new file mode 100644
index 00000000..1bd3f3b0
--- /dev/null
+++ b/src/checks/manuallevel/keeping-unstable-ref.cpp
@@ -0,0 +1,112 @@
+/*
+ This file is part of the clazy static checker.
+
+ Copyright (C) 2020 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 "keeping-unstable-ref.h"
+#include "Utils.h"
+#include "HierarchyUtils.h"
+#include "QtUtils.h"
+#include "TypeUtils.h"
+#include "ClazyContext.h"
+
+#include <clang/AST/AST.h>
+
+using namespace clang;
+using namespace std;
+
+
+KeepingUnstableRef::KeepingUnstableRef(const std::string &name, ClazyContext *context)
+ : CheckBase(name, context)
+{
+}
+
+void KeepingUnstableRef::VisitStmt(clang::Stmt *stmt)
+{
+ auto subscriptOp = dyn_cast<CXXOperatorCallExpr>(stmt); // operator[]
+ if (!subscriptOp || subscriptOp->getOperator() != OO_Subscript)
+ return;
+
+ auto subscriptMethod = dyn_cast<CXXMethodDecl>(subscriptOp->getCalleeDecl());
+ if (!subscriptMethod)
+ return;
+
+ CXXRecordDecl *classDecl = subscriptMethod->getParent();
+ if (!classDecl)
+ return;
+
+ StringRef className = classDecl->getName();
+ if (className != "QMap" && className != "QList")
+ return;
+
+ //if (processDeclRefCase(subscriptOp))
+ // return;
+
+ if (processMemberAssignment(subscriptOp))
+ return;
+}
+
+bool KeepingUnstableRef::processDeclRefCase(CXXOperatorCallExpr *op)
+{
+ Stmt *s = op;
+ DeclStmt *declStmt = nullptr;
+ while (s) {
+ s = clazy::parent(m_context->parentMap, s);
+ if (!s)
+ break;
+ if ((declStmt = dyn_cast<DeclStmt>(s)))
+ break;
+ }
+
+ if (!declStmt || !declStmt->isSingleDecl())
+ return false;
+
+ auto varDecl = dyn_cast<VarDecl>(declStmt->getSingleDecl());
+ const QualType qtype = varDecl->getType();
+ if (!varDecl || (!qtype->isReferenceType() && !qtype->isPointerType())) {
+ return false;
+ }
+
+ emitWarning(op, "storing a reference to an unstable container element");
+ return true;
+}
+
+bool KeepingUnstableRef::processMemberAssignment(CXXOperatorCallExpr *op)
+{
+ Stmt *s = op;
+ BinaryOperator *binaryOp = nullptr;
+ while (s) {
+ s = clazy::parent(m_context->parentMap, s);
+ if (!s)
+ break;
+ if ((binaryOp = dyn_cast<BinaryOperator>(s)))
+ break;
+ }
+
+ if (!binaryOp || binaryOp->getOpcode() != BO_Assign)
+ return false;
+
+ const QualType qtype = binaryOp->getType();
+ if (!qtype->isPointerType()) {
+ return false;
+ }
+
+ emitWarning(op, "storing a reference to an unstable container element");
+ return true;
+}
diff --git a/src/checks/manuallevel/keeping-unstable-ref.h b/src/checks/manuallevel/keeping-unstable-ref.h
new file mode 100644
index 00000000..d236085a
--- /dev/null
+++ b/src/checks/manuallevel/keeping-unstable-ref.h
@@ -0,0 +1,41 @@
+/*
+ This file is part of the clazy static checker.
+
+ Copyright (C) 2020 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_KEEPING_UNSTABLE_REF_H
+#define CLAZY_KEEPING_UNSTABLE_REF_H
+
+#include "checkbase.h"
+
+
+/**
+ * See README-keeping-unstable-ref.md for more info.
+ */
+class KeepingUnstableRef : public CheckBase
+{
+public:
+ explicit KeepingUnstableRef(const std::string &name, ClazyContext *context);
+ void VisitStmt(clang::Stmt *) override;
+private:
+ bool processDeclRefCase(clang::CXXOperatorCallExpr *op);
+ bool processMemberAssignment(clang::CXXOperatorCallExpr *op);
+};
+
+#endif
diff --git a/tests/keeping-unstable-ref/config.json b/tests/keeping-unstable-ref/config.json
new file mode 100644
index 00000000..e7e6e0cb
--- /dev/null
+++ b/tests/keeping-unstable-ref/config.json
@@ -0,0 +1,7 @@
+{
+ "tests" : [
+ {
+ "filename" : "main.cpp"
+ }
+ ]
+}
diff --git a/tests/keeping-unstable-ref/main.cpp b/tests/keeping-unstable-ref/main.cpp
new file mode 100644
index 00000000..d5d78c57
--- /dev/null
+++ b/tests/keeping-unstable-ref/main.cpp
@@ -0,0 +1,29 @@
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+
+QMap<int, int> getMap() {
+ return {};
+}
+
+
+struct Foo {
+ int *m = nullptr;
+};
+
+void test()
+{
+ QMap<int,int> map;
+ map.insert(0, 0);
+ int &a = map[0]; // Warn
+ int b = map[0];
+
+ int &c = b; // OK
+
+ int &d = getMap()[0]; // Warn
+ //Foo f;
+ //f.m = &map[0];
+ int aa;
+ map[0] = aa;
+}
+
diff --git a/tests/keeping-unstable-ref/main.cpp.expected b/tests/keeping-unstable-ref/main.cpp.expected
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/keeping-unstable-ref/main.cpp.expected