Fix issue 9144: Syntax error with type intrinsics (#1852)

* Fix issue 9144: Syntax error with type intrinsics

* Only run when using cpp
This commit is contained in:
Paul Fultz II 2019-05-26 23:54:21 -05:00 committed by Daniel Marjamäki
parent 61935802d1
commit 312fdf157b
4 changed files with 115 additions and 0 deletions

View File

@ -4436,6 +4436,9 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// Remove redundant parentheses
simplifyRedundantParentheses();
if (isCPP())
simplifyTypeIntrinsics();
if (!isC()) {
// Handle templates..
if (mTimerResults) {
@ -7937,6 +7940,56 @@ bool Tokenizer::simplifyRedundantParentheses()
return ret;
}
void Tokenizer::simplifyTypeIntrinsics()
{
static const std::unordered_map<std::string, std::string> intrinsics = {
{ "__has_nothrow_assign", "has_nothrow_assign" },
{ "__has_nothrow_constructor", "has_nothrow_constructor" },
{ "__has_nothrow_copy", "has_nothrow_copy" },
{ "__has_trivial_assign", "has_trivial_assign" },
{ "__has_trivial_constructor", "has_trivial_constructor" },
{ "__has_trivial_copy", "has_trivial_copy" },
{ "__has_trivial_destructor", "has_trivial_destructor" },
{ "__has_virtual_destructor", "has_virtual_destructor" },
{ "__is_abstract", "is_abstract" },
{ "__is_aggregate", "is_aggregate" },
{ "__is_assignable", "is_assignable" },
{ "__is_base_of", "is_base_of" },
{ "__is_class", "is_class" },
{ "__is_constructible", "is_constructible" },
{ "__is_convertible_to", "is_convertible_to" },
{ "__is_destructible", "is_destructible" },
{ "__is_empty", "is_empty" },
{ "__is_enum", "is_enum" },
{ "__is_final", "is_final" },
{ "__is_nothrow_assignable", "is_nothrow_assignable" },
{ "__is_nothrow_constructible", "is_nothrow_constructible" },
{ "__is_nothrow_destructible", "is_nothrow_destructible" },
{ "__is_pod", "is_pod" },
{ "__is_polymorphic", "is_polymorphic" },
{ "__is_trivially_assignable", "is_trivially_assignable" },
{ "__is_trivially_constructible", "is_trivially_constructible" },
{ "__is_union", "is_union" },
};
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (!Token::Match(tok, "%name% ("))
continue;
auto p = intrinsics.find(tok->str());
if (p == intrinsics.end())
continue;
Token * end = tok->next()->link();
Token * prev = tok->previous();
tok->str(p->second);
prev->insertToken("::");
prev->insertToken("std");
tok->next()->str("<");
end->str(">");
end->insertToken("}");
end->insertToken("{");
Token::createMutualLinks(end->tokAt(1), end->tokAt(2));
}
}
void Tokenizer::simplifyCharAt()
{
// Replace "string"[0] with 's'

View File

@ -508,6 +508,8 @@ public:
void simplifyExternC();
void simplifyRoundCurlyParentheses();
void simplifyTypeIntrinsics();
void simplifySQL();

View File

@ -146,6 +146,7 @@ private:
TEST_CASE(template106);
TEST_CASE(template107); // #8663
TEST_CASE(template108); // #9109
TEST_CASE(template109); // #9144
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)
@ -2531,6 +2532,52 @@ private:
}
}
void template109() { // #9144
{
const char code[] = "namespace a {\n"
"template <typename b, bool = __is_empty(b) && __is_final(b)> struct c;\n"
"}\n"
"namespace boost {\n"
"using a::c;\n"
"}\n"
"namespace d = boost;\n"
"using d::c;\n"
"template <typename...> struct e {};\n"
"static_assert(sizeof(e<>) == sizeof(e<c<int>, c<int>, int>), \"\");\n";
const char exp[] = "namespace a { "
"template < typename b , bool = std :: is_empty < b > { } && std :: is_final < b > { } > struct c ; "
"} "
"namespace boost { "
"using a :: c ; "
"} using boost :: c ; "
"struct e<> ; "
"struct e<c<int>,c<int>,int> ; "
"static_assert ( sizeof ( e<> ) == sizeof ( e<c<int>,c<int>,int> ) , \"\" ) ; "
"struct e<> { } ; "
"struct e<c<int>,c<int>,int> { } ;";
ASSERT_EQUALS(exp, tok(code));
}
{
const char code[] = "template <typename b, bool = __is_empty(b) && __is_final(b)> struct c;\n"
"template <typename...> struct e {};\n"
"static_assert(sizeof(e<>) == sizeof(e<c<int>, c<int>, int>), "");\n";
const char exp[] = "template < typename b , bool = std :: is_empty < b > { } && std :: is_final < b > { } > struct c ; "
"struct e<> ; "
"struct e<c<int>,c<int>,int> ; "
"static_assert ( sizeof ( e<> ) == sizeof ( e<c<int>,c<int>,int> ) , ) ; "
"struct e<> { } ; "
"struct e<c<int>,c<int>,int> { } ;";
ASSERT_EQUALS(exp, tok(code));
}
{
const char code[] = "template <typename b, bool = __is_empty(b) && __is_final(b)> struct c{};\n"
"c<int> cc;\n";
const char exp[] = "template < typename b , bool = std :: is_empty < b > { } && std :: is_final < b > { } > struct c { } ; "
"c < int > cc ;";
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"

View File

@ -7694,6 +7694,19 @@ private:
"template <> struct a<int> {\n"
"template <typename e> constexpr auto g() { d<0 || e::f>; return 0; }\n"
"};\n"))
// #9144
ASSERT_NO_THROW(tokenizeAndStringify(
"namespace a {\n"
"template <typename b, bool = __is_empty(b) && __is_final(b)> struct c;\n"
"}\n"
"namespace boost {\n"
"using a::c;\n"
"}\n"
"namespace d = boost;\n"
"using d::c;\n"
"template <typename...> struct e {};\n"
"static_assert(sizeof(e<>) == sizeof(e<c<int>, c<int>, int>), \"\");\n"))
}
void noCrash1() {