Fix ternary operator simplification to accept template parameters. (#2048)

Also simplify decltype of bool and numeric literals in template
arguments.
This commit is contained in:
IOBYTE 2019-07-28 15:52:52 -04:00 committed by Daniel Marjamäki
parent badc573b80
commit 07ac6c5f08
4 changed files with 94 additions and 8 deletions

View File

@ -2378,7 +2378,9 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end)
again = true;
for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) {
if (tok->str() == "?" && (tok->previous()->isNumber() || tok->previous()->isBoolean())) {
if (tok->str() == "?" &&
((tok->previous()->isNumber() || tok->previous()->isBoolean()) ||
Token::Match(tok->tokAt(-3), "( %bool%|%num% )"))) {
const int offset = (tok->previous()->str() == ")") ? 2 : 1;
// Find the token ":" then go to the next token
@ -2415,10 +2417,10 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end)
unsigned int ternaryOplevel = 0;
for (const Token *endTok = colon; endTok; endTok = endTok->next()) {
if (Token::Match(endTok, "(|[|{")) {
if (Token::Match(endTok, "(|[|{"))
endTok = endTok->link();
}
else if (endTok->str() == "<" && (endTok->strAt(1) == ">" || templateParameters(endTok)))
endTok = endTok->findClosingBracket();
else if (endTok->str() == "?")
++ternaryOplevel;
else if (Token::Match(endTok, ")|}|]|;|,|:|>")) {
@ -2529,6 +2531,37 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
ret = true;
}
if (validTokenEnd(bounded, tok, backToken, 3) &&
Token::Match(tok, "decltype ( %bool%|%num% )")) {
tok->deleteThis();
tok->deleteThis();
if (tok->isBoolean())
tok->str("bool");
else if (MathLib::isFloat(tok->str())) {
// MathLib::getSuffix doesn't work for floating point numbers
char suffix = tok->str().back();
if (suffix == 'f' || suffix == 'F')
tok->str("float");
else if (suffix == 'l' || suffix == 'L') {
tok->str("double");
tok->isLong(true);
} else
tok->str("double");
} else if (MathLib::isInt(tok->str())) {
std::string suffix = MathLib::getSuffix(tok->str());
if (suffix.find("LL") != std::string::npos) {
tok->str("long");
tok->isLong(true);
} else if (suffix.find('L') != std::string::npos)
tok->str("long");
else
tok->str("int");
tok->isUnsigned(suffix.find('U') != std::string::npos);
}
tok->deleteNext();
ret = true;
}
if (validTokenEnd(bounded, tok, backToken, 2) &&
Token::Match(tok, "char|short|int|long { }")) {
tok->str("0"); // FIXME add type suffix

View File

@ -5884,10 +5884,10 @@ bool Tokenizer::simplifyConstTernaryOp()
int ternaryOplevel = 0;
for (const Token *endTok = colon; endTok; endTok = endTok->next()) {
if (Token::Match(endTok, "(|[|{")) {
if (Token::Match(endTok, "(|[|{"))
endTok = endTok->link();
}
else if (endTok->str() == "<" && (endTok->strAt(1) == ">" || mTemplateSimplifier->templateParameters(endTok)))
endTok = endTok->findClosingBracket();
else if (endTok->str() == "?")
++ternaryOplevel;
else if (Token::Match(endTok, ")|}|]|;|,|:|>")) {
@ -5904,7 +5904,6 @@ bool Tokenizer::simplifyConstTernaryOp()
}
}
}
return ret;
}

View File

@ -222,6 +222,8 @@ private:
TEST_CASE(template_variable_2);
TEST_CASE(template_variable_3);
TEST_CASE(template_variable_4);
TEST_CASE(simplifyDecltype);
}
std::string tok(const char code[], bool debugwarnings = false, Settings::PlatformType type = Settings::Native) {
@ -4381,6 +4383,51 @@ private:
"void test<int> ( ) { }";
ASSERT_EQUALS(expected, tok(code));
}
void simplifyDecltype() {
const char code[] = "template<typename T> class type { };\n"
"type<decltype(true)> b;\n"
"type<decltype(0)> i;\n"
"type<decltype(0U)> ui;\n"
"type<decltype(0L)> l;\n"
"type<decltype(0UL)> ul;\n"
"type<decltype(0LL)> ll;\n"
"type<decltype(0ULL)> ull;\n"
"type<decltype(0.0)> d;\n"
"type<decltype(0.0F)> f;\n"
"type<decltype(0.0L)> ld;";
const char expected[] = "class type<bool> ; "
"class type<int> ; "
"class type<unsignedint> ; "
"class type<long> ; "
"class type<unsignedlong> ; "
"class type<longlong> ; "
"class type<unsignedlonglong> ; "
"class type<double> ; "
"class type<float> ; "
"class type<longdouble> ; "
"type<bool> b ; "
"type<int> i ; "
"type<unsignedint> ui ; "
"type<long> l ; "
"type<unsignedlong> ul ; "
"type<longlong> ll ; "
"type<unsignedlonglong> ull ; "
"type<double> d ; "
"type<float> f ; "
"type<longdouble> ld ; "
"class type<bool> { } ; "
"class type<int> { } ; "
"class type<unsignedint> { } ; "
"class type<long> { } ; "
"class type<unsignedlong> { } ; "
"class type<longlong> { } ; "
"class type<unsignedlonglong> { } ; "
"class type<double> { } ; "
"class type<float> { } ; "
"class type<longdouble> { } ;";
ASSERT_EQUALS(expected, tok(code));
}
};
REGISTER_TEST(TestSimplifyTemplate)

View File

@ -3407,6 +3407,13 @@ private:
ASSERT_EQUALS("; x = * b ;", tok("; x = (false)?*a:*b;"));
ASSERT_EQUALS("void f ( ) { return 1 ; }", tok("void f() { char *p=0; return (p==0)?1:2; }"));
}
{
ASSERT_EQUALS("; type = decay_t < decltype ( declval < T > ( ) ) > ;",
tok("; type = decay_t<decltype(true ? declval<T>() : declval<U>())>;"));
ASSERT_EQUALS("; type = decay_t < decltype ( declval < U > ( ) ) > ;",
tok("; type = decay_t<decltype(false ? declval<T>() : declval<U>())>;"));
}
}
void calculations() {