This commit is contained in:
parent
5036cb9ca6
commit
10fcf731d9
|
@ -354,6 +354,13 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok)
|
|||
tok = tok->link();
|
||||
if (tok)
|
||||
tok = tok->next();
|
||||
if (tok->str() == ">" && level == 0)
|
||||
return numberOfParameters;
|
||||
else if (tok->str() == "," && level == 0) {
|
||||
++numberOfParameters;
|
||||
tok = tok->next();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip std::
|
||||
|
@ -1930,12 +1937,14 @@ static Token *skipTernaryOp(Token *tok, Token *backToken)
|
|||
|
||||
void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end)
|
||||
{
|
||||
// start could be erased so use the token before start if available
|
||||
Token * first = (start && start->previous()) ? start->previous() : mTokenList.front();
|
||||
bool again = true;
|
||||
|
||||
while (again) {
|
||||
again = false;
|
||||
|
||||
for (Token *tok = start; tok && tok != end; tok = tok->next()) {
|
||||
for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) {
|
||||
if (tok->str() == "sizeof") {
|
||||
// sizeof('x')
|
||||
if (Token::Match(tok->next(), "( %char% )")) {
|
||||
|
@ -1980,11 +1989,11 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end)
|
|||
}
|
||||
}
|
||||
|
||||
if (simplifyCalculations(start, end))
|
||||
if (simplifyCalculations(first->next(), end))
|
||||
again = true;
|
||||
|
||||
for (Token *tok = start; tok && tok != end; tok = tok->next()) {
|
||||
if (tok->str() == "?" && tok->previous()->isNumber()) {
|
||||
for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) {
|
||||
if (tok->str() == "?" && (tok->previous()->isNumber() || tok->previous()->isBoolean())) {
|
||||
const int offset = (tok->previous()->str() == ")") ? 2 : 1;
|
||||
|
||||
// Find the token ":" then go to the next token
|
||||
|
@ -2043,24 +2052,60 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end)
|
|||
}
|
||||
}
|
||||
|
||||
for (Token *tok = start; tok && tok != end; tok = tok->next()) {
|
||||
if (Token::Match(tok, "( %num% )") && !Token::Match(tok->previous(), "%name%")) {
|
||||
for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) {
|
||||
if (Token::Match(tok, "( %num%|%bool% )") &&
|
||||
(tok->previous() && !Token::Match(tok->previous(), "%name%"))) {
|
||||
tok->deleteThis();
|
||||
tok->deleteNext();
|
||||
again = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool validTokenStart(bool bounded, const Token *tok, const Token *frontToken, int offset)
|
||||
{
|
||||
if (!bounded)
|
||||
return true;
|
||||
|
||||
if (frontToken)
|
||||
frontToken = frontToken->previous();
|
||||
|
||||
while (tok && offset <= 0) {
|
||||
if (tok == frontToken)
|
||||
return false;
|
||||
++offset;
|
||||
tok = tok->previous();
|
||||
}
|
||||
|
||||
return tok && offset > 0;
|
||||
}
|
||||
|
||||
static bool validTokenEnd(bool bounded, const Token *tok, const Token *backToken, int offset)
|
||||
{
|
||||
if (!bounded)
|
||||
return true;
|
||||
|
||||
while (tok && offset >= 0) {
|
||||
if (tok == backToken)
|
||||
return false;
|
||||
--offset;
|
||||
tok = tok->next();
|
||||
}
|
||||
|
||||
return tok && offset < 0;
|
||||
}
|
||||
|
||||
// TODO: This is not the correct class for simplifyCalculations(), so it
|
||||
// should be moved away.
|
||||
bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToken)
|
||||
{
|
||||
bool ret = false;
|
||||
const bool bounded = frontToken || backToken;
|
||||
if (!frontToken) {
|
||||
frontToken = mTokenList.front();
|
||||
}
|
||||
for (Token *tok = frontToken; tok != backToken; tok = tok->next()) {
|
||||
for (Token *tok = frontToken; tok && tok != backToken; tok = tok->next()) {
|
||||
// Remove parentheses around variable..
|
||||
// keep parentheses here: dynamic_cast<Fred *>(p);
|
||||
// keep parentheses here: A operator * (int);
|
||||
|
@ -2069,8 +2114,11 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
// keep parentheses here: operator new [] (size_t);
|
||||
// keep parentheses here: Functor()(a ... )
|
||||
// keep parentheses here: ) ( var ) ;
|
||||
if ((Token::Match(tok->next(), "( %name% ) ;|)|,|]") ||
|
||||
(Token::Match(tok->next(), "( %name% ) %cop%") && (tok->tokAt(2)->varId()>0 || !Token::Match(tok->tokAt(4), "[*&+-~]")))) &&
|
||||
if (validTokenEnd(bounded, tok, backToken, 4) &&
|
||||
(Token::Match(tok->next(), "( %name% ) ;|)|,|]") ||
|
||||
(Token::Match(tok->next(), "( %name% ) %cop%") &&
|
||||
(tok->tokAt(2)->varId()>0 ||
|
||||
!Token::Match(tok->tokAt(4), "[*&+-~]")))) &&
|
||||
!tok->isName() &&
|
||||
tok->str() != ">" &&
|
||||
tok->str() != ")" &&
|
||||
|
@ -2081,23 +2129,28 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::Match(tok->previous(), "(|&&|%oror% %char% %comp% %num% &&|%oror%|)")) {
|
||||
if (validTokenEnd(bounded, tok, backToken, 3) &&
|
||||
Token::Match(tok->previous(), "(|&&|%oror% %char% %comp% %num% &&|%oror%|)")) {
|
||||
tok->str(MathLib::toString(MathLib::toLongNumber(tok->str())));
|
||||
}
|
||||
|
||||
if (tok->isNumber()) {
|
||||
if (simplifyNumericCalculations(tok)) {
|
||||
if (tok && tok->isNumber()) {
|
||||
if (validTokenEnd(bounded, tok, backToken, 2) &&
|
||||
simplifyNumericCalculations(tok)) {
|
||||
ret = true;
|
||||
Token *prev = tok->tokAt(-2);
|
||||
while (prev && simplifyNumericCalculations(prev)) {
|
||||
while (validTokenStart(bounded, tok, frontToken, -2) &&
|
||||
prev && simplifyNumericCalculations(prev)) {
|
||||
tok = prev;
|
||||
prev = prev->tokAt(-2);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove redundant conditions (0&&x) (1||x)
|
||||
if (Token::Match(tok->previous(), "[(=,] 0 &&") ||
|
||||
Token::Match(tok->previous(), "[(=,] 1 %oror%")) {
|
||||
if (validTokenStart(bounded, tok, frontToken, -1) &&
|
||||
validTokenEnd(bounded, tok, backToken, 1) &&
|
||||
(Token::Match(tok->previous(), "[(=,] 0 &&") ||
|
||||
Token::Match(tok->previous(), "[(=,] 1 %oror%"))) {
|
||||
unsigned int par = 0;
|
||||
const Token *tok2 = tok;
|
||||
const bool andAnd = (tok->next()->str() == "&&");
|
||||
|
@ -2118,9 +2171,10 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
continue;
|
||||
}
|
||||
|
||||
if (tok->str() == "0") {
|
||||
if ((Token::Match(tok->previous(), "[+-] 0 %cop%|;") && isLowerThanMulDiv(tok->next())) ||
|
||||
(Token::Match(tok->previous(), "%or% 0 %cop%|;") && isLowerThanXor(tok->next()))) {
|
||||
if (tok->str() == "0" && validTokenStart(bounded, tok, frontToken, -1)) {
|
||||
if (validTokenEnd(bounded, tok, backToken, 1) &&
|
||||
((Token::Match(tok->previous(), "[+-] 0 %cop%|;") && isLowerThanMulDiv(tok->next())) ||
|
||||
(Token::Match(tok->previous(), "%or% 0 %cop%|;") && isLowerThanXor(tok->next())))) {
|
||||
tok = tok->previous();
|
||||
if (Token::Match(tok->tokAt(-4), "[;{}] %name% = %name% [+-|] 0 ;") &&
|
||||
tok->strAt(-3) == tok->previous()->str()) {
|
||||
|
@ -2131,22 +2185,26 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
tok->deleteNext(2);
|
||||
}
|
||||
ret = true;
|
||||
} else if (Token::Match(tok->previous(), "[=([,] 0 [+|]") ||
|
||||
Token::Match(tok->previous(), "return|case 0 [+|]")) {
|
||||
} else if (validTokenEnd(bounded, tok, backToken, 1) &&
|
||||
(Token::Match(tok->previous(), "[=([,] 0 [+|]") ||
|
||||
Token::Match(tok->previous(), "return|case 0 [+|]"))) {
|
||||
tok = tok->previous();
|
||||
tok->deleteNext(2);
|
||||
ret = true;
|
||||
} else if (Token::Match(tok->previous(), "[=[(,] 0 * %name%|%num% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "[=[(,] 0 * (") ||
|
||||
Token::Match(tok->previous(), "return|case 0 *|&& %name%|%num% ,|:|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 0 *|&& (")) {
|
||||
} else if ((((Token::Match(tok->previous(), "[=[(,] 0 * %name%|%num% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 0 *|&& %name%|%num% ,|:|;|=|%cop%")) &&
|
||||
validTokenEnd(bounded, tok, backToken, 3)) ||
|
||||
(((Token::Match(tok->previous(), "[=[(,] 0 * (") ||
|
||||
Token::Match(tok->previous(), "return|case 0 *|&& (")) &&
|
||||
validTokenEnd(bounded, tok, backToken, 2))))) {
|
||||
tok->deleteNext();
|
||||
if (tok->next()->str() == "(")
|
||||
eraseTokens(tok, tok->next()->link());
|
||||
tok->deleteNext();
|
||||
ret = true;
|
||||
} else if (Token::Match(tok->previous(), "[=[(,] 0 && *|& %any% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 0 && *|& %any% ,|:|;|=|%cop%")) {
|
||||
} else if (validTokenEnd(bounded, tok, backToken, 4) &&
|
||||
(Token::Match(tok->previous(), "[=[(,] 0 && *|& %any% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 0 && *|& %any% ,|:|;|=|%cop%"))) {
|
||||
tok->deleteNext();
|
||||
tok->deleteNext();
|
||||
if (tok->next()->str() == "(")
|
||||
|
@ -2156,16 +2214,18 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
}
|
||||
}
|
||||
|
||||
if (tok->str() == "1") {
|
||||
if (Token::Match(tok->previous(), "[=[(,] 1 %oror% %any% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 1 %oror% %any% ,|:|;|=|%cop%")) {
|
||||
if (tok->str() == "1" && validTokenStart(bounded, tok, frontToken, -1)) {
|
||||
if (validTokenEnd(bounded, tok, backToken, 3) &&
|
||||
(Token::Match(tok->previous(), "[=[(,] 1 %oror% %any% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 1 %oror% %any% ,|:|;|=|%cop%"))) {
|
||||
tok->deleteNext();
|
||||
if (tok->next()->str() == "(")
|
||||
eraseTokens(tok, tok->next()->link());
|
||||
tok->deleteNext();
|
||||
ret = true;
|
||||
} else if (Token::Match(tok->previous(), "[=[(,] 1 %oror% *|& %any% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 1 %oror% *|& %any% ,|:|;|=|%cop%")) {
|
||||
} else if (validTokenEnd(bounded, tok, backToken, 4) &&
|
||||
(Token::Match(tok->previous(), "[=[(,] 1 %oror% *|& %any% ,|]|)|;|=|%cop%") ||
|
||||
Token::Match(tok->previous(), "return|case 1 %oror% *|& %any% ,|:|;|=|%cop%"))) {
|
||||
tok->deleteNext();
|
||||
tok->deleteNext();
|
||||
if (tok->next()->str() == "(")
|
||||
|
@ -2175,7 +2235,10 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
}
|
||||
}
|
||||
|
||||
if (Token::Match(tok->tokAt(-2), "%any% * 1") || Token::Match(tok->previous(), "%any% 1 *")) {
|
||||
if ((Token::Match(tok->tokAt(-2), "%any% * 1") &&
|
||||
validTokenStart(bounded, tok, frontToken, -2)) ||
|
||||
(Token::Match(tok->previous(), "%any% 1 *") &&
|
||||
validTokenStart(bounded, tok, frontToken, -1))) {
|
||||
tok = tok->previous();
|
||||
if (tok->str() == "*")
|
||||
tok = tok->previous();
|
||||
|
@ -2184,15 +2247,19 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
}
|
||||
|
||||
// Remove parentheses around number..
|
||||
if (Token::Match(tok->tokAt(-2), "%op%|< ( %num% )") && tok->strAt(-2) != ">") {
|
||||
if (validTokenStart(bounded, tok, frontToken, -2) &&
|
||||
Token::Match(tok->tokAt(-2), "%op%|< ( %num% )") &&
|
||||
tok->strAt(-2) != ">") {
|
||||
tok = tok->previous();
|
||||
tok->deleteThis();
|
||||
tok->deleteNext();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::Match(tok->previous(), "( 0 [|+]") ||
|
||||
Token::Match(tok->previous(), "[|+-] 0 )")) {
|
||||
if (validTokenStart(bounded, tok, frontToken, -1) &&
|
||||
validTokenEnd(bounded, tok, backToken, 1) &&
|
||||
(Token::Match(tok->previous(), "( 0 [|+]") ||
|
||||
Token::Match(tok->previous(), "[|+-] 0 )"))) {
|
||||
tok = tok->previous();
|
||||
if (Token::Match(tok, "[|+-]"))
|
||||
tok = tok->previous();
|
||||
|
@ -2200,10 +2267,13 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
|
|||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "%num% %comp% %num%") &&
|
||||
if (validTokenEnd(bounded, tok, backToken, 2) &&
|
||||
Token::Match(tok, "%num% %comp% %num%") &&
|
||||
MathLib::isInt(tok->str()) &&
|
||||
MathLib::isInt(tok->strAt(2))) {
|
||||
if (Token::Match(tok->previous(), "(|&&|%oror%") && Token::Match(tok->tokAt(3), ")|&&|%oror%|?")) {
|
||||
if (validTokenStart(bounded, tok, frontToken, -1) &&
|
||||
Token::Match(tok->previous(), "(|&&|%oror%") &&
|
||||
Token::Match(tok->tokAt(3), ")|&&|%oror%|?")) {
|
||||
const MathLib::bigint op1(MathLib::toLongNumber(tok->str()));
|
||||
const std::string &cmp(tok->next()->str());
|
||||
const MathLib::bigint op2(MathLib::toLongNumber(tok->strAt(2)));
|
||||
|
|
|
@ -141,6 +141,7 @@ private:
|
|||
TEST_CASE(template101); // #8968
|
||||
TEST_CASE(template102); // #9005
|
||||
TEST_CASE(template103);
|
||||
TEST_CASE(template104); // #9021
|
||||
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_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||
|
@ -184,6 +185,8 @@ private:
|
|||
|
||||
TEST_CASE(templateTypeDeduction1); // #8962
|
||||
TEST_CASE(templateTypeDeduction2);
|
||||
|
||||
TEST_CASE(simplifyTemplateArgs);
|
||||
}
|
||||
|
||||
std::string tok(const char code[], bool debugwarnings = false, Settings::PlatformType type = Settings::Native) {
|
||||
|
@ -1275,7 +1278,7 @@ private:
|
|||
"void foo ( ) { "
|
||||
"Foo<true> myFoo ; "
|
||||
"} struct Foo<true> { "
|
||||
"std :: array < int , true ? 1 : 2 > mfoo ; "
|
||||
"std :: array < int , 1 > mfoo ; "
|
||||
"} ;";
|
||||
ASSERT_EQUALS(expected, tok(code, true));
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
@ -2354,6 +2357,32 @@ private:
|
|||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template104() { // #9021
|
||||
const char code[] = "template < int i >\n"
|
||||
"auto key ( ) { return hana :: test :: ct_eq < i > { } ; }\n"
|
||||
"template < int i >\n"
|
||||
"auto val ( ) { return hana :: test :: ct_eq < - i > { } ; }\n"
|
||||
"template < int i , int j >\n"
|
||||
"auto p ( ) { return :: minimal_product ( key < i > ( ) , val < j > ( ) ) ; }\n"
|
||||
"int main ( ) {\n"
|
||||
" BOOST_HANA_CONSTANT_CHECK ( hana :: equal (\n"
|
||||
" hana :: at_key ( hana :: make_map ( p < 0 , 0 > ( ) ) , key < 0 > ( ) ) ,\n"
|
||||
" val < 0 > ( ) ) ) ;\n"
|
||||
"}";
|
||||
const char exp[] = "auto key<0> ( ) ; "
|
||||
"auto val<0> ( ) ; "
|
||||
"auto p<0,0> ( ) ; "
|
||||
"int main ( ) { "
|
||||
"BOOST_HANA_CONSTANT_CHECK ( hana :: equal ( "
|
||||
"hana :: at_key ( hana :: make_map ( p<0,0> ( ) ) , key<0> ( ) ) , "
|
||||
"val<0> ( ) ) ) ; "
|
||||
"} "
|
||||
"auto p<0,0> ( ) { return :: minimal_product ( key<0> ( ) , val<0> ( ) ) ; } "
|
||||
"auto val<0> ( ) { return hana :: test :: ct_eq < - 0 > { } ; } "
|
||||
"auto key<0> ( ) { return hana :: test :: ct_eq < 0 > { } ; }";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||
const char code[] = "template <typename T> struct C {};\n"
|
||||
"template <typename T> struct S {a};\n"
|
||||
|
@ -3435,6 +3464,23 @@ private:
|
|||
TODO_ASSERT_EQUALS(expected, actual, tok(code));
|
||||
}
|
||||
|
||||
void simplifyTemplateArgs() {
|
||||
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < ( 2 ) >;"));
|
||||
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < 1 + 1 >;"));
|
||||
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < ( 1 + 1 ) >;"));
|
||||
|
||||
ASSERT_EQUALS("foo<2,2> = 4 ; foo<2,2> ;", tok("template<int N, int M> foo = N * M; foo < ( 2 ), ( 2 ) >;"));
|
||||
ASSERT_EQUALS("foo<2,2> = 4 ; foo<2,2> ;", tok("template<int N, int M> foo = N * M; foo < 1 + 1, 1 + 1 >;"));
|
||||
ASSERT_EQUALS("foo<2,2> = 4 ; foo<2,2> ;", tok("template<int N, int M> foo = N * M; foo < ( 1 + 1 ), ( 1 + 1 ) >;"));
|
||||
|
||||
ASSERT_EQUALS("foo<true> = true ; foo<true> ;", tok("template<bool N> foo = N; foo < true ? true : false >;"));
|
||||
ASSERT_EQUALS("foo<false> = false ; foo<false> ;", tok("template<bool N> foo = N; foo < false ? true : false >;"));
|
||||
ASSERT_EQUALS("foo<true> = true ; foo<true> ;", tok("template<bool N> foo = N; foo < 1 ? true : false >;"));
|
||||
ASSERT_EQUALS("foo<false> = false ; foo<false> ;", tok("template<bool N> foo = N; foo < 0 ? true : false >;"));
|
||||
ASSERT_EQUALS("foo<true> = true ; foo<true> ;", tok("template<bool N> foo = N; foo < (1 + 1 ) ? true : false >;"));
|
||||
ASSERT_EQUALS("foo<false> = false ; foo<false> ;", tok("template<bool N> foo = N; foo < ( 1 - 1) ? true : false >;"));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestSimplifyTemplate)
|
||||
|
|
Loading…
Reference in New Issue