diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 691e89308..373109da3 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -1560,6 +1560,7 @@ void TemplateSimplifier::expandTemplate( if (itype < typeParametersInDeclaration.size() && (!isVariable || !Token::Match(typeParametersInDeclaration[itype]->previous(), "<|, %type% >|,"))) { typeindentlevel = 0; + std::stack brackets1; // holds "(" and "{" tokens for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token; typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>")); typetok = typetok->next()) { @@ -1572,10 +1573,26 @@ void TemplateSimplifier::expandTemplate( else if (typeindentlevel > 0 && typetok->str() == ">") --typeindentlevel; dst->insertToken(typetok->str(), typetok->originalName(), true); - dst->previous()->isTemplateArg(true); - dst->previous()->isSigned(typetok->isSigned()); - dst->previous()->isUnsigned(typetok->isUnsigned()); - dst->previous()->isLong(typetok->isLong()); + Token *previous = dst->previous(); + previous->isTemplateArg(true); + previous->isSigned(typetok->isSigned()); + previous->isUnsigned(typetok->isUnsigned()); + previous->isLong(typetok->isLong()); + if (previous->str() == "{") { + brackets1.push(previous); + } else if (previous->str() == "(") { + brackets1.push(previous); + } else if (previous->str() == "}") { + assert(brackets1.empty() == false); + assert(brackets1.top()->str() == "{"); + Token::createMutualLinks(brackets1.top(), previous); + brackets1.pop(); + } else if (previous->str() == ")") { + assert(brackets1.empty() == false); + assert(brackets1.top()->str() == "("); + Token::createMutualLinks(brackets1.top(), previous); + brackets1.pop(); + } } } else { if (isSpecialization && !copy && !scope.empty() && Token::Match(start, (scope + templateDeclarationNameToken->str()).c_str())) { diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index df970843c..42666cdb3 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -234,6 +234,7 @@ private: TEST_CASE(garbageCode201); // #8873 TEST_CASE(garbageCode202); // #8907 TEST_CASE(garbageCode203); // #8972 + TEST_CASE(garbageCode204); TEST_CASE(garbageCodeFuzzerClientMode1); // test cases created with the fuzzer client, mode 1 @@ -1593,6 +1594,10 @@ private: ASSERT_THROW(checkCode("{ template class b { } template <> template c() b::e() { } template b; }"), InternalError); } + void garbageCode204() { + checkCode("template ()> c; template a as() {} as>();"); + } + void syntaxErrorFirstToken() { ASSERT_THROW(checkCode("&operator(){[]};"), InternalError); // #7818 ASSERT_THROW(checkCode("*(*const<> (size_t); foo) { } *(*const (size_t)() ; foo) { }"), InternalError); // #6858