fix some hangs in daca from uninstantiated template classes derived f… (#3133)

* fix some hangs in daca from uninstantiated template classes derived from itself

* remove assertions

* fix another simplifyUsing hang

Co-authored-by: Robert Reif <reif@FX6840>
This commit is contained in:
IOBYTE 2021-02-17 12:12:49 -05:00 committed by GitHub
parent 0619b873d0
commit 8547ff8cc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 17 deletions

View File

@ -3056,7 +3056,9 @@ const Token *Type::initBaseInfo(const Token *tok, const Token *tok1)
} }
} }
base.type = classScope->check->findType(base.nameTok, classScope); const Type * baseType = classScope->check->findType(base.nameTok, enclosingScope);
if (baseType && !baseType->findDependency(this))
base.type = baseType;
// save pattern for base class name // save pattern for base class name
derivedFrom.push_back(base); derivedFrom.push_back(base);

View File

@ -1755,6 +1755,8 @@ namespace {
fullName = name; fullName = name;
ScopeInfo3 *scope = parent; ScopeInfo3 *scope = parent;
while (scope && scope->parent) { while (scope && scope->parent) {
if (scope->name.empty())
break;
fullName = scope->name + " :: " + fullName; fullName = scope->name + " :: " + fullName;
scope = scope->parent; scope = scope->parent;
} }
@ -1770,14 +1772,14 @@ namespace {
std::set<std::string> recordTypes; std::set<std::string> recordTypes;
std::set<std::string> baseTypes; std::set<std::string> baseTypes;
ScopeInfo3 *addChild(Type type, const std::string &name, const Token *bodyStart, const Token *bodyEnd) { ScopeInfo3 *addChild(Type scopeType, const std::string &scopeName, const Token *bodyStartToken, const Token *bodyEndToken) {
children.emplace_back(this, type, name, bodyStart, bodyEnd); children.emplace_back(this, scopeType, scopeName, bodyStartToken, bodyEndToken);
return &children.back(); return &children.back();
} }
bool hasChild(const std::string &name) const { bool hasChild(const std::string &childName) const {
for (const auto & child : children) { for (const auto & child : children) {
if (child.name == name) if (child.name == childName)
return true; return true;
} }
return false; return false;
@ -1824,24 +1826,39 @@ namespace {
return nullptr; return nullptr;
} }
const ScopeInfo3 * findInChildren(const std::string & scope) const {
for (const auto & child : children) {
if (child.name == scope || child.fullName == scope)
return &child;
else {
const ScopeInfo3 * temp = child.findInChildren(scope);
if (temp)
return temp;
}
}
return nullptr;
}
const ScopeInfo3 * findScope(const std::string & scope) const { const ScopeInfo3 * findScope(const std::string & scope) const {
const ScopeInfo3 * tempScope = this; const ScopeInfo3 * tempScope = this;
while (tempScope) { while (tempScope) {
// check children
for (const auto & child : tempScope->children) { for (const auto & child : tempScope->children) {
if (child.type == Record && (child.name == scope || child.fullName == scope)) if (&child != this && child.type == Record && (child.name == scope || child.fullName == scope))
return &child; return &child;
} }
tempScope = tempScope->parent; // check siblings for same name
} if (tempScope->parent) {
// check for another scope with same name for (const auto &sibling : tempScope->parent->children) {
const ScopeInfo3 * global = this; if (sibling.name == tempScope->name && &sibling != this) {
while (global->parent) const ScopeInfo3 * temp = sibling.findInChildren(scope);
global = global->parent;
for (const ScopeInfo3 & tempChild : global->children) {
const ScopeInfo3 * temp = tempChild.findScopeRecursive(scope);
if (temp) if (temp)
return temp; return temp;
} }
}
}
tempScope = tempScope->parent;
}
return nullptr; return nullptr;
} }

View File

@ -5546,20 +5546,20 @@ private:
} }
void const61() { // ticket #5606 - don't crash void const61() { // ticket #5606 - don't crash
// this code is invalid so a false negative is OK
checkConst("class MixerParticipant : public MixerParticipant {\n" checkConst("class MixerParticipant : public MixerParticipant {\n"
" int GetAudioFrame();\n" " int GetAudioFrame();\n"
"};\n" "};\n"
"int MixerParticipant::GetAudioFrame() {\n" "int MixerParticipant::GetAudioFrame() {\n"
" return 0;\n" " return 0;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::GetAudioFrame' can be static (but you may consider moving to unnamed namespace).\n", errout.str());
// this code is invalid so a false negative is OK
checkConst("class MixerParticipant : public MixerParticipant {\n" checkConst("class MixerParticipant : public MixerParticipant {\n"
" bool InitializeFileReader() {\n" " bool InitializeFileReader() {\n"
" printf(\"music\");\n" " printf(\"music\");\n"
" }\n" " }\n"
"};"); "};");
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::InitializeFileReader' can be static (but you may consider moving to unnamed namespace).\n", errout.str());
// Based on an example from SVN source code causing an endless recursion within CheckClass::isConstMemberFunc() // Based on an example from SVN source code causing an endless recursion within CheckClass::isConstMemberFunc()
// A more complete example including a template declaration like // A more complete example including a template declaration like

View File

@ -65,6 +65,7 @@ private:
TEST_CASE(simplifyUsing16); TEST_CASE(simplifyUsing16);
TEST_CASE(simplifyUsing17); TEST_CASE(simplifyUsing17);
TEST_CASE(simplifyUsing18); TEST_CASE(simplifyUsing18);
TEST_CASE(simplifyUsing19);
TEST_CASE(simplifyUsing8970); TEST_CASE(simplifyUsing8970);
TEST_CASE(simplifyUsing8971); TEST_CASE(simplifyUsing8971);
@ -463,6 +464,18 @@ private:
tok(code, false); // don't crash tok(code, false); // don't crash
} }
void simplifyUsing19() {
const char code[] = "namespace a {\n"
"using b = int;\n"
"void foo::c() { }\n"
"void foo::d() { }\n"
"void foo::e() {\n"
" using b = float;\n"
"}\n"
"}";
tok(code, false); // don't hang
}
void simplifyUsing8970() { void simplifyUsing8970() {
const char code[] = "using V = std::vector<int>;\n" const char code[] = "using V = std::vector<int>;\n"
"struct A {\n" "struct A {\n"