Ticket #7117: Properly detect if a const ternary operator is in a template parameter list.
This commit is contained in:
parent
583b340034
commit
3c10b25b3e
|
@ -4866,7 +4866,12 @@ bool Tokenizer::simplifyConditions()
|
|||
bool Tokenizer::simplifyConstTernaryOp()
|
||||
{
|
||||
bool ret = false;
|
||||
const Token *templateParameterEnd = 0; // The end of the current template parameter list, if any
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
if (tok->str() == "<" && TemplateSimplifier::templateParameters(tok))
|
||||
templateParameterEnd = tok->findClosingBracket();
|
||||
if (tok == templateParameterEnd)
|
||||
templateParameterEnd = 0; // End of the current template parameter list
|
||||
if (tok->str() != "?")
|
||||
continue;
|
||||
|
||||
|
@ -4876,20 +4881,18 @@ bool Tokenizer::simplifyConstTernaryOp()
|
|||
|
||||
const int offset = (tok->previous()->str() == ")") ? 2 : 1;
|
||||
|
||||
bool inTemplateParameter = false;
|
||||
if (tok->strAt(-2*offset) == "<") {
|
||||
if (isC() || !TemplateSimplifier::templateParameters(tok->tokAt(-2*offset)))
|
||||
continue; // '<' is less than; the condition is not a constant
|
||||
inTemplateParameter = true;
|
||||
}
|
||||
|
||||
// Find the token ":" then go to the next token
|
||||
Token *semicolon = skipTernaryOp(tok);
|
||||
if (!semicolon || semicolon->previous()->str() != ":" || !semicolon->next())
|
||||
Token *colon = skipTernaryOp(tok);
|
||||
if (!colon || colon->previous()->str() != ":" || !colon->next())
|
||||
continue;
|
||||
|
||||
//handle the GNU extension: "x ? : y" <-> "x ? x : y"
|
||||
if (semicolon->previous() == tok->next())
|
||||
if (colon->previous() == tok->next())
|
||||
tok->insertToken(tok->strAt(-offset));
|
||||
|
||||
// go back before the condition, if possible
|
||||
|
@ -4903,8 +4906,8 @@ bool Tokenizer::simplifyConstTernaryOp()
|
|||
}
|
||||
|
||||
if (Token::Match(tok->next(), "false|0")) {
|
||||
// Use code after semicolon, remove code before it.
|
||||
Token::eraseTokens(tok, semicolon);
|
||||
// Use code after colon, remove code before it.
|
||||
Token::eraseTokens(tok, colon);
|
||||
|
||||
tok = tok->next();
|
||||
ret = true;
|
||||
|
@ -4916,7 +4919,7 @@ bool Tokenizer::simplifyConstTernaryOp()
|
|||
tok->deleteNext(2);
|
||||
|
||||
unsigned int ternaryOplevel = 0;
|
||||
for (const Token *endTok = semicolon; endTok; endTok = endTok->next()) {
|
||||
for (const Token *endTok = colon; endTok; endTok = endTok->next()) {
|
||||
if (Token::Match(endTok, "(|[|{")) {
|
||||
endTok = endTok->link();
|
||||
}
|
||||
|
@ -4926,10 +4929,10 @@ bool Tokenizer::simplifyConstTernaryOp()
|
|||
else if (Token::Match(endTok, ")|}|]|;|,|:|>")) {
|
||||
if (endTok->str() == ":" && ternaryOplevel)
|
||||
--ternaryOplevel;
|
||||
else if (endTok->str() == ">" && !inTemplateParameter)
|
||||
else if (endTok->str() == ">" && !templateParameterEnd)
|
||||
;
|
||||
else {
|
||||
Token::eraseTokens(semicolon->tokAt(-2), endTok);
|
||||
Token::eraseTokens(colon->tokAt(-2), endTok);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ private:
|
|||
TEST_CASE(template53); // #4335 - bail out for valid code
|
||||
TEST_CASE(template54); // #6587 - memory corruption upon valid code
|
||||
TEST_CASE(template55); // #6604 - simplify "const const" to "const" in template instantiations
|
||||
TEST_CASE(template56); // #7117 - const ternary operator simplification as template parameter
|
||||
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||
TEST_CASE(template_unhandled);
|
||||
TEST_CASE(template_default_parameter);
|
||||
|
@ -1011,6 +1012,16 @@ private:
|
|||
"A<int> a(0);"));
|
||||
}
|
||||
|
||||
void template56() { // #7117
|
||||
tok("template<bool B> struct Foo { "
|
||||
" std::array<int, B ? 1 : 2> mfoo; "
|
||||
"}; "
|
||||
"void foo() { "
|
||||
" Foo<true> myFoo; "
|
||||
"}", /*simplify=*/true, /*debugwarnings=*/true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void template_enum() {
|
||||
const char code1[] = "template <class T>\n"
|
||||
"struct Unconst {\n"
|
||||
|
|
Loading…
Reference in New Issue