diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-04-04 14:01:12 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-04-04 14:56:04 +0300 |
commit | 52b63882560c34afaf0575233cbb815b0de5d87d (patch) | |
tree | 730e86e78124c74d286e7227f72e830fde44f834 /src | |
parent | 1ba2daa59361c916ad0a39d33bfc54899d8613a3 (diff) | |
download | cflow-52b63882560c34afaf0575233cbb815b0de5d87d.tar.gz cflow-52b63882560c34afaf0575233cbb815b0de5d87d.tar.bz2 |
Improve parsing of typecasts.
* src/cflow.rc: Mark 'typeof' as wrapper.
* src/parser.c (expression): Allow for wrappers and explicit
structures in typecasts.
(dcl): Don't skip token that follows the wrapper.
* tests/struct.at: Test for unions in typecasts.
Diffstat (limited to 'src')
-rw-r--r-- | src/c.l | 4 | ||||
-rw-r--r-- | src/cflow.rc | 3 | ||||
-rw-r--r-- | src/parser.c | 36 |
3 files changed, 32 insertions, 11 deletions
@@ -76,9 +76,7 @@ typedef return TYPEDEF; struct {yylval.str = "struct"; return STRUCT;} union {yylval.str = "union"; return STRUCT;} enum {yylval.str = "enum"; return STRUCT;} -\* { yylval.str = "*"; - return MODIFIER; - } +\* {yylval.str = "*"; return MODIFIER;} /* Operators * */ diff --git a/src/cflow.rc b/src/cflow.rc index 768fae9..4ce09fd 100644 --- a/src/cflow.rc +++ b/src/cflow.rc @@ -5,6 +5,9 @@ --symbol __const:=const --symbol __restrict:=restrict --symbol __extension__:qualifier +--symbol typeof:wrapper +--symbol __typeof:=typeof +--symbol __typeof__:=typeof --symbol __attribute__:wrapper --symbol __asm__:wrapper --symbol __nonnull:wrapper diff --git a/src/parser.c b/src/parser.c index a3724e0..b71d14d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -594,6 +594,14 @@ expression() switch (tok.type) { case ';': return; + case PARM_WRAPPER: + if (skip_balanced('(', ')', 0) == -1) { + file_error(_("unexpected end of file in expression"), + NULL); + return; + } + putback(); + break; case LBRACE: case LBRACE0: case RBRACE: @@ -637,12 +645,23 @@ expression() break; case '(': /* maybe typecast */ - if (nexttoken() == TYPE || tok.type == STRUCT) - skip_to(')'); - else { - putback(); + if (nexttoken() == TYPE || tok.type == STRUCT) { + if (skip_balanced('(', ')', 1) == -1) { + file_error(_("unexpected end of file in expression"), + NULL); + return; + } + if (tok.type == LBRACE || tok.type == LBRACE0) { + if (skip_balanced('{', '}', 1) == -1) { + file_error(_("unexpected end of file in expression"), + NULL); + return; + } + } + } else { parens_lev++; } + putback(); break; case ')': parens_lev--; @@ -895,6 +914,7 @@ dcl(Ident *idptr) NULL); return 1; } + putback(); } else if (tok.type == IDENTIFIER) { int type; @@ -1066,7 +1086,7 @@ func_body() parse_declaration(&ident, 0); break; case LBRACE0: - case '{': + case LBRACE: level++; break; case RBRACE0: @@ -1080,7 +1100,7 @@ func_body() } /* else: */ /* FALLTHRU */ - case '}': + case RBRACE: delete_autos(level); level--; break; @@ -1088,10 +1108,10 @@ func_body() if (verbose) file_error(_("unexpected end of file in function body"), NULL); - caller = NULL; - return; + goto end; } } +end: caller = NULL; } |