Skip to content

Commit a49ed56

Browse files
ludviggunnedanmar
authored andcommitted
fix #13203: FP operatorEqVarError when only pointed-to data is assigned (danmar#6911)
1 parent f1d1d6f commit a49ed56

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

lib/checkclass.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,9 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
856856
if (!Token::Match(ftok->next(), "::| %name%") &&
857857
!Token::Match(ftok->next(), "*| this . %name%") &&
858858
!Token::Match(ftok->next(), "* %name% =") &&
859-
!Token::Match(ftok->next(), "( * this ) . %name%"))
859+
!Token::Match(ftok->next(), "( * this ) . %name%") &&
860+
!Token::Match(ftok->next(), "( * %name% ) =") &&
861+
!Token::Match(ftok->next(), "* ( %name% ) ="))
860862
continue;
861863

862864
// Goto the first token in this statement..
@@ -1060,6 +1062,10 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
10601062
// Assignment of array item of member variable?
10611063
else if (Token::Match(ftok, "* %name% =")) {
10621064
assignVar(usage, ftok->next()->varId());
1065+
} else if (Token::Match(ftok, "( * %name% ) =")) {
1066+
assignVar(usage, ftok->tokAt(2)->varId());
1067+
} else if (Token::Match(ftok, "* ( %name% ) =")) {
1068+
assignVar(usage, ftok->tokAt(2)->varId());
10631069
} else if (Token::Match(ftok, "* this . %name% =")) {
10641070
assignVar(usage, ftok->tokAt(3)->varId());
10651071
} else if (astIsRangeBasedForDecl(ftok)) {

test/testclass.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class TestClass : public TestFixture {
8080
TEST_CASE(operatorEqToSelf8); // ticket #2179
8181
TEST_CASE(operatorEqToSelf9); // ticket #2592
8282

83+
TEST_CASE(operatorEqPtrAssign); // ticket #13203
84+
8385
TEST_CASE(memsetOnStruct);
8486
TEST_CASE(memsetVector);
8587
TEST_CASE(memsetOnClass);
@@ -2589,6 +2591,55 @@ class TestClass : public TestFixture {
25892591
ASSERT_EQUALS("", errout_str());
25902592
}
25912593

2594+
#define checkConstructors(code) checkConstructors_(code, __FILE__, __LINE__)
2595+
template<size_t size>
2596+
void checkConstructors_(const char (&code)[size], const char* file, int line) {
2597+
const Settings settings = settingsBuilder().severity(Severity::warning).build();
2598+
2599+
// Tokenize..
2600+
SimpleTokenizer tokenizer(settings, *this);
2601+
ASSERT_LOC(tokenizer.tokenize(code), file, line);
2602+
2603+
// Check..
2604+
CheckClass checkClass(&tokenizer, &settings, this);
2605+
(checkClass.constructors)();
2606+
}
2607+
2608+
void operatorEqPtrAssign() { // ticket #13203
2609+
checkConstructors("struct S {\n"
2610+
" int* m_data;\n"
2611+
" S() : m_data(new int()) {}\n"
2612+
" S& operator=(const S& s) {\n"
2613+
" if (&s != this) {\n"
2614+
" *(m_data) = *(s.m_data);\n"
2615+
" }\n"
2616+
" return *this;\n"
2617+
" }\n"
2618+
"};\n");
2619+
ASSERT_EQUALS("", errout_str());
2620+
2621+
checkConstructors("struct S {\n"
2622+
" int* m_data;\n"
2623+
" S() : m_data(new int()) {}\n"
2624+
" S& operator=(const S& s) {\n"
2625+
" if (&s != this) {\n"
2626+
" (*m_data) = *(s.m_data);\n"
2627+
" }\n"
2628+
" return *this;\n"
2629+
" }\n"
2630+
"};\n");
2631+
ASSERT_EQUALS("", errout_str());
2632+
2633+
checkConstructors("struct S {\n"
2634+
" int* m_data;\n"
2635+
" S() : m_data(new int()) {}\n"
2636+
" S& operator=(const S& s) {\n"
2637+
" return *this;\n"
2638+
" }\n"
2639+
"};\n");
2640+
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'S::m_data' is not assigned a value in 'S::operator='.\n", errout_str());
2641+
}
2642+
25922643
// Check that base classes have virtual destructors
25932644
#define checkVirtualDestructor(...) checkVirtualDestructor_(__FILE__, __LINE__, __VA_ARGS__)
25942645
template<size_t size>

0 commit comments

Comments
 (0)