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()
|
void TemplateSimplifier::simplifyTemplateAliases()
|
||||||
{
|
{
|
||||||
std::list<TokenAndName>::iterator it1, it2;
|
std::list<TokenAndName>::iterator it1, it2, it3;
|
||||||
for (it1 = mTemplateInstantiations.begin(); it1 != mTemplateInstantiations.end();) {
|
for (it1 = mTemplateInstantiations.begin(); it1 != mTemplateInstantiations.end();) {
|
||||||
|
it3 = it1;
|
||||||
TokenAndName &templateAlias = *it1;
|
TokenAndName &templateAlias = *it1;
|
||||||
++it1;
|
++it1;
|
||||||
Token *startToken = templateAlias.token;
|
Token *startToken = templateAlias.token;
|
||||||
|
@ -1065,13 +1066,15 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
||||||
continue;
|
continue;
|
||||||
while (Token::Match(startToken->tokAt(-2), "%name% :: %name%"))
|
while (Token::Match(startToken->tokAt(-2), "%name% :: %name%"))
|
||||||
startToken = startToken->tokAt(-2);
|
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;
|
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;
|
const Token * const aliasToken1 = startToken;
|
||||||
|
|
||||||
// Get start token for alias
|
// Get start token for alias
|
||||||
startToken = startToken->tokAt(-5);
|
startToken = startToken->tokAt(hasTypename ? -6 : -5);
|
||||||
while (Token::Match(startToken, "%name%|<|>|>>|,"))
|
while (Token::Match(startToken, "%name%|<|>|>>|,"))
|
||||||
startToken = startToken->previous();
|
startToken = startToken->previous();
|
||||||
// handle case where 'template' is first token
|
// handle case where 'template' is first token
|
||||||
|
@ -1158,6 +1161,8 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
endToken = endToken1->next();
|
endToken = endToken1->next();
|
||||||
|
while (endToken->str() != ";")
|
||||||
|
endToken = endToken->next();
|
||||||
|
|
||||||
// Remove alias usage code (parameters)
|
// Remove alias usage code (parameters)
|
||||||
Token::eraseTokens(tok2->previous(), args.back().second);
|
Token::eraseTokens(tok2->previous(), args.back().second);
|
||||||
|
@ -1180,7 +1185,7 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
// find declaration
|
// 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(),
|
mTemplateDeclarations.end(),
|
||||||
FindToken(startToken ? startToken->next() : mTokenList.front()));
|
FindToken(startToken ? startToken->next() : mTokenList.front()));
|
||||||
|
|
||||||
|
@ -1192,9 +1197,10 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove declaration
|
// remove declaration
|
||||||
if (it3 != mTemplateDeclarations.end())
|
if (it4 != mTemplateDeclarations.end())
|
||||||
mTemplateDeclarations.erase(it3);
|
mTemplateDeclarations.erase(it4);
|
||||||
}
|
} else
|
||||||
|
mTemplateInstantiations.erase(it3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2417,7 +2423,8 @@ std::string TemplateSimplifier::getNewName(
|
||||||
{
|
{
|
||||||
std::string typeForNewName;
|
std::string typeForNewName;
|
||||||
unsigned int indentlevel = 0;
|
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
|
// #2648 - unhandled parentheses => bail out
|
||||||
// #2721 - unhandled [ => bail out
|
// #2721 - unhandled [ => bail out
|
||||||
if (Token::Match(tok3, "(|[")) {
|
if (Token::Match(tok3, "(|[")) {
|
||||||
|
@ -2686,10 +2693,11 @@ void TemplateSimplifier::replaceTemplateUsage(
|
||||||
|
|
||||||
// match parameters
|
// match parameters
|
||||||
Token * tok2 = nameTok->tokAt(2);
|
Token * tok2 = nameTok->tokAt(2);
|
||||||
|
const Token * endToken = nameTok->next()->findClosingBracket();
|
||||||
unsigned int typeCountInInstantiation = tok2->str() == ">" ? 0U : 1U;
|
unsigned int typeCountInInstantiation = tok2->str() == ">" ? 0U : 1U;
|
||||||
const Token *typetok = (!mTypesUsedInTemplateInstantiation.empty()) ? mTypesUsedInTemplateInstantiation[0].token : nullptr;
|
const Token *typetok = (!mTypesUsedInTemplateInstantiation.empty()) ? mTypesUsedInTemplateInstantiation[0].token : nullptr;
|
||||||
unsigned int indentlevel2 = 0; // indentlevel for tokgt
|
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)
|
if (tok2->str() == "<" && templateParameters(tok2) > 0)
|
||||||
++indentlevel2;
|
++indentlevel2;
|
||||||
else if (indentlevel2 > 0 && Token::Match(tok2, "> [,>]"))
|
else if (indentlevel2 > 0 && Token::Match(tok2, "> [,>]"))
|
||||||
|
|
|
@ -145,6 +145,7 @@ private:
|
||||||
TEST_CASE(template105); // #9076
|
TEST_CASE(template105); // #9076
|
||||||
TEST_CASE(template106);
|
TEST_CASE(template106);
|
||||||
TEST_CASE(template107); // #8663
|
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_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_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)
|
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||||
|
@ -2448,6 +2449,88 @@ private:
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
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>> {..};
|
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
const char code[] = "template <typename T> struct C {};\n"
|
const char code[] = "template <typename T> struct C {};\n"
|
||||||
"template <typename T> struct S {a};\n"
|
"template <typename T> struct S {a};\n"
|
||||||
|
|
|
@ -7647,6 +7647,21 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkTemplates() {
|
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(
|
ASSERT_NO_THROW(tokenizeAndStringify(
|
||||||
"template <typename = void> struct a {\n"
|
"template <typename = void> struct a {\n"
|
||||||
" void c();\n"
|
" void c();\n"
|
||||||
|
@ -7666,7 +7681,6 @@ private:
|
||||||
"};\n"))
|
"};\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void noCrash1() {
|
void noCrash1() {
|
||||||
ASSERT_NO_THROW(tokenizeAndStringify(
|
ASSERT_NO_THROW(tokenizeAndStringify(
|
||||||
"struct A {\n"
|
"struct A {\n"
|
||||||
|
|
Loading…
Reference in New Issue