diff --git a/CMakeSettings.json b/CMakeSettings.json
new file mode 100644
index 00000000000..f8e4110d54f
--- /dev/null
+++ b/CMakeSettings.json
@@ -0,0 +1,22 @@
+{
+ "configurations": [
+ {
+ "name": "x64-Debug",
+ "generator": "Ninja",
+ "configurationType": "Debug",
+ "inheritEnvironments": [ "msvc_x64_x64" ],
+ "buildRoot": "${projectDir}\\out\\build\\${name}",
+ "installRoot": "${projectDir}\\out\\install\\${name}",
+ "cmakeCommandArgs": "",
+ "buildCommandArgs": "-v",
+ "ctestCommandArgs": "",
+ "variables": [
+ {
+ "name": "BUILD_TESTS",
+ "value": "True",
+ "type": "BOOL"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/lib/checkselfassignment.cpp b/lib/checkselfassignment.cpp
new file mode 100644
index 00000000000..0df4505b51f
--- /dev/null
+++ b/lib/checkselfassignment.cpp
@@ -0,0 +1,126 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2020 Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "checkselfassignment.h"
+
+#include "astutils.h"
+#include "errorlogger.h"
+#include "library.h"
+#include "settings.h"
+#include "symboldatabase.h"
+#include "token.h"
+#include "tokenize.h"
+#include "utils.h"
+
+#include
+#include
+#include
+
+ //---------------------------------------------------------------------------
+using namespace std;
+
+// Register this check class into cppcheck by creating a static instance of it..
+namespace {
+ CheckSelfAssignment instance;
+}
+
+// CWE ID used:
+static const CWE CWE398(398U); // Indicator of Poor Code Quality
+static const CWE CWE401(401U); // Improper Release of Memory Before Removing Last Reference ('Memory Leak')
+static const CWE CWE771(771U); // Missing Reference to Active Allocated Resource
+static const CWE CWE772(772U); // Missing Release of Resource after Effective Lifetimes
+
+static const std::set deallocations_func_list = {
+ "delete", "free"
+};
+
+
+#include
+void CheckSelfAssignment::check()
+{
+ const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase();
+ for (const Scope* scope : symbolDatabase->classAndStructScopes)
+ {
+ for (const Token* tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next())
+ {
+ if (tok->str() == "operator=")
+ {
+ cout << "isassignmentOp() " << tok->isAssignmentOp() << endl;
+ auto func = tok->function();
+ if (func)
+ {
+ const Token* argTok;
+ if (Token::Match(func->argDef, "( const Bug & %name%"))
+ {
+ argTok = func->argDef->tokAt(4);
+ }
+ else
+ {
+ continue;
+ }
+ auto fieldList = func->functionScope->functionOf->varlist;
+ bool insideSelfCheckScope = false;
+ string selfCheckPattern = "if ( this != & " + argTok->str();
+ const Token* endOfSelfCheckScope = NULL;
+ for (const Token* itr = func->functionScope->bodyStart; itr && itr != func->functionScope->bodyEnd; itr = itr->next())
+ {
+
+ if (Token::Match(itr, selfCheckPattern.c_str()))
+ {
+ insideSelfCheckScope = true;
+ const Token* parenthesisTok = itr->tokAt(7);
+ if (parenthesisTok && parenthesisTok->str() == "{")
+ {
+ endOfSelfCheckScope = parenthesisTok->link();
+ }
+ else
+ {
+ const Token* iter;
+ for (iter = parenthesisTok; iter && iter->str() != ";"; iter = iter->next())
+ {}
+ if (iter)
+ {
+ endOfSelfCheckScope = iter;
+ }
+ }
+ }
+ else if (itr == endOfSelfCheckScope)
+ {
+ insideSelfCheckScope = false;
+ }
+ else if (!insideSelfCheckScope && deallocations_func_list.find(itr->str()) != deallocations_func_list.end())
+ {
+ if (itr->next() && fieldList.find(itr->next())) //ALON CONTINUE HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ selfAssignmentError(itr);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+void CheckSelfAssignment::selfAssignmentError(const Token* tok)
+{
+ reportError(tok, Severity::error, "selfAssignmentError",
+ "Assignment operator self assignment issue "
+ , CWE398, false);
+}
+
diff --git a/lib/checkselfassignment.h b/lib/checkselfassignment.h
new file mode 100644
index 00000000000..24798485fb3
--- /dev/null
+++ b/lib/checkselfassignment.h
@@ -0,0 +1,64 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2020 Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+ //---------------------------------------------------------------------------
+#ifndef checkselfassignmentH
+#define checkselfassignmentH
+//---------------------------------------------------------------------------
+
+#include "check.h"
+
+class CPPCHECKLIB CheckSelfAssignment : public Check {
+public:
+
+ /** This constructor is used when registering the CheckClass */
+ CheckSelfAssignment() : Check(myName()) {
+ }
+
+ /** This constructor is used when running checks. */
+ CheckSelfAssignment(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger)
+ : Check(myName(), tokenizer, settings, errorLogger) {
+ }
+
+ void check();
+
+ /** @brief Run checks against the normal token list */
+ void runChecks(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) OVERRIDE {
+ CheckSelfAssignment checkSelfAssignment(tokenizer, settings, errorLogger);
+ // Checks
+ checkSelfAssignment.check();
+ }
+
+ std::string classInfo() const OVERRIDE {
+ return "Assignment operator should check for self assignment";
+ }
+
+
+private:
+ void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const OVERRIDE {
+ ErrorPath errorPath;
+ CheckSelfAssignment checkSelfAssignment(nullptr, settings, errorLogger);
+ }
+
+ void selfAssignmentError(const Token* tok);
+ static std::string myName() {
+ return "CheckSelfAssignment";
+ }
+};
+
+#endif // checkselfassignmentH
\ No newline at end of file
diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj
index f4d1e87ffbe..6500caff08f 100644
--- a/lib/cppcheck.vcxproj
+++ b/lib/cppcheck.vcxproj
@@ -59,6 +59,7 @@
+
@@ -119,6 +120,7 @@
+
@@ -569,4 +571,4 @@ xcopy "$(SolutionDir)platforms" "$(OutDir)platforms" /E /I /D /Y
-
+
\ No newline at end of file
diff --git a/lib/cppcheck.vcxproj.filters b/lib/cppcheck.vcxproj.filters
index 39e2fcd8150..5f376d41558 100644
--- a/lib/cppcheck.vcxproj.filters
+++ b/lib/cppcheck.vcxproj.filters
@@ -179,6 +179,15 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -346,6 +355,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/samples/selfAssignmentOperator/bad.cpp b/samples/selfAssignmentOperator/bad.cpp
new file mode 100644
index 00000000000..ef4ba423a25
--- /dev/null
+++ b/samples/selfAssignmentOperator/bad.cpp
@@ -0,0 +1,23 @@
+#include
+#include "bad.hpp"
+
+Bug::Bug(int l) : length(l), array(new int[length])
+{
+}
+
+Bug::~Bug()
+{
+ delete[] array;
+}
+
+Bug& Bug::operator=(const Bug& rhs)
+{
+ if (this == &rhs) // Oh no, inverse condition
+ {
+ length = rhs.length;
+ delete[] array;
+ array = new int[length];
+ std::copy_n(rhs.array, length, array);
+ }
+ return *this;
+}
\ No newline at end of file
diff --git a/samples/selfAssignmentOperator/bad.hpp b/samples/selfAssignmentOperator/bad.hpp
new file mode 100644
index 00000000000..130eb0ab469
--- /dev/null
+++ b/samples/selfAssignmentOperator/bad.hpp
@@ -0,0 +1,12 @@
+#include
+class Bug
+{
+ int length;
+ int* array;
+
+public:
+ Bug(int l);
+ ~Bug();
+ Bug(const Bug& rhs) = delete;
+ Bug& operator=(const Bug& rhs);
+};
\ No newline at end of file
diff --git a/samples/selfAssignmentOperator/good.cpp b/samples/selfAssignmentOperator/good.cpp
new file mode 100644
index 00000000000..d58ba58d6eb
--- /dev/null
+++ b/samples/selfAssignmentOperator/good.cpp
@@ -0,0 +1,23 @@
+#include
+#include "bad.hpp"
+
+Bug::Bug(int l) : length(l), array(new int[length])
+{
+}
+
+Bug::~Bug()
+{
+ delete[] array;
+}
+
+Bug& Bug::operator=(const Bug& rhs)
+{
+ if (this != &rhs)
+ {
+ length = rhs.length;
+ delete[] array;
+ array = new int[length];
+ std::copy_n(rhs.array, length, array);
+ }
+ return *this;
+}
\ No newline at end of file
diff --git a/samples/selfAssignmentOperator/good.hpp b/samples/selfAssignmentOperator/good.hpp
new file mode 100644
index 00000000000..130eb0ab469
--- /dev/null
+++ b/samples/selfAssignmentOperator/good.hpp
@@ -0,0 +1,12 @@
+#include
+class Bug
+{
+ int length;
+ int* array;
+
+public:
+ Bug(int l);
+ ~Bug();
+ Bug(const Bug& rhs) = delete;
+ Bug& operator=(const Bug& rhs);
+};
\ No newline at end of file