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:
parent
0619b873d0
commit
8547ff8cc2
|
@ -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
|
||||
derivedFrom.push_back(base);
|
||||
|
|
|
@ -1755,6 +1755,8 @@ namespace {
|
|||
fullName = name;
|
||||
ScopeInfo3 *scope = parent;
|
||||
while (scope && scope->parent) {
|
||||
if (scope->name.empty())
|
||||
break;
|
||||
fullName = scope->name + " :: " + fullName;
|
||||
scope = scope->parent;
|
||||
}
|
||||
|
@ -1770,14 +1772,14 @@ namespace {
|
|||
std::set<std::string> recordTypes;
|
||||
std::set<std::string> baseTypes;
|
||||
|
||||
ScopeInfo3 *addChild(Type type, const std::string &name, const Token *bodyStart, const Token *bodyEnd) {
|
||||
children.emplace_back(this, type, name, bodyStart, bodyEnd);
|
||||
ScopeInfo3 *addChild(Type scopeType, const std::string &scopeName, const Token *bodyStartToken, const Token *bodyEndToken) {
|
||||
children.emplace_back(this, scopeType, scopeName, bodyStartToken, bodyEndToken);
|
||||
return &children.back();
|
||||
}
|
||||
|
||||
bool hasChild(const std::string &name) const {
|
||||
bool hasChild(const std::string &childName) const {
|
||||
for (const auto & child : children) {
|
||||
if (child.name == name)
|
||||
if (child.name == childName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1824,24 +1826,39 @@ namespace {
|
|||
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 * tempScope = this;
|
||||
while (tempScope) {
|
||||
// check 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;
|
||||
}
|
||||
// check siblings for same name
|
||||
if (tempScope->parent) {
|
||||
for (const auto &sibling : tempScope->parent->children) {
|
||||
if (sibling.name == tempScope->name && &sibling != this) {
|
||||
const ScopeInfo3 * temp = sibling.findInChildren(scope);
|
||||
if (temp)
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
tempScope = tempScope->parent;
|
||||
}
|
||||
// check for another scope with same name
|
||||
const ScopeInfo3 * global = this;
|
||||
while (global->parent)
|
||||
global = global->parent;
|
||||
for (const ScopeInfo3 & tempChild : global->children) {
|
||||
const ScopeInfo3 * temp = tempChild.findScopeRecursive(scope);
|
||||
if (temp)
|
||||
return temp;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -5546,20 +5546,20 @@ private:
|
|||
}
|
||||
|
||||
void const61() { // ticket #5606 - don't crash
|
||||
// this code is invalid so a false negative is OK
|
||||
checkConst("class MixerParticipant : public MixerParticipant {\n"
|
||||
" int GetAudioFrame();\n"
|
||||
"};\n"
|
||||
"int MixerParticipant::GetAudioFrame() {\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"
|
||||
" bool InitializeFileReader() {\n"
|
||||
" printf(\"music\");\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()
|
||||
// A more complete example including a template declaration like
|
||||
|
|
|
@ -65,6 +65,7 @@ private:
|
|||
TEST_CASE(simplifyUsing16);
|
||||
TEST_CASE(simplifyUsing17);
|
||||
TEST_CASE(simplifyUsing18);
|
||||
TEST_CASE(simplifyUsing19);
|
||||
|
||||
TEST_CASE(simplifyUsing8970);
|
||||
TEST_CASE(simplifyUsing8971);
|
||||
|
@ -463,6 +464,18 @@ private:
|
|||
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() {
|
||||
const char code[] = "using V = std::vector<int>;\n"
|
||||
"struct A {\n"
|
||||
|
|
Loading…
Reference in New Issue