From e6cc897e29e501e1275ceb9443dc90affc585ebd Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Tue, 5 Jan 2010 21:55:33 +0100 Subject: [PATCH] Fixed #1224 (segmentation fault of cppcheck) --- lib/checkclass.cpp | 39 +++++++++++++++++++++++---------------- test/testclass.cpp | 20 +++++++++++++++++++- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 742abfc26..595607579 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -922,7 +922,14 @@ void CheckClass::operatorEqRetRefThis() static bool hasDeallocation(const Token * first, const Token * last) { - for (const Token * tok = first; tok && tok != last; tok = tok->next()) + // This function is called when no simple check was found for assignment + // to self. We are currently looking for a specific sequence of: + // deallocate member ; ... member = allocate + // This check is far from ideal because it can cause false negatives. + // Unfortunately, this is necessary to prevent false positives. + // This check needs to do careful analysis someday to get this + // correct with a high degree of certainty. + for (const Token * tok = first; tok && (tok != last); tok = tok->next()) { // check for deallocating memory if (Token::Match(tok, "{|;|, free ( %type%")) @@ -931,17 +938,17 @@ static bool hasDeallocation(const Token * first, const Token * last) // we should probably check that var is a pointer in this class - tok = tok->tokAt(4); + const Token * tok1 = tok->tokAt(4); - while (tok && tok != last) + while (tok1 && (tok1 != last)) { - if (Token::Match(tok, "%type% =")) + if (Token::Match(tok1, "%type% =")) { - if (tok->str() == var->str()) + if (tok1->str() == var->str()) return true; } - tok = tok->next(); + tok1 = tok1->next(); } } else if (Token::Match(tok, "{|;|, delete [ ] %type%")) @@ -950,17 +957,17 @@ static bool hasDeallocation(const Token * first, const Token * last) // we should probably check that var is a pointer in this class - tok = tok->tokAt(5); + const Token * tok1 = tok->tokAt(5); - while (tok && tok != last) + while (tok1 && (tok1 != last)) { - if (Token::Match(tok, "%type% = new [")) + if (Token::Match(tok1, "%type% = new [")) { - if (tok->str() == var->str()) + if (tok1->str() == var->str()) return true; } - tok = tok->next(); + tok1 = tok1->next(); } } else if (Token::Match(tok, "{|;|, delete %type%")) @@ -969,17 +976,17 @@ static bool hasDeallocation(const Token * first, const Token * last) // we should probably check that var is a pointer in this class - tok = tok->tokAt(3); + const Token * tok1 = tok->tokAt(3); - while (tok && tok != last) + while (tok1 && (tok1 != last)) { - if (Token::Match(tok, "%type% = new")) + if (Token::Match(tok1, "%type% = new")) { - if (tok->str() == var->str()) + if (tok1->str() == var->str()) return true; } - tok = tok->next(); + tok1 = tok1->next(); } } } diff --git a/test/testclass.cpp b/test/testclass.cpp index 13fb92b15..64555969a 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -145,7 +145,6 @@ private: " void operator=(const A&);\n" "};\n"); ASSERT_EQUALS("[test.cpp:3]: (style) 'operator=' should return something\n", errout.str()); - } // Check that operator Equal returns reference to this @@ -399,6 +398,25 @@ private: " return *this;\n" "}\n"); ASSERT_EQUALS("[test.cpp:7]: (possible style) 'operator=' should check for assignment to self\n", errout.str()); + + // ticket #1224 + checkOpertorEqToSelf( + "const SubTree &SubTree::operator= (const SubTree &b)\n" + "{\n" + " CodeTree *oldtree = tree;\n" + " tree = new CodeTree(*b.tree);\n" + " delete oldtree;\n" + " return *this;\n" + "}\n" + "const SubTree &SubTree::operator= (const CodeTree &b)\n" + "{\n" + " CodeTree *oldtree = tree;\n" + " tree = new CodeTree(b);\n" + " delete oldtree;\n" + " return *this;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } void operatorEqToSelf2()