This commit is contained in:
Martin Ettl 2014-03-21 21:31:39 +01:00
commit 2b71bd6732
5 changed files with 57 additions and 6 deletions

View File

@ -2029,7 +2029,7 @@ bool Function::isImplicitlyVirtual(bool defaultVal) const
return false;
}
bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe) const
bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe, std::deque< const ::Type* > *anchestors) const
{
// check each base class
for (std::size_t i = 0; i < baseType->derivedFrom.size(); ++i) {
@ -2065,10 +2065,20 @@ bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe) const
}
if (!baseType->derivedFrom[i].type->derivedFrom.empty()) {
// avoid endless recursion, see #5289 Crash: Stack overflow in isImplicitlyVirtual_rec when checking SVN
if ((baseType != baseType->derivedFrom[i].type) && isImplicitlyVirtual_rec(baseType->derivedFrom[i].type, safe))
// avoid endless recursion, see #5289 Crash: Stack overflow in isImplicitlyVirtual_rec when checking SVN and
// #5590 with a loop within the class hierarchie.
// We do so by tracking all previously checked types in a deque.
std::deque< const ::Type* > local_anchestors;
if (!anchestors) {
anchestors=&local_anchestors;
}
anchestors->push_back(baseType);
if (std::find(anchestors->begin(), anchestors->end(), baseType->derivedFrom[i].type)==anchestors->end()) {
if (isImplicitlyVirtual_rec(baseType->derivedFrom[i].type, safe, anchestors)) {
return true;
}
}
}
} else {
// unable to find base class so assume it has no virtual function
safe = false;

View File

@ -24,6 +24,7 @@
#include <string>
#include <list>
#include <vector>
#include <deque>
#include <set>
#include <algorithm>
@ -603,7 +604,7 @@ public:
static bool argsMatch(const Scope *info, const Token *first, const Token *second, const std::string &path, unsigned int depth);
private:
bool isImplicitlyVirtual_rec(const ::Type* type, bool& safe) const;
bool isImplicitlyVirtual_rec(const ::Type* type, bool& safe, std::deque<const ::Type* > *anchestors = nullptr) const;
};
class CPPCHECKLIB Scope {

View File

@ -788,7 +788,6 @@ static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int
}
else if (Token::Match(tok2, ") {") && Token::findmatch(tok2->link(), "%varid%", tok2, varid)) {
const Token *start = tok2->link();
if (settings->debugwarnings)
bailout(tokenlist, errorLogger, tok2, "For loop variable stopping on {");
break;

View File

@ -1818,6 +1818,27 @@ private:
" }\n"
"};");
ASSERT(db && db->findScopeByName("Bar") && !db->findScopeByName("Bar")->functionList.front().isImplicitlyVirtual(false));
ASSERT_EQUALS(1, db->findScopeByName("Bar")->functionList.size());
}
// #5590
{
GET_SYMBOL_DB("class InfiniteB : InfiniteA {\n"
" class D {\n"
" };\n"
"};\n"
"namespace N {\n"
" class InfiniteA : InfiniteB {\n"
" };\n"
"}\n"
"class InfiniteA : InfiniteB {\n"
" void foo();\n"
"};\n"
"void InfiniteA::foo() {\n"
" C a;\n"
"}");
//ASSERT(db && db->findScopeByName("InfiniteA") && !db->findScopeByName("InfiniteA")->functionList.front().isImplicitlyVirtual());
TODO_ASSERT_EQUALS(1, 0, db->findScopeByName("InfiniteA")->functionList.size());
}
}

View File

@ -72,6 +72,7 @@ private:
TEST_CASE(multiFile);
TEST_CASE(unknownBaseTemplate); // ticket #2580
TEST_CASE(hierarchie_loop); // ticket 5590
}
@ -692,6 +693,25 @@ private:
ASSERT_EQUALS("", errout.str());
}
void hierarchie_loop() {
check("class InfiniteB : InfiniteA {\n"
" class D {\n"
" };\n"
"};\n"
"namespace N {\n"
" class InfiniteA : InfiniteB {\n"
" };\n"
"}\n"
"class InfiniteA : InfiniteB {\n"
" void foo();\n"
"};\n"
"void InfiniteA::foo() {\n"
" C a;\n"
"}");
ASSERT_EQUALS("[test.cpp:10]: (style) Unused private function: 'InfiniteA::foo'\n", errout.str());
}
};
REGISTER_TEST(TestUnusedPrivateFunction)