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 | |||
@@ -605,9 +605,17 @@ expression() | |||
605 | parens_lev++; | 605 | parens_lev++; |
606 | } else { | 606 | } else { |
607 | reference(name, line); | 607 | reference(name, line); |
608 | |||
609 | /* MEMBER_OF can be preceded by a closing paren, as in | ||
610 | (*a)->b | ||
611 | */ | ||
612 | while (parens_lev > 0 && tok.type == ')') { | ||
613 | parens_lev--; | ||
614 | nexttoken(); | ||
615 | } | ||
616 | |||
608 | if (tok.type == MEMBER_OF) { | 617 | if (tok.type == MEMBER_OF) { |
609 | while (tok.type == MEMBER_OF) | 618 | nexttoken(); |
610 | nexttoken(); | ||
611 | } else { | 619 | } else { |
612 | putback(); | 620 | putback(); |
613 | } | 621 | } |
@@ -615,7 +623,7 @@ expression() | |||
615 | break; | 623 | break; |
616 | case '(': | 624 | case '(': |
617 | /* maybe typecast */ | 625 | /* maybe typecast */ |
618 | if (nexttoken() == TYPE) | 626 | if (nexttoken() == TYPE || tok.type == STRUCT) |
619 | skip_to(')'); | 627 | skip_to(')'); |
620 | else { | 628 | else { |
621 | putback(); | 629 | putback(); |
@@ -625,6 +633,9 @@ expression() | |||
625 | case ')': | 633 | case ')': |
626 | parens_lev--; | 634 | parens_lev--; |
627 | break; | 635 | break; |
636 | case MEMBER_OF: | ||
637 | nexttoken(); | ||
638 | break; | ||
628 | } | 639 | } |
629 | nexttoken(); | 640 | nexttoken(); |
630 | } | 641 | } |
diff --git a/tests/Makefile.am b/tests/Makefile.am index 0beb3b3..d78b7c5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am | |||
@@ -50,6 +50,7 @@ TESTSUITE_AT = \ | |||
50 | include.at\ | 50 | include.at\ |
51 | invalid.at\ | 51 | invalid.at\ |
52 | knr.at\ | 52 | knr.at\ |
53 | memberof.at\ | ||
53 | multi.at\ | 54 | multi.at\ |
54 | nfarg.at\ | 55 | nfarg.at\ |
55 | nfparg.at\ | 56 | nfparg.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 @@ | |||
1 | # This file is part of GNU cflow testsuite. -*- Autotest -*- | ||
2 | # Copyright (C) 2016-2019 Sergey Poznyakoff | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_SETUP([member of]) | ||
18 | AT_KEYWORDS([memberof]) | ||
19 | |||
20 | CFLOW_CHECK( | ||
21 | [int bar(struct foo *a) { | ||
22 | return a.bar(); | ||
23 | } | ||
24 | ], | ||
25 | [bar() <int bar (struct foo *a) at prog:1> | ||
26 | ]) | ||
27 | |||
28 | # https://savannah.gnu.org/bugs/index.php?47110 | ||
29 | CFLOW_CHECK( | ||
30 | [int bar(struct foo *a) { | ||
31 | return (*a).bar(); | ||
32 | } | ||
33 | ], | ||
34 | [bar() <int bar (struct foo *a) at prog:1> | ||
35 | ]) | ||
36 | |||
37 | CFLOW_CHECK( | ||
38 | [int bar(struct foo **a) { | ||
39 | return (*a)->bar(); | ||
40 | } | ||
41 | ], | ||
42 | [bar() <int bar (struct foo **a) at prog:1> | ||
43 | ]) | ||
44 | |||
45 | CFLOW_CHECK( | ||
46 | [int bar(void *a) { | ||
47 | return (*(struct foo*)a).bar(); | ||
48 | } | ||
49 | ], | ||
50 | [bar() <int bar (void *a) at prog:1> | ||
51 | ]) | ||
52 | |||
53 | CFLOW_CHECK( | ||
54 | [int bar(void *a) { | ||
55 | return (*(struct foo*)(((struct qux*)a)->foo)).bar(); | ||
56 | } | ||
57 | ], | ||
58 | [bar() <int bar (void *a) at prog:1> | ||
59 | ]) | ||
60 | |||
61 | AT_CLEANUP | ||
62 | |||
diff --git a/tests/testsuite.at b/tests/testsuite.at index 766e018..baf997b 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at | |||
@@ -72,5 +72,6 @@ m4_include([struct03.at]) | |||
72 | m4_include([struct04.at]) | 72 | m4_include([struct04.at]) |
73 | m4_include([decl01.at]) | 73 | m4_include([decl01.at]) |
74 | m4_include([invalid.at]) | 74 | m4_include([invalid.at]) |
75 | m4_include([memberof.at]) | ||
75 | 76 | ||
76 | # End of testsuite.at | 77 | # End of testsuite.at |