Merge branch 'master' of https://github.com/danmar/cppcheck
This commit is contained in:
commit
2b71bd6732
|
@ -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,9 +2065,19 @@ 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))
|
||||
return true;
|
||||
// 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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue