From 8568a802080766895659ae4ebbced8ababffd61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 20 Jan 2016 16:10:58 +0100 Subject: [PATCH] Fixed #6883 (Template parsing error) --- lib/tokenize.cpp | 22 +++++++++++++++++----- test/testtokenize.cpp | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4595d3476..2eac7effc 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3059,8 +3059,16 @@ void Tokenizer::createLinks2() if (isC()) return; + const Token * templateToken = nullptr; + bool isStruct = false; + std::stack type; for (Token *token = list.front(); token; token = token->next()) { + if (Token::Match(token, "struct|class %name% :")) + isStruct = true; + else if (Token::Match(token, "[;{}]")) + isStruct = false; + if (token->link()) { if (Token::Match(token, "{|[|(")) type.push(token); @@ -3068,16 +3076,17 @@ void Tokenizer::createLinks2() while (type.top()->str() == "<") type.pop(); type.pop(); + templateToken = nullptr; } else token->link(0); - } - - else if (Token::Match(token, "%oror%|&&|;")) + } else if (!templateToken && !isStruct && Token::Match(token, "%oror%|&&|;")) { while (!type.empty() && type.top()->str() == "<") type.pop(); - else if (token->str() == "<" && token->previous() && token->previous()->isName() && !token->previous()->varId()) + } else if (token->str() == "<" && token->previous() && token->previous()->isName() && !token->previous()->varId()) { type.push(token); - else if (token->str() == ">") { + if (!templateToken && (token->previous()->str() == "template")) + templateToken = token; + } else if (token->str() == ">") { if (type.empty() || type.top()->str() != "<") // < and > don't match. continue; if (token->next() && !Token::Match(token->next(), "%name%|>|&|*|::|,|(|)|{|;|[|:")) @@ -3097,6 +3106,9 @@ void Tokenizer::createLinks2() Token* top = type.top(); type.pop(); + if (top == templateToken) + templateToken = nullptr; + Token::createMutualLinks(top, token); } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 4d33de017..780fe1fff 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -4514,6 +4514,28 @@ private: ASSERT_EQUALS(true, tok->linkAt(3) == nullptr); } + { + const char code[] = "template < f = b || c > struct S;"; + errout.str(""); + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + const Token *tok = tokenizer.tokens(); + ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(7)); + ASSERT_EQUALS(true, tok->tokAt(1) == tok->linkAt(7)); + } + + { + const char code[] = "struct A : B {};"; + errout.str(""); + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + const Token *tok = tokenizer.tokens(); + ASSERT_EQUALS(true, tok->linkAt(4) == tok->tokAt(8)); + ASSERT_EQUALS(true, tok->tokAt(4) == tok->linkAt(8)); + } + { // #6601 const char code[] = "template struct FuncType : FuncType { };";