Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions lib/templatesimplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,9 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
continue;
}

if (tok->str() == "<" && (tok->strAt(1) == ">" || templateParameters(tok)))
if (tok->str() == "<" &&
(tok->strAt(1) == ">" || (tok->previous()->isName() &&
typeParameterNames.find(tok->strAt(-1)) == typeParameterNames.end())))
++templateParmDepth;

// end of template parameters?
Expand All @@ -1012,7 +1014,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
}

// map type parameter name to index
if (Token::Match(tok, "typename|class %name% ,|>"))
if (Token::Match(tok, "typename|class|%type% %name% ,|>"))
typeParameterNames[tok->strAt(1)] = templatepar - 1;

// next template parameter
Expand Down Expand Up @@ -1054,7 +1056,9 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
tok1 = tok1->next();
} while (tok1 && tok1 != endLink);
instantiationArgs[index].push_back(tok1);
} else if (tok1->str() == "<" && (tok1->strAt(1) == ">" || templateParameters(tok1))) {
} else if (tok1->str() == "<" &&
(tok1->strAt(1) == ">" || (tok1->previous()->isName() &&
typeParameterNames.find(tok1->strAt(-1)) == typeParameterNames.end()))) {
const Token *endLink = tok1->findClosingBracket();
do {
instantiationArgs[index].push_back(tok1);
Expand All @@ -1071,7 +1075,8 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
// count the parameters..
Token *tok = instantiation.token->next();
unsigned int usedpar = templateParameters(tok);
tok = tok->findClosingBracket();
Token *instantiationEnd = tok->findClosingBracket();
tok = instantiationEnd;

if (tok && tok->str() == ">") {
tok = tok->previous();
Expand All @@ -1088,7 +1093,9 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
const Token *from = (*it)->next();
std::stack<Token *> links;
while (from && (!links.empty() || indentlevel || !Token::Match(from, ",|>"))) {
if (from->str() == "<" && (from->strAt(1) == ">" || templateParameters(from)))
if (from->str() == "<" &&
(from->strAt(1) == ">" || (from->previous()->isName() &&
typeParameterNames.find(from->strAt(-1)) == typeParameterNames.end())))
++indentlevel;
else if (from->str() == ">")
--indentlevel;
Expand Down Expand Up @@ -1123,6 +1130,8 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
usedpar++;
}
}

simplifyTemplateArgs(instantiation.token->next(), instantiationEnd);
}

for (Token * const eqtok : eq) {
Expand Down Expand Up @@ -2276,6 +2285,35 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end)
} else if (tok->strAt(1) == "(") {
tok = tok->linkAt(1);
}
} else if (Token::Match(tok, "%num% %comp% %num%") &&
MathLib::isInt(tok->str()) &&
MathLib::isInt(tok->strAt(2))) {
if ((Token::Match(tok->previous(), "(|&&|%oror%|,") || tok->previous() == start) &&
(Token::Match(tok->tokAt(3), ")|&&|%oror%|?") || tok->tokAt(3) == end)) {
const MathLib::bigint op1(MathLib::toLongNumber(tok->str()));
const std::string &cmp(tok->next()->str());
const MathLib::bigint op2(MathLib::toLongNumber(tok->strAt(2)));

std::string result;

if (cmp == "==")
result = (op1 == op2) ? "true" : "false";
else if (cmp == "!=")
result = (op1 != op2) ? "true" : "false";
else if (cmp == "<=")
result = (op1 <= op2) ? "true" : "false";
else if (cmp == ">=")
result = (op1 >= op2) ? "true" : "false";
else if (cmp == "<")
result = (op1 < op2) ? "true" : "false";
else
result = (op1 > op2) ? "true" : "false";

tok->str(result);
tok->deleteNext(2);
again = true;
tok = tok->previous();
}
}
}

Expand Down
11 changes: 10 additions & 1 deletion lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,8 @@ const Token * Token::findClosingBracket() const
return nullptr;

const Token *closing = nullptr;
const bool templateParameter(strAt(-1) == "template");
std::set<std::string> templateParameters;

unsigned int depth = 0;
for (closing = this; closing != nullptr; closing = closing->next()) {
Expand All @@ -864,7 +866,10 @@ const Token * Token::findClosingBracket() const
return nullptr; // #6803
} else if (Token::Match(closing, "}|]|)|;"))
return nullptr;
else if (closing->str() == "<")
// we can make some guesses for template parameters
else if (closing->str() == "<" &&
(!templateParameter || (closing->previous() && closing->previous()->isName() &&
templateParameters.find(closing->strAt(-1)) == templateParameters.end())))
++depth;
else if (closing->str() == ">") {
if (--depth == 0)
Expand All @@ -874,6 +879,10 @@ const Token * Token::findClosingBracket() const
return closing;
depth -= 2;
}
// save named template parameter
else if (templateParameter && depth == 1 && closing->str() == "," &&
closing->previous()->isName() && !Match(closing->previous(), "class|typename|."))
templateParameters.insert(closing->strAt(-1));
}

return closing;
Expand Down
28 changes: 28 additions & 0 deletions test/testsimplifytemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class TestSimplifyTemplate : public TestFixture {
TEST_CASE(template128); // #9224
TEST_CASE(template129);
TEST_CASE(template130); // #9246
TEST_CASE(template131); // #9249
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
Expand Down Expand Up @@ -3101,6 +3102,33 @@ class TestSimplifyTemplate : public TestFixture {
ASSERT_EQUALS(exp, tok(code));
}

void template131() { // #9249
{
const char code[] = "template <long a, bool = 0 == a> struct b {};\n"
"b<1> b1;";
const char exp[] = "struct b<1,false> ; "
"b<1,false> b1 ; "
"struct b<1,false> { } ;";
ASSERT_EQUALS(exp, tok(code));
}
{
const char code[] = "template <long a, bool = a < 0> struct b {};\n"
"b<1> b1;";
const char exp[] = "struct b<1,false> ; "
"b<1,false> b1 ; "
"struct b<1,false> { } ;";
ASSERT_EQUALS(exp, tok(code));
}
{
const char code[] = "template <long a, bool = 0 < a> struct b {};\n"
"b<1> b1;";
const char exp[] = "struct b<1,true> ; "
"b<1,true> b1 ; "
"struct b<1,true> { } ;";
ASSERT_EQUALS(exp, tok(code));
}
}

void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n"
Expand Down