Tokenizer: Improve handling of block declarations (C extension)

This commit is contained in:
Daniel Marjamäki 2016-01-04 09:59:53 +01:00
parent 036306d7c2
commit b748453b30
2 changed files with 42 additions and 29 deletions

View File

@ -9295,18 +9295,26 @@ void Tokenizer::simplifyAsm()
void Tokenizer::simplifyAsm2() void Tokenizer::simplifyAsm2()
{ {
// Block declarations: ^{}
// A C extension used to create lambda like closures.
// Put ^{} statements in asm() // Put ^{} statements in asm()
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::simpleMatch(tok, "^ {")) { if (tok->str() != "^")
continue;
if (Token::simpleMatch(tok, "^ {") || Token::simpleMatch(tok->linkAt(1), ") {")) {
Token * start = tok; Token * start = tok;
while (start && !Token::Match(start, "[;{}=]")) { while (start && !Token::Match(start, "[;{}=]")) {
if (start->link() && start->str() == ")") if (start->link() && Token::Match(start, ")|]|>"))
start = start->link(); start = start->link();
start = start->previous(); start = start->previous();
} }
if (start) if (start)
start = start->next(); start = start->next();
const Token *last = tok->next()->link(); const Token *last = tok->next()->link();
if (Token::simpleMatch(last, ") {"))
last = last->linkAt(1);
if (start != tok) { if (start != tok) {
last = last->next(); last = last->next();
while (last && !Token::Match(last, "[;{})]")) { while (last && !Token::Match(last, "[;{})]")) {
@ -9337,9 +9345,9 @@ void Tokenizer::simplifyAsm2()
} }
} }
} }
// When the assembly code has been cleaned up, no @ is allowed // When the assembly code has been cleaned up, no @ is allowed
for (const Token *tok = list.front(); tok; tok = tok->next()) { for (const Token *tok = list.front(); tok; tok = tok->next()) {
assert(list.validateToken(tok)); // see #7185 "crash: Tokenizer::simplifyAsm2 on invalid code"
if (tok->str() == "(") { if (tok->str() == "(") {
tok = tok->link(); tok = tok->link();
if (!tok) if (!tok)

View File

@ -63,7 +63,6 @@ private:
TEST_CASE(tokenize25); // #4239 (segmentation fault) TEST_CASE(tokenize25); // #4239 (segmentation fault)
TEST_CASE(tokenize26); // #4245 (segmentation fault) TEST_CASE(tokenize26); // #4245 (segmentation fault)
TEST_CASE(tokenize27); // #4525 (segmentation fault) TEST_CASE(tokenize27); // #4525 (segmentation fault)
TEST_CASE(tokenize28); // #4725 (writing asm() around "^{}")
TEST_CASE(tokenize31); // #3503 (Wrong handling of member function taking function pointer as argument) TEST_CASE(tokenize31); // #3503 (Wrong handling of member function taking function pointer as argument)
TEST_CASE(tokenize32); // #5884 (fsanitize=undefined: left shift of negative value -10000 in lib/templatesimplifier.cpp:852:46) TEST_CASE(tokenize32); // #5884 (fsanitize=undefined: left shift of negative value -10000 in lib/templatesimplifier.cpp:852:46)
TEST_CASE(tokenize33); // #5780 Various crashes on valid template code TEST_CASE(tokenize33); // #5780 Various crashes on valid template code
@ -97,6 +96,7 @@ private:
TEST_CASE(removeCast17); // #6110 - don't remove any parentheses in 'a(b)(c)' TEST_CASE(removeCast17); // #6110 - don't remove any parentheses in 'a(b)(c)'
TEST_CASE(inlineasm); TEST_CASE(inlineasm);
TEST_CASE(simplifyAsm2); // #4725 (writing asm() around "^{}")
TEST_CASE(ifAddBraces1); TEST_CASE(ifAddBraces1);
TEST_CASE(ifAddBraces2); TEST_CASE(ifAddBraces2);
@ -769,31 +769,6 @@ private:
tokenizeAndStringify("static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) internal_function __attribute__ ((pure));"); tokenizeAndStringify("static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) internal_function __attribute__ ((pure));");
} }
// #4725 - ^{}
void tokenize28() {
ASSERT_EQUALS("void f ( ) { asm ( \"^{}\" ) ; }", tokenizeAndStringify("void f() { ^{} }"));
ASSERT_EQUALS("void f ( ) { asm ( \"x(^{});\" ) ; }", tokenizeAndStringify("void f() { x(^{}); }"));
ASSERT_EQUALS("void f ( ) { asm ( \"foo(A(),^{bar();});\" ) ; }", tokenizeAndStringify("void f() { foo(A(), ^{ bar(); }); }"));
ASSERT_EQUALS("int f0 ( Args args ) {\n"
"asm ( \"return^{returnsizeof...(Args);}()+\" ) ;\n"
"\n"
"asm ( \"^{returnsizeof...(args);}\" ) ;\n"
"\n"
"\n"
"} ;", tokenizeAndStringify("int f0(Args args) {\n"
" return ^{\n"
" return sizeof...(Args);\n"
" }() + ^ {\n"
" return sizeof...(args);\n"
" }();\n"
"};"));
ASSERT_EQUALS("int ( ^ block ) ( void ) = asm ( \"^{staticinttest=0;returntest;}\" ) ;",
tokenizeAndStringify("int(^block)(void) = ^{\n"
" static int test = 0;\n"
" return test;\n"
"};"));
}
// #3503 - don't "simplify" SetFunction member function to a variable // #3503 - don't "simplify" SetFunction member function to a variable
void tokenize31() { void tokenize31() {
ASSERT_EQUALS("struct TTestClass { TTestClass ( ) { }\n" ASSERT_EQUALS("struct TTestClass { TTestClass ( ) { }\n"
@ -1021,6 +996,36 @@ private:
ASSERT_EQUALS(";\n\nasm ( \"\"mov ax,bx\"\" ) ;", tokenizeAndStringify(";\n\n__asm__ volatile ( \"mov ax,bx\" );", true)); ASSERT_EQUALS(";\n\nasm ( \"\"mov ax,bx\"\" ) ;", tokenizeAndStringify(";\n\n__asm__ volatile ( \"mov ax,bx\" );", true));
} }
// #4725 - ^{}
void simplifyAsm2() {
ASSERT_EQUALS("void f ( ) { asm ( \"^{}\" ) ; }", tokenizeAndStringify("void f() { ^{} }"));
ASSERT_EQUALS("void f ( ) { asm ( \"x(^{});\" ) ; }", tokenizeAndStringify("void f() { x(^{}); }"));
ASSERT_EQUALS("void f ( ) { asm ( \"foo(A(),^{bar();});\" ) ; }", tokenizeAndStringify("void f() { foo(A(), ^{ bar(); }); }"));
ASSERT_EQUALS("int f0 ( Args args ) {\n"
"asm ( \"return^{returnsizeof...(Args);}()+\" ) ;\n"
"\n"
"asm ( \"^{returnsizeof...(args);}\" ) ;\n"
"\n"
"\n"
"} ;", tokenizeAndStringify("int f0(Args args) {\n"
" return ^{\n"
" return sizeof...(Args);\n"
" }() + ^ {\n"
" return sizeof...(args);\n"
" }();\n"
"};"));
ASSERT_EQUALS("int ( ^ block ) ( void ) = asm ( \"^{staticinttest=0;returntest;}\" ) ;",
tokenizeAndStringify("int(^block)(void) = ^{\n"
" static int test = 0;\n"
" return test;\n"
"};"));
ASSERT_EQUALS("; asm ( \"returnf([=]().int^{});\" ) ;",
tokenizeAndStringify("; return f([=]() -> int^{});")); // #7185 - garbage
ASSERT_EQUALS("; asm ( \"returnf(^(void){somecode});\" ) ;",
tokenizeAndStringify("; return f(^(void){somecode});"));
}
void ifAddBraces1() { void ifAddBraces1() {
const char code[] = "void f()\n" const char code[] = "void f()\n"
"{\n" "{\n"