Fix issue 9109: Syntax error for valid C++ code
This commit is contained in:
parent
5efb23ffff
commit
cb7f925f5e
|
@ -1056,8 +1056,9 @@ void TemplateSimplifier::useDefaultArgumentValues(TemplateSimplifier::TokenAndNa
|
|||
|
||||
void TemplateSimplifier::simplifyTemplateAliases()
|
||||
{
|
||||
std::list<TokenAndName>::iterator it1, it2;
|
||||
std::list<TokenAndName>::iterator it1, it2, it3;
|
||||
for (it1 = mTemplateInstantiations.begin(); it1 != mTemplateInstantiations.end();) {
|
||||
it3 = it1;
|
||||
TokenAndName &templateAlias = *it1;
|
||||
++it1;
|
||||
Token *startToken = templateAlias.token;
|
||||
|
@ -1065,13 +1066,15 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
|||
continue;
|
||||
while (Token::Match(startToken->tokAt(-2), "%name% :: %name%"))
|
||||
startToken = startToken->tokAt(-2);
|
||||
if (!Token::Match(startToken->tokAt(-4), "> using %name% = %name% ::|<"))
|
||||
if (!(Token::Match(startToken->tokAt(-4), "> using %name% = %name% ::|<") ||
|
||||
Token::Match(startToken->tokAt(-5), "> using %name% = typename %name% ::|<")))
|
||||
continue;
|
||||
const std::string aliasName(startToken->strAt(-2));
|
||||
const bool hasTypename(startToken->strAt(-1) == "typename");
|
||||
const std::string aliasName(startToken->strAt(hasTypename ? -3 : -2));
|
||||
const Token * const aliasToken1 = startToken;
|
||||
|
||||
// Get start token for alias
|
||||
startToken = startToken->tokAt(-5);
|
||||
startToken = startToken->tokAt(hasTypename ? -6 : -5);
|
||||
while (Token::Match(startToken, "%name%|<|>|>>|,"))
|
||||
startToken = startToken->previous();
|
||||
// handle case where 'template' is first token
|
||||
|
@ -1158,6 +1161,8 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
|||
}
|
||||
|
||||
endToken = endToken1->next();
|
||||
while (endToken->str() != ";")
|
||||
endToken = endToken->next();
|
||||
|
||||
// Remove alias usage code (parameters)
|
||||
Token::eraseTokens(tok2->previous(), args.back().second);
|
||||
|
@ -1180,7 +1185,7 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
|||
}
|
||||
|
||||
// find declaration
|
||||
const std::list<TokenAndName>::iterator it3 = std::find_if(mTemplateDeclarations.begin(),
|
||||
const std::list<TokenAndName>::iterator it4 = std::find_if(mTemplateDeclarations.begin(),
|
||||
mTemplateDeclarations.end(),
|
||||
FindToken(startToken ? startToken->next() : mTokenList.front()));
|
||||
|
||||
|
@ -1192,9 +1197,10 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
|||
}
|
||||
|
||||
// remove declaration
|
||||
if (it3 != mTemplateDeclarations.end())
|
||||
mTemplateDeclarations.erase(it3);
|
||||
}
|
||||
if (it4 != mTemplateDeclarations.end())
|
||||
mTemplateDeclarations.erase(it4);
|
||||
} else
|
||||
mTemplateInstantiations.erase(it3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2417,7 +2423,8 @@ std::string TemplateSimplifier::getNewName(
|
|||
{
|
||||
std::string typeForNewName;
|
||||
unsigned int indentlevel = 0;
|
||||
for (Token *tok3 = tok2->tokAt(2); tok3 && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
|
||||
const Token * endToken = tok2->next()->findClosingBracket();
|
||||
for (Token *tok3 = tok2->tokAt(2); tok3 != endToken && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
|
||||
// #2648 - unhandled parentheses => bail out
|
||||
// #2721 - unhandled [ => bail out
|
||||
if (Token::Match(tok3, "(|[")) {
|
||||
|
@ -2686,10 +2693,11 @@ void TemplateSimplifier::replaceTemplateUsage(
|
|||
|
||||
// match parameters
|
||||
Token * tok2 = nameTok->tokAt(2);
|
||||
const Token * endToken = nameTok->next()->findClosingBracket();
|
||||
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() != ">")) {
|
||||
while (tok2 != endToken && (indentlevel2 > 0 || tok2->str() != ">")) {
|
||||
if (tok2->str() == "<" && templateParameters(tok2) > 0)
|
||||
++indentlevel2;
|
||||
else if (indentlevel2 > 0 && Token::Match(tok2, "> [,>]"))
|
||||
|
|
|
@ -145,6 +145,7 @@ private:
|
|||
TEST_CASE(template105); // #9076
|
||||
TEST_CASE(template106);
|
||||
TEST_CASE(template107); // #8663
|
||||
TEST_CASE(template108); // #9109
|
||||
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)
|
||||
|
@ -2448,6 +2449,88 @@ private:
|
|||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template108() { // #9109
|
||||
{
|
||||
const char code[] = "template <typename> struct a;\n"
|
||||
"template <typename> struct b {};\n"
|
||||
"template <typename> struct c;\n"
|
||||
"template <typename d> struct e {\n"
|
||||
" using f = a<b<typename c<d>::g>>;\n"
|
||||
" bool h = f::h;\n"
|
||||
"};\n"
|
||||
"struct i {\n"
|
||||
" e<int> j();\n"
|
||||
"};\n";
|
||||
const char exp[] = "template < typename > struct a ; "
|
||||
"struct b<c<int>::g> ; "
|
||||
"template < typename > struct c ; "
|
||||
"struct e<int> ; "
|
||||
"struct i { e<int> j ( ) ; "
|
||||
"} ; "
|
||||
"struct e<int> { bool h ; "
|
||||
"h = a < b<c<int>::g> > :: h ; "
|
||||
"} ; "
|
||||
"struct b<c<int>::g> { } ;";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
{
|
||||
const char code[] = "namespace {\n"
|
||||
"template <typename> struct a;\n"
|
||||
"template <typename> struct b {};\n"
|
||||
"}\n"
|
||||
"namespace {\n"
|
||||
"template <typename> struct c;\n"
|
||||
"template <typename d> struct e {\n"
|
||||
" using f = a<b<typename c<d>::g>>;\n"
|
||||
" bool h = f::h;\n"
|
||||
"};\n"
|
||||
"template <typename i> using j = typename e<i>::g;\n"
|
||||
"}";
|
||||
const char exp[] = "namespace { "
|
||||
"template < typename > struct a ; "
|
||||
"template < typename > struct b { } ; "
|
||||
"} "
|
||||
"namespace { "
|
||||
"template < typename > struct c ; "
|
||||
"template < typename d > struct e { "
|
||||
"using f = a < b < c < d > :: g > > ; "
|
||||
"bool h ; h = f :: h ; "
|
||||
"} ; "
|
||||
"template < typename i > using j = typename e < i > :: g ; "
|
||||
"}";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
{
|
||||
const char code[] = "namespace {\n"
|
||||
"template <typename> struct a;\n"
|
||||
"template <typename> struct b {};\n"
|
||||
"}\n"
|
||||
"namespace {\n"
|
||||
"template <typename> struct c;\n"
|
||||
"template <typename d> struct e {\n"
|
||||
" using f = a<b<typename c<d>::g>>;\n"
|
||||
" bool h = f::h;\n"
|
||||
"};\n"
|
||||
"template <typename i> using j = typename e<i>::g;\n"
|
||||
"}\n"
|
||||
"j<int> foo;";
|
||||
const char exp[] = "namespace { "
|
||||
"template < typename > struct a ; "
|
||||
"struct b<c<int>::g> ; "
|
||||
"} "
|
||||
"namespace { "
|
||||
"template < typename > struct c ; "
|
||||
"struct e<int> ; "
|
||||
"} "
|
||||
"e<int> foo ; "
|
||||
"struct e<int> { "
|
||||
"bool h ; h = a < b<c<int>::g> > :: h ; "
|
||||
"} ; "
|
||||
"struct b<c<int>::g> { } ;";
|
||||
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"
|
||||
|
|
|
@ -7647,6 +7647,21 @@ private:
|
|||
}
|
||||
|
||||
void checkTemplates() {
|
||||
// #9109
|
||||
ASSERT_NO_THROW(tokenizeAndStringify(
|
||||
"namespace {\n"
|
||||
"template <typename> struct a;\n"
|
||||
"template <typename> struct b {};\n"
|
||||
"}\n"
|
||||
"namespace {\n"
|
||||
"template <typename> struct c;\n"
|
||||
"template <typename d> struct e {\n"
|
||||
" using f = a< b<typename c<d>::g> >;\n"
|
||||
" bool h = f::h;\n"
|
||||
"};\n"
|
||||
"template <typename i> using j = typename e<i>::g;\n"
|
||||
"}\n"))
|
||||
|
||||
ASSERT_NO_THROW(tokenizeAndStringify(
|
||||
"template <typename = void> struct a {\n"
|
||||
" void c();\n"
|
||||
|
@ -7666,7 +7681,6 @@ private:
|
|||
"};\n"))
|
||||
}
|
||||
|
||||
|
||||
void noCrash1() {
|
||||
ASSERT_NO_THROW(tokenizeAndStringify(
|
||||
"struct A {\n"
|
||||
|
|
Loading…
Reference in New Issue