* Fix #9225 (Crash on valid C++14 code) This only fixes the crash. Specialization of nested templates is still broken. * fix cppcheck warnings * fixed another cppcheck warning
This commit is contained in:
parent
bbcffce529
commit
999d2f797c
|
@ -79,7 +79,21 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *tok, const std::string &s,
|
||||||
// only set flags for declaration
|
// only set flags for declaration
|
||||||
if (token && nameToken && paramEnd) {
|
if (token && nameToken && paramEnd) {
|
||||||
isSpecialization(Token::simpleMatch(token, "template < >"));
|
isSpecialization(Token::simpleMatch(token, "template < >"));
|
||||||
isPartialSpecialization(!isSpecialization() && nameToken->strAt(1) == "<");
|
|
||||||
|
if (!isSpecialization()) {
|
||||||
|
if (Token::simpleMatch(token->next()->findClosingBracket(), "> template <")) {
|
||||||
|
const Token * temp = nameToken->tokAt(-2);
|
||||||
|
while (Token::Match(temp, ">|%name% ::")) {
|
||||||
|
if (temp->str() == ">")
|
||||||
|
temp = temp->findOpeningBracket()->previous();
|
||||||
|
else
|
||||||
|
temp = temp->tokAt(-2);
|
||||||
|
}
|
||||||
|
isPartialSpecialization(temp->strAt(1) == "<");
|
||||||
|
} else
|
||||||
|
isPartialSpecialization(nameToken->strAt(1) == "<");
|
||||||
|
}
|
||||||
|
|
||||||
isAlias(paramEnd->strAt(1) == "using");
|
isAlias(paramEnd->strAt(1) == "using");
|
||||||
|
|
||||||
if (isAlias() && isPartialSpecialization()) {
|
if (isAlias() && isPartialSpecialization()) {
|
||||||
|
@ -775,6 +789,19 @@ bool TemplateSimplifier::getTemplateDeclarations()
|
||||||
// ignore template template parameter
|
// ignore template template parameter
|
||||||
if (tok->strAt(-1) == "<")
|
if (tok->strAt(-1) == "<")
|
||||||
continue;
|
continue;
|
||||||
|
// ignore nested template
|
||||||
|
if (tok->strAt(-1) == ">")
|
||||||
|
continue;
|
||||||
|
// skip to last nested template parameter
|
||||||
|
const Token *tok1 = tok;
|
||||||
|
while (tok1 && tok1->next() && Token::simpleMatch(tok1->next()->findClosingBracket(), "> template <")) {
|
||||||
|
const Token *closing = tok1->next()->findClosingBracket();
|
||||||
|
if (!closing)
|
||||||
|
syntaxError(tok1->next());
|
||||||
|
tok1 = closing->next();
|
||||||
|
}
|
||||||
|
if (!tok1)
|
||||||
|
syntaxError(tok);
|
||||||
// Some syntax checks, see #6865
|
// Some syntax checks, see #6865
|
||||||
if (!tok->tokAt(2))
|
if (!tok->tokAt(2))
|
||||||
syntaxError(tok->next());
|
syntaxError(tok->next());
|
||||||
|
@ -782,7 +809,7 @@ bool TemplateSimplifier::getTemplateDeclarations()
|
||||||
!Token::Match(tok->tokAt(3), "%name%|.|,|=|>"))
|
!Token::Match(tok->tokAt(3), "%name%|.|,|=|>"))
|
||||||
syntaxError(tok->next());
|
syntaxError(tok->next());
|
||||||
codeWithTemplates = true;
|
codeWithTemplates = true;
|
||||||
const Token * const parmEnd = tok->next()->findClosingBracket();
|
const Token * const parmEnd = tok1->next()->findClosingBracket();
|
||||||
for (const Token *tok2 = parmEnd; tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = parmEnd; tok2; tok2 = tok2->next()) {
|
||||||
if (tok2->str() == "(" && tok2->link())
|
if (tok2->str() == "(" && tok2->link())
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
|
@ -1403,9 +1430,9 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
|
||||||
if (Token::Match(tok->next(), ";|{"))
|
if (Token::Match(tok->next(), ";|{"))
|
||||||
return false;
|
return false;
|
||||||
// skip decltype(...)
|
// skip decltype(...)
|
||||||
else if (Token::simpleMatch(tok, "decltype (")) {
|
else if (Token::simpleMatch(tok->next(), "decltype (")) {
|
||||||
const Token * end = tok->linkAt(1);
|
const Token * end = tok->linkAt(2)->previous();
|
||||||
while (tok && tok != end) {
|
while (tok && tok->next() && tok != end) {
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
namepos++;
|
namepos++;
|
||||||
}
|
}
|
||||||
|
@ -1863,6 +1890,7 @@ void TemplateSimplifier::expandTemplate(
|
||||||
if (tok5)
|
if (tok5)
|
||||||
tok5 = tok5->next();
|
tok5 = tok5->next();
|
||||||
// copy return type
|
// copy return type
|
||||||
|
std::stack<Token *> brackets2; // holds "(" and "{" tokens
|
||||||
while (tok5 && tok5 != tok3) {
|
while (tok5 && tok5 != tok3) {
|
||||||
// replace name if found
|
// replace name if found
|
||||||
if (Token::Match(tok5, "%name% <") && tok5->str() == templateInstantiation.name) {
|
if (Token::Match(tok5, "%name% <") && tok5->str() == templateInstantiation.name) {
|
||||||
|
@ -1924,8 +1952,28 @@ void TemplateSimplifier::expandTemplate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!added)
|
if (!added) {
|
||||||
mTokenList.addtoken(tok5, tok5->linenr(), tok5->fileIndex());
|
mTokenList.addtoken(tok5, tok5->linenr(), tok5->fileIndex());
|
||||||
|
Token *back = mTokenList.back();
|
||||||
|
if (Token::Match(back, "{|(|[")) {
|
||||||
|
brackets2.push(back);
|
||||||
|
} else if (back->str() == "}") {
|
||||||
|
assert(brackets2.empty() == false);
|
||||||
|
assert(brackets2.top()->str() == "{");
|
||||||
|
Token::createMutualLinks(brackets2.top(), back);
|
||||||
|
brackets2.pop();
|
||||||
|
} else if (back->str() == ")") {
|
||||||
|
assert(brackets2.empty() == false);
|
||||||
|
assert(brackets2.top()->str() == "(");
|
||||||
|
Token::createMutualLinks(brackets2.top(), back);
|
||||||
|
brackets2.pop();
|
||||||
|
} else if (back->str() == "]") {
|
||||||
|
assert(brackets2.empty() == false);
|
||||||
|
assert(brackets2.top()->str() == "[");
|
||||||
|
Token::createMutualLinks(brackets2.top(), back);
|
||||||
|
brackets2.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tok5 = tok5->next();
|
tok5 = tok5->next();
|
||||||
|
|
|
@ -111,7 +111,7 @@ const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &end
|
||||||
tok = tok->linkAt(1)->next();
|
tok = tok->linkAt(1)->next();
|
||||||
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName())
|
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName())
|
||||||
tok = tok->linkAt(1)->next();
|
tok = tok->linkAt(1)->next();
|
||||||
if (tok && tok->str() == ".") { // trailing return type
|
if (tok && tok->originalName() == "->") { // trailing return type
|
||||||
for (tok = tok->next(); tok && !Token::Match(tok, ";|{|override|final"); tok = tok->next())
|
for (tok = tok->next(); tok && !Token::Match(tok, ";|{|override|final"); tok = tok->next())
|
||||||
if (tok->link() && Token::Match(tok, "<|[|("))
|
if (tok->link() && Token::Match(tok, "<|[|("))
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
|
|
|
@ -1592,7 +1592,6 @@ private:
|
||||||
void garbageCode203() { // #8972
|
void garbageCode203() { // #8972
|
||||||
checkCode("{ > () {} }");
|
checkCode("{ > () {} }");
|
||||||
checkCode("template <> a > ::b();");
|
checkCode("template <> a > ::b();");
|
||||||
ASSERT_THROW(checkCode("{ template <a> class b { } template <> template <c> c() b<a>::e() { } template b<d>; }"), InternalError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void garbageCode204() {
|
void garbageCode204() {
|
||||||
|
|
|
@ -164,6 +164,7 @@ private:
|
||||||
TEST_CASE(template124); // #9197
|
TEST_CASE(template124); // #9197
|
||||||
TEST_CASE(template125);
|
TEST_CASE(template125);
|
||||||
TEST_CASE(template126); // #9217
|
TEST_CASE(template126); // #9217
|
||||||
|
TEST_CASE(template127); // #9225
|
||||||
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)
|
||||||
|
@ -2943,6 +2944,96 @@ private:
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template127() { // #9225
|
||||||
|
{
|
||||||
|
const char code[] = "template <typename> struct a {\n"
|
||||||
|
" template <typename b> constexpr decltype(auto) operator()(b &&) const;\n"
|
||||||
|
"};\n"
|
||||||
|
"a<int> c;\n"
|
||||||
|
"template <typename d>\n"
|
||||||
|
"template <typename b>\n"
|
||||||
|
"constexpr decltype(auto) a<d>::operator()(b &&) const {}";
|
||||||
|
const char exp[] = "struct a<int> ; "
|
||||||
|
"a<int> c ; "
|
||||||
|
"template < typename d > "
|
||||||
|
"template < typename b > "
|
||||||
|
"const decltype ( auto ) a < d > :: operator() ( b & & ) const { } "
|
||||||
|
"struct a<int> { "
|
||||||
|
"template < typename b > const decltype ( auto ) operator() ( b & & ) const ; "
|
||||||
|
"} ;";
|
||||||
|
const char act[] = "struct a<int> ; "
|
||||||
|
"a<int> c ; "
|
||||||
|
"template < typename d > "
|
||||||
|
"template < typename b > "
|
||||||
|
"const decltype ( auto ) a < d > :: operator() ( b & & ) const { } "
|
||||||
|
"struct a<int> { "
|
||||||
|
"template < typename b > const decltype ( auto ) operator() ( b & & ) const ; "
|
||||||
|
"} ; "
|
||||||
|
"const decltype ( auto ) a<int> :: operator() ( b & & ) const { }";
|
||||||
|
TODO_ASSERT_EQUALS(exp, act, tok(code));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const char code[] = "template <typename> struct a {\n"
|
||||||
|
" template <typename b> static void foo();\n"
|
||||||
|
"};\n"
|
||||||
|
"a<int> c;\n"
|
||||||
|
"template <typename d>\n"
|
||||||
|
"template <typename b>\n"
|
||||||
|
"void a<d>::foo() {}\n"
|
||||||
|
"void bar() { a<int>::foo<char>(); }";
|
||||||
|
const char exp[] = "struct a<int> ; "
|
||||||
|
"a<int> c ; "
|
||||||
|
"template < typename d > "
|
||||||
|
"template < typename b > "
|
||||||
|
"void a < d > :: foo ( ) { } "
|
||||||
|
"void bar ( ) { a<int> :: foo < char > ( ) ; } "
|
||||||
|
"struct a<int> { "
|
||||||
|
"template < typename b > static void foo ( ) ; "
|
||||||
|
"static void foo<char> ( ) ; "
|
||||||
|
"} ; "
|
||||||
|
"void a<int> :: foo<char> ( ) { }";
|
||||||
|
const char act[] = "struct a<int> ; "
|
||||||
|
"a<int> c ; "
|
||||||
|
"template < typename d > "
|
||||||
|
"template < typename b > "
|
||||||
|
"void a < d > :: foo ( ) { } "
|
||||||
|
"void bar ( ) { a<int> :: foo < char > ( ) ; } "
|
||||||
|
"struct a<int> { "
|
||||||
|
"template < typename b > static void foo ( ) ; "
|
||||||
|
"} ; "
|
||||||
|
"void a<int> :: foo ( ) { }";
|
||||||
|
TODO_ASSERT_EQUALS(exp, act, tok(code));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const char code[] = "template <typename> struct a {\n"
|
||||||
|
" template <typename b> static void foo();\n"
|
||||||
|
"};\n"
|
||||||
|
"template <typename d>\n"
|
||||||
|
"template <typename b>\n"
|
||||||
|
"void a<d>::foo() {}\n"
|
||||||
|
"void bar() { a<int>::foo<char>(); }";
|
||||||
|
const char exp[] = "struct a<int> ; "
|
||||||
|
"template < typename d > "
|
||||||
|
"template < typename b > "
|
||||||
|
"void a < d > :: foo ( ) { } "
|
||||||
|
"void bar ( ) { a<int> :: foo < char > ( ) ; } "
|
||||||
|
"struct a<int> { "
|
||||||
|
"static void foo<char> ( ) ; "
|
||||||
|
"} ; "
|
||||||
|
"void a<int> :: foo<char> ( ) { }";
|
||||||
|
const char act[] = "struct a<int> ; "
|
||||||
|
"template < typename d > "
|
||||||
|
"template < typename b > "
|
||||||
|
"void a < d > :: foo ( ) { } "
|
||||||
|
"void bar ( ) { a<int> :: foo < char > ( ) ; } "
|
||||||
|
"struct a<int> { "
|
||||||
|
"template < typename b > static void foo ( ) ; "
|
||||||
|
"} ; "
|
||||||
|
"void a<int> :: foo ( ) { }";
|
||||||
|
TODO_ASSERT_EQUALS(exp, act, 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"
|
||||||
|
|
Loading…
Reference in New Issue