diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-02-08 17:28:04 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-02-08 17:28:04 +0200 |
commit | b64ca53d3f65ea7d51afa977e9d4bed808f494f7 (patch) | |
tree | ec7e7d1b184c25b716a4a49844fad3cf41cc36e7 | |
parent | b0cc5efa1a1c8145981846cfa8e80cc67d12ebf6 (diff) | |
download | cflow-b64ca53d3f65ea7d51afa977e9d4bed808f494f7.tar.gz cflow-b64ca53d3f65ea7d51afa977e9d4bed808f494f7.tar.bz2 |
Fix https://savannah.gnu.org/bugs/index.php?47110
* src/parser.c (expression): Fix parsing of type casts.
* tests/memberof.at: New test case.
* tests/testsuite.at: Add new test.
* tests/Makefile.am: Add new test.
-rw-r--r-- | src/parser.c | 17 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/memberof.at | 62 | ||||
-rw-r--r-- | tests/testsuite.at | 1 |
4 files changed, 78 insertions, 3 deletions
diff --git a/src/parser.c b/src/parser.c index 2b173c2..391fe33 100644 --- a/src/parser.c +++ b/src/parser.c @@ -602,32 +602,43 @@ expression() nexttoken(); if (tok.type == '(') { call(name, line); parens_lev++; } else { reference(name, line); + + /* MEMBER_OF can be preceded by a closing paren, as in + (*a)->b + */ + while (parens_lev > 0 && tok.type == ')') { + parens_lev--; + nexttoken(); + } + if (tok.type == MEMBER_OF) { - while (tok.type == MEMBER_OF) - nexttoken(); + nexttoken(); } else { putback(); } } break; case '(': /* maybe typecast */ - if (nexttoken() == TYPE) + if (nexttoken() == TYPE || tok.type == STRUCT) skip_to(')'); else { putback(); parens_lev++; } break; case ')': parens_lev--; break; + case MEMBER_OF: + nexttoken(); + break; } nexttoken(); } } void diff --git a/tests/Makefile.am b/tests/Makefile.am index 0beb3b3..d78b7c5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -47,12 +47,13 @@ TESTSUITE_AT = \ fdecl.at\ funcarg.at\ hiding.at\ include.at\ invalid.at\ knr.at\ + memberof.at\ multi.at\ nfarg.at\ nfparg.at\ parm.at\ pwrapper.at\ recurse.at\ diff --git a/tests/memberof.at b/tests/memberof.at new file mode 100644 index 0000000..42e9ec6 --- /dev/null +++ b/tests/memberof.at @@ -0,0 +1,62 @@ +# This file is part of GNU cflow testsuite. -*- Autotest -*- +# Copyright (C) 2016-2019 Sergey Poznyakoff +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([member of]) +AT_KEYWORDS([memberof]) + +CFLOW_CHECK( +[int bar(struct foo *a) { + return a.bar(); +} +], +[bar() <int bar (struct foo *a) at prog:1> +]) + +# https://savannah.gnu.org/bugs/index.php?47110 +CFLOW_CHECK( +[int bar(struct foo *a) { + return (*a).bar(); +} +], +[bar() <int bar (struct foo *a) at prog:1> +]) + +CFLOW_CHECK( +[int bar(struct foo **a) { + return (*a)->bar(); +} +], +[bar() <int bar (struct foo **a) at prog:1> +]) + +CFLOW_CHECK( +[int bar(void *a) { + return (*(struct foo*)a).bar(); +} +], +[bar() <int bar (void *a) at prog:1> +]) + +CFLOW_CHECK( +[int bar(void *a) { + return (*(struct foo*)(((struct qux*)a)->foo)).bar(); +} +], +[bar() <int bar (void *a) at prog:1> +]) + +AT_CLEANUP + diff --git a/tests/testsuite.at b/tests/testsuite.at index 766e018..baf997b 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -69,8 +69,9 @@ m4_include([struct00.at]) m4_include([struct01.at]) m4_include([struct02.at]) m4_include([struct03.at]) m4_include([struct04.at]) m4_include([decl01.at]) m4_include([invalid.at]) +m4_include([memberof.at]) # End of testsuite.at |