Fix #11489 Crash in TemplateSimplifier (#5020)

* Add test for #11489

* Fix #11489 Crash in TemplateSimplifier
This commit is contained in:
chrchr-github 2023-04-30 07:33:04 +02:00 committed by GitHub
parent 043f4fa621
commit 51cba8162b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 5 deletions

View File

@ -626,13 +626,26 @@ void TemplateSimplifier::deleteToken(Token *tok)
tok->deleteThis(); tok->deleteThis();
} }
bool TemplateSimplifier::removeTemplate(Token *tok) static void invalidateForwardDecls(const Token* beg, const Token* end, std::map<Token*, Token*>* forwardDecls) {
if (!forwardDecls)
return;
for (auto& fwd : *forwardDecls) {
for (const Token* tok = beg; tok != end; tok = tok->next())
if (fwd.second == tok) {
fwd.second = nullptr;
break;
}
}
}
bool TemplateSimplifier::removeTemplate(Token *tok, std::map<Token*, Token*>* forwardDecls)
{ {
if (!Token::simpleMatch(tok, "template <")) if (!Token::simpleMatch(tok, "template <"))
return false; return false;
Token *end = findTemplateDeclarationEnd(tok); Token *end = findTemplateDeclarationEnd(tok);
if (end && end->next()) { if (end && end->next()) {
invalidateForwardDecls(tok, end->next(), forwardDecls);
eraseTokens(tok, end->next()); eraseTokens(tok, end->next());
deleteToken(tok); deleteToken(tok);
return true; return true;
@ -2417,8 +2430,10 @@ static void invalidateInst(const Token* beg, const Token* end, std::vector<newIn
return; return;
for (auto& inst : *newInst) { for (auto& inst : *newInst) {
for (const Token* tok = beg; tok != end; tok = tok->next()) for (const Token* tok = beg; tok != end; tok = tok->next())
if (inst.token == tok) if (inst.token == tok) {
inst.token = nullptr; inst.token = nullptr;
break;
}
} }
} }
@ -3850,8 +3865,8 @@ void TemplateSimplifier::simplifyTemplates(
// remove forward declaration if found // remove forward declaration if found
auto it1 = mTemplateForwardDeclarationsMap.find(it->token()); auto it1 = mTemplateForwardDeclarationsMap.find(it->token());
if (it1 != mTemplateForwardDeclarationsMap.end()) if (it1 != mTemplateForwardDeclarationsMap.end())
removeTemplate(it1->second); removeTemplate(it1->second, &mTemplateForwardDeclarationsMap);
removeTemplate(it->token()); removeTemplate(it->token(), &mTemplateForwardDeclarationsMap);
} }
mTemplateDeclarations.erase(decl); mTemplateDeclarations.erase(decl);
} }

View File

@ -457,7 +457,7 @@ private:
/** /**
* Remove a specific "template < ..." template class/function * Remove a specific "template < ..." template class/function
*/ */
static bool removeTemplate(Token *tok); static bool removeTemplate(Token *tok, std::map<Token*, Token*>* forwardDecls = nullptr);
/** Syntax error */ /** Syntax error */
NORETURN static void syntaxError(const Token *tok); NORETURN static void syntaxError(const Token *tok);

View File

@ -4054,6 +4054,26 @@ private:
"b<a100<int>> d100;"; "b<a100<int>> d100;";
// don't bother checking the output because this is not instantiated properly // don't bother checking the output because this is not instantiated properly
tok(code); // don't crash tok(code); // don't crash
const char code2[] = "template<typename T> void f();\n" // #11489
"template<typename T> void f(int);\n"
"void g() {\n"
" f<int>();\n"
" f<char>(1);\n"
"}\n"
"template<typename T>\n"
"void f(int) {}\n"
"template<typename T>\n"
"void f() {\n"
" f<T>(0);\n"
"}\n";
const char exp2[] = "template < typename T > void f ( ) ; "
"void f<int> ( int ) ; "
"void f<char> ( int ) ; "
"void g ( ) { f<int> ( ) ; f<char> ( 1 ) ; } "
"void f<int> ( ) { f<int> ( 0 ) ; } "
"void f<char> ( int ) { }";
ASSERT_EQUALS(exp2, tok(code2));
} }
void template159() { // #9886 void template159() { // #9886