From 958dfeb3b532a9df1c582d07985f5e510c01f093 Mon Sep 17 00:00:00 2001 From: chrchr Date: Fri, 28 Apr 2023 16:07:26 +0200 Subject: [PATCH 1/2] Add test for #11489 --- test/testsimplifytemplate.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 4307e45c7c4..69dd7ab5f2a 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -4054,6 +4054,26 @@ class TestSimplifyTemplate : public TestFixture { "b> d100;"; // don't bother checking the output because this is not instantiated properly tok(code); // don't crash + + const char code2[] = "template void* allocateCell(Heap&);\n" + "template void* allocateCell(Heap&, size_t);\n" + "JSRopeString* createNull(VM& vm) {\n" + " JSRopeString* newString = new (NotNull, allocateCell(vm.heap)) JSRopeString(vm);\n" + " return newString;\n" + "}\n" + "JSFinalObject* create(VM& vm, Structure* structure) {\n" + " JSFinalObject* finalObject = new (NotNull, allocateCell(vm.heap, allocationSize(structure->inlineCapacity()))) JSFinalObject(vm, structure);\n" + " return finalObject;\n" + "}\n" + "template\n" + "void* allocateCell(Heap& heap, size_t size) {\n" + " return 0;\n" + "}\n" + "template\n" + "void* allocateCell(Heap& heap) {\n" + " return allocateCell(heap, sizeof(T));\n" + "}\n"; + tok(code2); } void template159() { // #9886 From 672b6b479b0092d80ab796f67b0e7d4beac6d4ab Mon Sep 17 00:00:00 2001 From: chrchr Date: Fri, 28 Apr 2023 17:33:16 +0200 Subject: [PATCH 2/2] Fix #11489 Crash in TemplateSimplifier --- lib/templatesimplifier.cpp | 23 +++++++++++++++++++---- lib/templatesimplifier.h | 2 +- test/testsimplifytemplate.cpp | 30 +++++++++++++++--------------- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 8b4a0fa1c3b..0beb610d147 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -626,13 +626,26 @@ void TemplateSimplifier::deleteToken(Token *tok) tok->deleteThis(); } -bool TemplateSimplifier::removeTemplate(Token *tok) +static void invalidateForwardDecls(const Token* beg, const Token* end, std::map* 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* forwardDecls) { if (!Token::simpleMatch(tok, "template <")) return false; Token *end = findTemplateDeclarationEnd(tok); if (end && end->next()) { + invalidateForwardDecls(tok, end->next(), forwardDecls); eraseTokens(tok, end->next()); deleteToken(tok); return true; @@ -2417,8 +2430,10 @@ static void invalidateInst(const Token* beg, const Token* end, std::vectornext()) - if (inst.token == tok) + if (inst.token == tok) { inst.token = nullptr; + break; + } } } @@ -3850,8 +3865,8 @@ void TemplateSimplifier::simplifyTemplates( // remove forward declaration if found auto it1 = mTemplateForwardDeclarationsMap.find(it->token()); if (it1 != mTemplateForwardDeclarationsMap.end()) - removeTemplate(it1->second); - removeTemplate(it->token()); + removeTemplate(it1->second, &mTemplateForwardDeclarationsMap); + removeTemplate(it->token(), &mTemplateForwardDeclarationsMap); } mTemplateDeclarations.erase(decl); } diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index a454b092e88..b0e373bf349 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -457,7 +457,7 @@ class CPPCHECKLIB TemplateSimplifier { /** * Remove a specific "template < ..." template class/function */ - static bool removeTemplate(Token *tok); + static bool removeTemplate(Token *tok, std::map* forwardDecls = nullptr); /** Syntax error */ NORETURN static void syntaxError(const Token *tok); diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 69dd7ab5f2a..e3db648b02b 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -4055,25 +4055,25 @@ class TestSimplifyTemplate : public TestFixture { // don't bother checking the output because this is not instantiated properly tok(code); // don't crash - const char code2[] = "template void* allocateCell(Heap&);\n" - "template void* allocateCell(Heap&, size_t);\n" - "JSRopeString* createNull(VM& vm) {\n" - " JSRopeString* newString = new (NotNull, allocateCell(vm.heap)) JSRopeString(vm);\n" - " return newString;\n" - "}\n" - "JSFinalObject* create(VM& vm, Structure* structure) {\n" - " JSFinalObject* finalObject = new (NotNull, allocateCell(vm.heap, allocationSize(structure->inlineCapacity()))) JSFinalObject(vm, structure);\n" - " return finalObject;\n" + const char code2[] = "template void f();\n" // #11489 + "template void f(int);\n" + "void g() {\n" + " f();\n" + " f(1);\n" "}\n" "template\n" - "void* allocateCell(Heap& heap, size_t size) {\n" - " return 0;\n" - "}\n" + "void f(int) {}\n" "template\n" - "void* allocateCell(Heap& heap) {\n" - " return allocateCell(heap, sizeof(T));\n" + "void f() {\n" + " f(0);\n" "}\n"; - tok(code2); + const char exp2[] = "template < typename T > void f ( ) ; " + "void f ( int ) ; " + "void f ( int ) ; " + "void g ( ) { f ( ) ; f ( 1 ) ; } " + "void f ( ) { f ( 0 ) ; } " + "void f ( int ) { }"; + ASSERT_EQUALS(exp2, tok(code2)); } void template159() { // #9886