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:
parent
61935802d1
commit
312fdf157b
|
@ -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'
|
||||
|
|
|
@ -508,6 +508,8 @@ public:
|
|||
void simplifyExternC();
|
||||
|
||||
void simplifyRoundCurlyParentheses();
|
||||
|
||||
void simplifyTypeIntrinsics();
|
||||
|
||||
void simplifySQL();
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue