From 5efb23ffff8f395802ce63258248ce84961d2723 Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Thu, 23 May 2019 14:53:26 -0400 Subject: [PATCH] template simplifier: fix instantiation of variadic template with no arguments (#1848) * template simplifier: fix instantiation of variadic template with no arguments * fix white space change * add support for * add variadic template flag --- lib/templatesimplifier.cpp | 11 +++++++++-- lib/templatesimplifier.h | 8 ++++++++ test/testsimplifytemplate.cpp | 11 +++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index ef232d5d3..fb3cafd69 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -82,6 +82,10 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *tok, const std::string &s, isPartialSpecialization(!isSpecialization() && nameToken->strAt(1) == "<"); isAlias(paramEnd->strAt(1) == "using"); isClass(Token::Match(paramEnd->next(), "class|struct|union %name% <|{|:|;")); + if (token->strAt(1) == "<" && !isSpecialization()) { + const Token *end = token->next()->findClosingBracket(); + isVariadic(end && Token::findmatch(token->tokAt(2), "typename|class . . .", end)); + } const Token *tok1 = nameToken->next(); if (tok1->str() == "<") { const Token *closing = tok1->findClosingBracket(); @@ -2538,7 +2542,8 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( std::list typeStringsUsedInTemplateInstantiation; std::string typeForNewName = getNewName(tok2, typeStringsUsedInTemplateInstantiation); - if (typeForNewName.empty() || (!typeParametersInDeclaration.empty() && typeParametersInDeclaration.size() != mTypesUsedInTemplateInstantiation.size())) { + if ((typeForNewName.empty() && !templateDeclaration.isVariadic()) || + (!typeParametersInDeclaration.empty() && typeParametersInDeclaration.size() != mTypesUsedInTemplateInstantiation.size())) { if (printDebug && mErrorLogger) { std::list callstack(1, tok2); mErrorLogger->reportErr(ErrorLogger::ErrorMessage(callstack, &mTokenList, Severity::debug, "debug", @@ -2681,7 +2686,7 @@ void TemplateSimplifier::replaceTemplateUsage( // match parameters Token * tok2 = nameTok->tokAt(2); - unsigned int typeCountInInstantiation = 1U; // There is always at least one type + unsigned int typeCountInInstantiation = tok2->str() == ">" ? 0U : 1U; const Token *typetok = (!mTypesUsedInTemplateInstantiation.empty()) ? mTypesUsedInTemplateInstantiation[0].token : nullptr; unsigned int indentlevel2 = 0; // indentlevel for tokgt while (tok2 && (indentlevel2 > 0 || tok2->str() != ">")) { @@ -2895,6 +2900,8 @@ void TemplateSimplifier::printOut(const TokenAndName &tokenAndName, const std::s std::cout << " isPartialSpecialization"; if (tokenAndName.isForwardDeclaration()) std::cout << " isForwardDeclaration"; + if (tokenAndName.isVariadic()) + std::cout << " isVariadic"; std::cout << std::endl; if (tokenAndName.token && !tokenAndName.paramEnd && tokenAndName.token->strAt(1) == "<") { const Token *end = tokenAndName.token->next()->findClosingBracket(); diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index ad2c7e9aa..19e7260d8 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -106,6 +106,7 @@ public: fIsSpecialization = (1 << 4), // user specialized template fIsPartialSpecialization = (1 << 5), // user partial specialized template fIsForwardDeclaration = (1 << 6), // forward declaration + fIsVariadic = (1 << 7), // variadic template }; bool isClass() const { @@ -157,6 +158,13 @@ public: setFlag(fIsForwardDeclaration, state); } + bool isVariadic() const { + return getFlag(fIsVariadic); + } + void isVariadic(bool state) { + setFlag(fIsVariadic, state); + } + /** * Get specified flag state. * @param flag flag to get state of diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index e3bf11991..4d98107ca 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -191,6 +191,8 @@ private: TEST_CASE(templateTypeDeduction2); TEST_CASE(simplifyTemplateArgs); + + TEST_CASE(template_variadic_1); // #9144 } std::string tok(const char code[], bool debugwarnings = false, Settings::PlatformType type = Settings::Native) { @@ -3618,6 +3620,15 @@ private: ASSERT_EQUALS("foo = false ; foo ;", tok("template foo = N; foo < ( 1 - 1) ? true : false >;")); } + void template_variadic_1() { // #9144 + const char code[] = "template struct e {};\n" + "static_assert(sizeof(e<>) == sizeof(e), \"\");"; + const char expected[] = "struct e<> ; struct e ; " + "static_assert ( sizeof ( e<> ) == sizeof ( e ) , \"\" ) ; " + "struct e<> { } ; struct e { } ;"; + ASSERT_EQUALS(expected, tok(code)); + } + }; REGISTER_TEST(TestSimplifyTemplate)