Fix 10491: Crash in unusedFunction on valid C++ code (#3465)
This commit is contained in:
parent
4ad09f181a
commit
edd435d5f0
|
@ -4482,6 +4482,7 @@ void Tokenizer::createLinks2()
|
||||||
bool isStruct = false;
|
bool isStruct = false;
|
||||||
|
|
||||||
std::stack<Token*> type;
|
std::stack<Token*> type;
|
||||||
|
std::stack<Token*> templateTokens;
|
||||||
for (Token *token = list.front(); token; token = token->next()) {
|
for (Token *token = list.front(); token; token = token->next()) {
|
||||||
if (Token::Match(token, "%name%|> %name% [:<]"))
|
if (Token::Match(token, "%name%|> %name% [:<]"))
|
||||||
isStruct = true;
|
isStruct = true;
|
||||||
|
@ -4493,14 +4494,14 @@ void Tokenizer::createLinks2()
|
||||||
type.push(token);
|
type.push(token);
|
||||||
else if (!type.empty() && Token::Match(token, "}|]|)")) {
|
else if (!type.empty() && Token::Match(token, "}|]|)")) {
|
||||||
while (type.top()->str() == "<") {
|
while (type.top()->str() == "<") {
|
||||||
if (templateToken && templateToken->next() == type.top())
|
if (!templateTokens.empty() && templateTokens.top()->next() == type.top())
|
||||||
templateToken = nullptr;
|
templateTokens.pop();
|
||||||
type.pop();
|
type.pop();
|
||||||
}
|
}
|
||||||
type.pop();
|
type.pop();
|
||||||
} else
|
} else
|
||||||
token->link(nullptr);
|
token->link(nullptr);
|
||||||
} else if (!templateToken && !isStruct && Token::Match(token, "%oror%|&&|;")) {
|
} else if (templateTokens.empty() && !isStruct && Token::Match(token, "%oror%|&&|;")) {
|
||||||
if (Token::Match(token, "&& [,>]"))
|
if (Token::Match(token, "&& [,>]"))
|
||||||
continue;
|
continue;
|
||||||
// If there is some such code: A<B||C>..
|
// If there is some such code: A<B||C>..
|
||||||
|
@ -4548,8 +4549,8 @@ void Tokenizer::createLinks2()
|
||||||
(token->previous()->isName() && !token->previous()->varId()))) ||
|
(token->previous()->isName() && !token->previous()->varId()))) ||
|
||||||
Token::Match(token->next(), ">|>>"))) {
|
Token::Match(token->next(), ">|>>"))) {
|
||||||
type.push(token);
|
type.push(token);
|
||||||
if (!templateToken && (token->previous()->str() == "template"))
|
if (token->previous()->str() == "template")
|
||||||
templateToken = token;
|
templateTokens.push(token);
|
||||||
} else if (token->str() == ">" || token->str() == ">>") {
|
} else if (token->str() == ">" || token->str() == ">>") {
|
||||||
if (type.empty() || type.top()->str() != "<") // < and > don't match.
|
if (type.empty() || type.top()->str() != "<") // < and > don't match.
|
||||||
continue;
|
continue;
|
||||||
|
@ -4580,15 +4581,18 @@ void Tokenizer::createLinks2()
|
||||||
type.pop();
|
type.pop();
|
||||||
type.pop();
|
type.pop();
|
||||||
Token::createMutualLinks(top2, token);
|
Token::createMutualLinks(top2, token);
|
||||||
if (top1 == templateToken || top2 == templateToken)
|
if (templateTokens.size() == 2 && (top1 == templateTokens.top() || top2 == templateTokens.top())) {
|
||||||
templateToken = nullptr;
|
templateTokens.pop();
|
||||||
|
templateTokens.pop();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
type.pop();
|
type.pop();
|
||||||
if (Token::Match(token, "> %name%") && Token::Match(top1->tokAt(-2), "%op% %name% <"))
|
if (Token::Match(token, "> %name%") && Token::Match(top1->tokAt(-2), "%op% %name% <") &&
|
||||||
|
(templateTokens.empty() || top1 != templateTokens.top()))
|
||||||
continue;
|
continue;
|
||||||
Token::createMutualLinks(top1, token);
|
Token::createMutualLinks(top1, token);
|
||||||
if (top1 == templateToken)
|
if (!templateTokens.empty() && top1 == templateTokens.top())
|
||||||
templateToken = nullptr;
|
templateTokens.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3304,6 +3304,32 @@ private:
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> . f (")->link());
|
ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> . f (")->link());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// #10491
|
||||||
|
const char code[] = "template <template <class> class> struct a;\n";
|
||||||
|
errout.str("");
|
||||||
|
Tokenizer tokenizer(&settings0, this);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
const Token* tok1 = Token::findsimplematch(tokenizer.tokens(), "< class");
|
||||||
|
const Token* tok2 = Token::findsimplematch(tok1, "> class");
|
||||||
|
ASSERT_EQUALS(true, tok1->link() == tok2);
|
||||||
|
ASSERT_EQUALS(true, tok2->link() == tok1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// #10491
|
||||||
|
const char code[] = "template <template <class> class> struct a;\n";
|
||||||
|
errout.str("");
|
||||||
|
Tokenizer tokenizer(&settings0, this);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
const Token* tok1 = Token::findsimplematch(tokenizer.tokens(), "< template");
|
||||||
|
const Token* tok2 = Token::findsimplematch(tok1, "> struct");
|
||||||
|
ASSERT_EQUALS(true, tok1->link() == tok2);
|
||||||
|
ASSERT_EQUALS(true, tok2->link() == tok1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifyString() {
|
void simplifyString() {
|
||||||
|
|
Loading…
Reference in New Issue