aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergio Martins <smartins@kde.org>2019-05-12 16:49:25 +0100
committerSergio Martins <smartins@kde.org>2019-05-12 16:49:25 +0100
commitd1cb8a0e5d8dc9932e75e16b79a5b93aee5f129e (patch)
tree29fa3195d801b805cbdca32f620499e778f51819
parente1c8faffca38256ad27cd13c2d8e33c92c092b79 (diff)
Introduce heap-allocated-small-trivial-type
Catches heap-allocating small trivially copyable/destructible types. Such as: auto p = new QPoint(); Could contain false-positives, hence going to manual level.
-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-heap-allocated-small-trivial-type.md9
-rw-r--r--readmes.cmake1
-rw-r--r--src/Checks.h2
-rw-r--r--src/checks/manuallevel/heap-allocated-small-trivial-type.cpp58
-rw-r--r--src/checks/manuallevel/heap-allocated-small-trivial-type.h39
-rw-r--r--tests/heap-allocated-small-trivial-type/config.json7
-rw-r--r--tests/heap-allocated-small-trivial-type/main.cpp37
-rw-r--r--tests/heap-allocated-small-trivial-type/main.cpp.expected1
12 files changed, 164 insertions, 0 deletions
diff --git a/Changelog b/Changelog
index 2c923d06..65f604ff 100644
--- a/Changelog
+++ b/Changelog
@@ -107,6 +107,8 @@
* v1.6 (, 2019)
+ - New Checks:
+ - heap-allocated-small-trivial-type
- Moved all level3 checks to manual level. Doesn't make sense to enable all of them. Each one must be
carefully considered.
- Fixit infrastructure was overhauled
diff --git a/CheckSources.cmake b/CheckSources.cmake
index 5f8d3d62..cb541688 100644
--- a/CheckSources.cmake
+++ b/CheckSources.cmake
@@ -2,6 +2,7 @@ set(CLAZY_CHECKS_SRCS ${CLAZY_CHECKS_SRCS}
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/assert-with-side-effects.cpp
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/container-inside-loop.cpp
${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/detaching-member.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/src/checks/manuallevel/heap-allocated-small-trivial-type.cpp
${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
diff --git a/README.md b/README.md
index 4c13b628..538a6518 100644
--- a/README.md
+++ b/README.md
@@ -218,6 +218,7 @@ clazy runs all checks from level1 by default.
- [assert-with-side-effects](docs/checks/README-assert-with-side-effects.md)
- [container-inside-loop](docs/checks/README-container-inside-loop.md)
- [detaching-member](docs/checks/README-detaching-member.md)
+ - [heap-allocated-small-trivial-type](docs/checks/README-heap-allocated-small-trivial-type.md)
- [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)
diff --git a/checks.json b/checks.json
index 66ebbe1d..0b409176 100644
--- a/checks.json
+++ b/checks.json
@@ -11,6 +11,12 @@
]
},
{
+ "name" : "heap-allocated-small-trivial-type",
+ "level" : -1,
+ "categories" : ["performance"],
+ "visits_stmts" : true
+ },
+ {
"name" : "ifndef-define-typo",
"level" : -1,
"categories" : ["bug"]
diff --git a/docs/checks/README-heap-allocated-small-trivial-type.md b/docs/checks/README-heap-allocated-small-trivial-type.md
new file mode 100644
index 00000000..0996a866
--- /dev/null
+++ b/docs/checks/README-heap-allocated-small-trivial-type.md
@@ -0,0 +1,9 @@
+# heap-allocated-small-trivial-type
+
+Warns when you're allocating small trivially copyable/destructible types on the heap.
+Example:
+```
+ auto p = new QPoint(1, 1);
+```
+
+Unneeded memory allocations are costly.
diff --git a/readmes.cmake b/readmes.cmake
index b0dd5871..8d3953ac 100644
--- a/readmes.cmake
+++ b/readmes.cmake
@@ -2,6 +2,7 @@ SET(README_manuallevel_FILES
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-assert-with-side-effects.md
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-container-inside-loop.md
${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-detaching-member.md
+ ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-heap-allocated-small-trivial-type.md
${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
diff --git a/src/Checks.h b/src/Checks.h
index 1bb85ee5..00cb6b9c 100644
--- a/src/Checks.h
+++ b/src/Checks.h
@@ -30,6 +30,7 @@
#include "checks/manuallevel/assert-with-side-effects.h"
#include "checks/manuallevel/container-inside-loop.h"
#include "checks/manuallevel/detaching-member.h"
+#include "checks/manuallevel/heap-allocated-small-trivial-type.h"
#include "checks/manuallevel/ifndef-define-typo.h"
#include "checks/manuallevel/inefficient-qlist.h"
#include "checks/manuallevel/isempty-vs-count.h"
@@ -120,6 +121,7 @@ void CheckManager::registerChecks()
registerCheck(check<AssertWithSideEffects>("assert-with-side-effects", ManualCheckLevel, RegisteredCheck::Option_VisitsStmts));
registerCheck(check<ContainerInsideLoop>("container-inside-loop", ManualCheckLevel, RegisteredCheck::Option_VisitsStmts));
registerCheck(check<DetachingMember>("detaching-member", ManualCheckLevel, RegisteredCheck::Option_VisitsStmts));
+ registerCheck(check<HeapAllocatedSmallTrivialType>("heap-allocated-small-trivial-type", ManualCheckLevel, RegisteredCheck::Option_VisitsStmts));
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));
diff --git a/src/checks/manuallevel/heap-allocated-small-trivial-type.cpp b/src/checks/manuallevel/heap-allocated-small-trivial-type.cpp
new file mode 100644
index 00000000..a730b7c2
--- /dev/null
+++ b/src/checks/manuallevel/heap-allocated-small-trivial-type.cpp
@@ -0,0 +1,58 @@
+/*
+ This file is part of the clazy static checker.
+
+ Copyright (C) 2019 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 "heap-allocated-small-trivial-type.h"
+#include "Utils.h"
+#include "HierarchyUtils.h"
+#include "QtUtils.h"
+#include "TypeUtils.h"
+
+#include <clang/AST/AST.h>
+
+using namespace clang;
+using namespace std;
+
+
+HeapAllocatedSmallTrivialType::HeapAllocatedSmallTrivialType(const std::string &name,
+ ClazyContext *context)
+ : CheckBase(name, context)
+{
+}
+
+void HeapAllocatedSmallTrivialType::VisitStmt(clang::Stmt *stmt)
+{
+ auto newExpr = dyn_cast<CXXNewExpr>(stmt);
+ if (!newExpr || newExpr->getNumPlacementArgs() > 0) // Placement new, user probably knows what he's doing
+ return;
+
+ if (newExpr->isArray())
+ return;
+
+ QualType qualType = newExpr->getType()->getPointeeType();
+ if (TypeUtils::isSmallTrivial(m_context, qualType)) {
+ if (clazy::contains(qualType.getAsString(), "Private")) {
+ // Possibly a pimpl, forward declared in header
+ return;
+ }
+
+ emitWarning(stmt, "Don't heap-allocate small trivially copyable/destructible types: " + qualType.getAsString());
+ }
+}
diff --git a/src/checks/manuallevel/heap-allocated-small-trivial-type.h b/src/checks/manuallevel/heap-allocated-small-trivial-type.h
new file mode 100644
index 00000000..691b53e9
--- /dev/null
+++ b/src/checks/manuallevel/heap-allocated-small-trivial-type.h
@@ -0,0 +1,39 @@
+/*
+ This file is part of the clazy static checker.
+
+ Copyright (C) 2019 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_HEAP_ALLOCATED_SMALL_TRIVIAL_TYPE_H
+#define CLAZY_HEAP_ALLOCATED_SMALL_TRIVIAL_TYPE_H
+
+#include "checkbase.h"
+
+
+/**
+ * See README-heap-allocated-small-trivial-type.md for more info.
+ */
+class HeapAllocatedSmallTrivialType : public CheckBase
+{
+public:
+ explicit HeapAllocatedSmallTrivialType(const std::string &name, ClazyContext *context);
+ void VisitStmt(clang::Stmt *) override;
+private:
+};
+
+#endif
diff --git a/tests/heap-allocated-small-trivial-type/config.json b/tests/heap-allocated-small-trivial-type/config.json
new file mode 100644
index 00000000..e7e6e0cb
--- /dev/null
+++ b/tests/heap-allocated-small-trivial-type/config.json
@@ -0,0 +1,7 @@
+{
+ "tests" : [
+ {
+ "filename" : "main.cpp"
+ }
+ ]
+}
diff --git a/tests/heap-allocated-small-trivial-type/main.cpp b/tests/heap-allocated-small-trivial-type/main.cpp
new file mode 100644
index 00000000..a193d51f
--- /dev/null
+++ b/tests/heap-allocated-small-trivial-type/main.cpp
@@ -0,0 +1,37 @@
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+struct SmallTrivial
+{
+ int v;
+};
+
+struct BigTrivial
+{
+ int v[10];
+};
+
+struct NonTrivial
+{
+ int v;
+ ~NonTrivial() {}
+};
+
+struct NonTrivial2
+{
+ int v;
+ NonTrivial2() {}
+ NonTrivial2(const NonTrivial2 &) {}
+};
+
+void test()
+{
+ auto a = new SmallTrivial(); // Warn
+ auto b = new BigTrivial();
+ auto c = new NonTrivial();
+ auto d = new NonTrivial2();
+
+ auto e = new(0) SmallTrivial;
+ auto f = new SmallTrivial[100];
+
+}
diff --git a/tests/heap-allocated-small-trivial-type/main.cpp.expected b/tests/heap-allocated-small-trivial-type/main.cpp.expected
new file mode 100644
index 00000000..1a720d5e
--- /dev/null
+++ b/tests/heap-allocated-small-trivial-type/main.cpp.expected
@@ -0,0 +1 @@
+heap-allocated-small-trivial-type/main.cpp:29:14: warning: Don't heap-allocate small trivially copyable/destructible types: struct SmallTrivial [-Wclazy-heap-allocated-small-trivial-type]