Skip to content

Commit 51cba81

Browse files
Fix #11489 Crash in TemplateSimplifier (#5020)
* Add test for #11489 * Fix #11489 Crash in TemplateSimplifier
1 parent 043f4fa commit 51cba81

3 files changed

Lines changed: 40 additions & 5 deletions

File tree

lib/templatesimplifier.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -626,13 +626,26 @@ void TemplateSimplifier::deleteToken(Token *tok)
626626
tok->deleteThis();
627627
}
628628

629-
bool TemplateSimplifier::removeTemplate(Token *tok)
629+
static void invalidateForwardDecls(const Token* beg, const Token* end, std::map<Token*, Token*>* forwardDecls) {
630+
if (!forwardDecls)
631+
return;
632+
for (auto& fwd : *forwardDecls) {
633+
for (const Token* tok = beg; tok != end; tok = tok->next())
634+
if (fwd.second == tok) {
635+
fwd.second = nullptr;
636+
break;
637+
}
638+
}
639+
}
640+
641+
bool TemplateSimplifier::removeTemplate(Token *tok, std::map<Token*, Token*>* forwardDecls)
630642
{
631643
if (!Token::simpleMatch(tok, "template <"))
632644
return false;
633645

634646
Token *end = findTemplateDeclarationEnd(tok);
635647
if (end && end->next()) {
648+
invalidateForwardDecls(tok, end->next(), forwardDecls);
636649
eraseTokens(tok, end->next());
637650
deleteToken(tok);
638651
return true;
@@ -2417,8 +2430,10 @@ static void invalidateInst(const Token* beg, const Token* end, std::vector<newIn
24172430
return;
24182431
for (auto& inst : *newInst) {
24192432
for (const Token* tok = beg; tok != end; tok = tok->next())
2420-
if (inst.token == tok)
2433+
if (inst.token == tok) {
24212434
inst.token = nullptr;
2435+
break;
2436+
}
24222437
}
24232438
}
24242439

@@ -3850,8 +3865,8 @@ void TemplateSimplifier::simplifyTemplates(
38503865
// remove forward declaration if found
38513866
auto it1 = mTemplateForwardDeclarationsMap.find(it->token());
38523867
if (it1 != mTemplateForwardDeclarationsMap.end())
3853-
removeTemplate(it1->second);
3854-
removeTemplate(it->token());
3868+
removeTemplate(it1->second, &mTemplateForwardDeclarationsMap);
3869+
removeTemplate(it->token(), &mTemplateForwardDeclarationsMap);
38553870
}
38563871
mTemplateDeclarations.erase(decl);
38573872
}

lib/templatesimplifier.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ class CPPCHECKLIB TemplateSimplifier {
457457
/**
458458
* Remove a specific "template < ..." template class/function
459459
*/
460-
static bool removeTemplate(Token *tok);
460+
static bool removeTemplate(Token *tok, std::map<Token*, Token*>* forwardDecls = nullptr);
461461

462462
/** Syntax error */
463463
NORETURN static void syntaxError(const Token *tok);

test/testsimplifytemplate.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4054,6 +4054,26 @@ class TestSimplifyTemplate : public TestFixture {
40544054
"b<a100<int>> d100;";
40554055
// don't bother checking the output because this is not instantiated properly
40564056
tok(code); // don't crash
4057+
4058+
const char code2[] = "template<typename T> void f();\n" // #11489
4059+
"template<typename T> void f(int);\n"
4060+
"void g() {\n"
4061+
" f<int>();\n"
4062+
" f<char>(1);\n"
4063+
"}\n"
4064+
"template<typename T>\n"
4065+
"void f(int) {}\n"
4066+
"template<typename T>\n"
4067+
"void f() {\n"
4068+
" f<T>(0);\n"
4069+
"}\n";
4070+
const char exp2[] = "template < typename T > void f ( ) ; "
4071+
"void f<int> ( int ) ; "
4072+
"void f<char> ( int ) ; "
4073+
"void g ( ) { f<int> ( ) ; f<char> ( 1 ) ; } "
4074+
"void f<int> ( ) { f<int> ( 0 ) ; } "
4075+
"void f<char> ( int ) { }";
4076+
ASSERT_EQUALS(exp2, tok(code2));
40574077
}
40584078

40594079
void template159() { // #9886

0 commit comments

Comments
 (0)