template simplifier: consistently handle templates with no arguments (#1939)

this fixes daca boost1.67 crashes
This commit is contained in:
IOBYTE 2019-07-01 01:01:14 -04:00 committed by Daniel Marjamäki
parent f8c350fc70
commit bf4e1ef790
2 changed files with 40 additions and 10 deletions

View File

@ -1048,7 +1048,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
continue;
}
if (tok->str() == "<" && templateParameters(tok))
if (tok->str() == "<" && (tok->strAt(1) == ">" || templateParameters(tok)))
++templateParmDepth;
// end of template parameters?
@ -1101,7 +1101,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
instantiationArgs[index].push_back(tok1);
tok1 = tok1->next();
} while (tok1 && tok1 != endLink);
} else if (tok1->str() == "<") {
} else if (tok1->str() == "<" && (tok1->strAt(1) == ">" || templateParameters(tok1))) {
const Token *endLink = tok1->findClosingBracket();
do {
instantiationArgs[index].push_back(tok1);
@ -1134,7 +1134,7 @@ 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() == "<")
if (from->str() == "<" && (from->strAt(1) == ">" || templateParameters(from)))
++indentlevel;
else if (from->str() == ">")
--indentlevel;
@ -1181,7 +1181,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
}
if (Token::Match(tok2, "(|{|["))
tok2 = tok2->link();
else if (Token::Match(tok2, "%type% <") && templateParameters(tok2->next())) {
else if (Token::Match(tok2, "%type% <") && (tok2->strAt(2) == ">" || templateParameters(tok2->next()))) {
std::list<TokenAndName>::iterator ti = std::find_if(mTemplateInstantiations.begin(),
mTemplateInstantiations.end(),
FindToken(tok2));
@ -1346,7 +1346,7 @@ bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::size
const Token *tok = instance;
unsigned int indentlevel = 0;
for (tok = instance; tok && (tok->str() != ">" || indentlevel > 0); tok = tok->next()) {
if (Token::Match(tok, "<|,|(|:: %name% <") && templateParameters(tok->tokAt(2)) > 0)
if (Token::Match(tok, "<|,|(|:: %name% <") && (tok->strAt(3) == ">" || templateParameters(tok->tokAt(2))))
++indentlevel;
if (indentlevel > 0 && tok->str() == ">")
--indentlevel;
@ -1637,7 +1637,7 @@ void TemplateSimplifier::expandTemplate(
typetok = typetok->tokAt(2);
continue;
}
if (Token::Match(typetok, "%name% <") && templateParameters(typetok->next()) > 0)
if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
++typeindentlevel;
else if (typeindentlevel > 0 && typetok->str() == ">")
--typeindentlevel;
@ -1859,7 +1859,7 @@ void TemplateSimplifier::expandTemplate(
if (Token::simpleMatch(typetok, ". . .")) {
typetok = typetok->tokAt(2);
} else {
if (Token::Match(typetok, "%name% <") && templateParameters(typetok->next()) > 0)
if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
++typeindentlevel;
else if (typeindentlevel > 0 && typetok->str() == ">")
--typeindentlevel;
@ -1939,7 +1939,7 @@ void TemplateSimplifier::expandTemplate(
typetok = typetok->tokAt(2);
continue;
}
if (Token::Match(typetok, "%name% <") && templateParameters(typetok->next()) > 0)
if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
++typeindentlevel;
else if (typeindentlevel > 0 && typetok->str() == ">")
--typeindentlevel;
@ -2710,7 +2710,7 @@ std::string TemplateSimplifier::getNewName(
typeForNewName.clear();
break;
}
if (Token::Match(tok3->tokAt(-2), "<|,|:: %name% <") && templateParameters(tok3) > 0)
if (Token::Match(tok3->tokAt(-2), "<|,|:: %name% <") && (tok3->strAt(1) == ">" || templateParameters(tok3)))
++indentlevel;
else if (indentlevel > 0 && Token::Match(tok3, "> [,>]"))
--indentlevel;
@ -2975,7 +2975,7 @@ void TemplateSimplifier::replaceTemplateUsage(
const Token *typetok = (!mTypesUsedInTemplateInstantiation.empty()) ? mTypesUsedInTemplateInstantiation[0].token : nullptr;
unsigned int indentlevel2 = 0; // indentlevel for tokgt
while (tok2 != endToken && (indentlevel2 > 0 || tok2->str() != ">")) {
if (tok2->str() == "<" && templateParameters(tok2) > 0)
if (tok2->str() == "<" && (tok2->strAt(1) == ">" || templateParameters(tok2)))
++indentlevel2;
else if (indentlevel2 > 0 && Token::Match(tok2, "> [,>]"))
--indentlevel2;

View File

@ -157,6 +157,7 @@ private:
TEST_CASE(template117);
TEST_CASE(template118);
TEST_CASE(template119); // #9186
TEST_CASE(template120);
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)
@ -2819,6 +2820,35 @@ private:
}
}
void template120() {
const char code[] = "template<typename Tuple>\n"
"struct lambda_context {\n"
" template<typename Sig> struct result;\n"
" template<typename This, typename I>\n"
" struct result<This(terminal, placeholder)> : at<Tuple, I> {};\n"
"};\n"
"template<typename T>\n"
"struct lambda {\n"
" template<typename Sig> struct result;\n"
" template<typename This>\n"
" struct result<This()> : lambda_context<tuple<> > {};\n"
"};\n"
"lambda<int> l;";
const char exp[] = "template < typename Tuple > "
"struct lambda_context { "
"template < typename Sig > struct result ; "
"template < typename This , typename I > "
"struct result < This ( terminal , placeholder ) > : at < Tuple , I > { } ; "
"} ; "
"struct lambda<int> ; "
"lambda<int> l ; struct lambda<int> { "
"template < typename Sig > struct result ; "
"template < typename This > "
"struct result < This ( ) > : lambda_context < tuple < > > { } ; "
"} ;";
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"