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 <class...>

* add variadic template flag
This commit is contained in:
IOBYTE 2019-05-23 14:53:26 -04:00 committed by Daniel Marjamäki
parent cd05f4eefc
commit 5efb23ffff
3 changed files with 28 additions and 2 deletions

View File

@ -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<std::string> 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<const Token *> 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();

View File

@ -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

View File

@ -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> = false ; foo<false> ;", tok("template<bool N> foo = N; foo < ( 1 - 1) ? true : false >;"));
}
void template_variadic_1() { // #9144
const char code[] = "template <typename...> struct e {};\n"
"static_assert(sizeof(e<>) == sizeof(e<int,int>), \"\");";
const char expected[] = "struct e<> ; struct e<int,int> ; "
"static_assert ( sizeof ( e<> ) == sizeof ( e<int,int> ) , \"\" ) ; "
"struct e<> { } ; struct e<int,int> { } ;";
ASSERT_EQUALS(expected, tok(code));
}
};
REGISTER_TEST(TestSimplifyTemplate)