diff options
-rw-r--r-- | .gitignore | 7 | ||||
-rw-r--r-- | src/cflow.h | 4 | ||||
-rw-r--r-- | src/output.c | 4 | ||||
-rw-r--r-- | src/parser.c | 37 | ||||
-rw-r--r-- | src/parser.h | 40 | ||||
-rw-r--r-- | src/symbol.c | 21 | ||||
-rw-r--r-- | tests/Makefile.am | 7 | ||||
-rw-r--r-- | tests/struct.at | 105 | ||||
-rw-r--r-- | tests/struct02.at | 37 | ||||
-rw-r--r-- | tests/struct03.at | 40 | ||||
-rw-r--r-- | tests/struct04.at | 31 | ||||
-rw-r--r-- | tests/testsuite.at | 15 | ||||
-rw-r--r-- | tests/typedef.at (renamed from tests/struct01.at) | 51 |
13 files changed, 223 insertions, 176 deletions
@@ -8,7 +8,7 @@ *~ .bootstrap .deps -.emacs.desktop +.emacs* .gdbinit ABOUT-NLS ChangeLog @@ -28,3 +28,8 @@ configure gnu m4 stamp-h1 +/cflow-*.tar.* +*.cflow +core +tmp/ +*.patch diff --git a/src/cflow.h b/src/cflow.h index 8779a68..7728ab7 100644 --- a/src/cflow.h +++ b/src/cflow.h @@ -85,8 +85,8 @@ typedef struct { enum symbol_flag { symbol_none, - symbol_temp, /* Temporary symbol. Must be deleted after - processing of the current module */ + symbol_local, /* Unit-local symbol. Must be deleted after + processing current compilation unit */ symbol_parm, /* Parameter */ symbol_alias /* Alias to another symbol */ }; diff --git a/src/output.c b/src/output.c index f4d1359..bf5af1f 100644 --- a/src/output.c +++ b/src/output.c @@ -401,7 +401,9 @@ tree_output() if (all_functions) { for (i = 0; i < num; i++) { - if (main_sym != symbols[i] && symbols[i]->source) { + if (main_sym != symbols[i] + && symbols[i]->source + && symbols[i]->caller == NULL) { direct_tree(0, 0, symbols[i]); separator(); } diff --git a/src/parser.c b/src/parser.c index 391fe33..39d4b7c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -379,6 +379,20 @@ save_token(TOKSTK *tokptr) obstack_1grow(&text_stk, tokptr->type); need_space = 0; break; + case LBRACE: + case LBRACE0: + if (need_space) + obstack_1grow(&text_stk, ' '); + obstack_1grow(&text_stk, '{'); + need_space = 1; + break; + case RBRACE: + case RBRACE0: + if (need_space) + obstack_1grow(&text_stk, ' '); + obstack_1grow(&text_stk, '}'); + need_space = 1; + break; case OP: obstack_1grow(&text_stk, ' '); obstack_grow(&text_stk, tokptr->token, strlen(tokptr->token)); @@ -685,9 +699,6 @@ parse_function_declaration(Ident *ident, int parm) int fake_struct(Ident *ident) { - Stackpos sp; - - mark(sp); ident->type_end = -1; if (tok.type == STRUCT) { if (nexttoken() == IDENTIFIER) { @@ -695,15 +706,8 @@ fake_struct(Ident *ident) } putback(); skip_struct(); - if (tok.type == IDENTIFIER || tok.type == MODIFIER) { - int pos = curs-1; - restore(sp); - if (ident->type_end == -1) { - /* there was no tag. Insert { ... } */ - tokdel(curs, pos - 1); - tokins(curs, IDENTIFIER, tok.line, "{ ... }"); - debugtoken(&tok, "modified stack"); - } + if (tok.type == IDENTIFIER || tok.type == MODIFIER || tok.type == QUALIFIER) { + putback(); } else if (tok.type == '(') return 0; else if (tok.type != ';') @@ -729,9 +733,9 @@ parse_variable_declaration(Ident *ident, int parm) while (tok.type == MODIFIER || tok.type == QUALIFIER) nexttoken(); if (tok.type == IDENTIFIER) { - int pos = curs-1; - restore(sp); if (ident->type_end == -1) { + int pos = curs-1; + restore(sp); /* there was no tag. Insert { ... } */ tokdel(curs, pos - 1); tokins(curs, IDENTIFIER, tok.line, "{ ... }"); @@ -772,7 +776,6 @@ parse_variable_declaration(Ident *ident, int parm) else expression(); goto select; - break; case LBRACE0: case LBRACE: func_body(); @@ -837,8 +840,10 @@ skip_struct() } while (tok.type == PARM_WRAPPER) { - if (skip_balanced('(', ')', 0) == -1) + if (skip_balanced('(', ')', 0) == -1) { file_error(_("unexpected end of file in struct"), NULL); + return; + } } } diff --git a/src/parser.h b/src/parser.h index 24434b1..6415d5b 100644 --- a/src/parser.h +++ b/src/parser.h @@ -15,25 +15,27 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* tokens */ -#define WORD 257 -#define LBRACE0 258 -#define RBRACE0 259 -#define IDENTIFIER 260 -#define EXTERN 261 -#define STATIC 262 -#define TYPEDEF 263 -#define STRUCT 264 -#define MODIFIER 265 -#define OP 266 -#define UNION 267 -#define ENUM 268 -#define LBRACE '{' -#define RBRACE '}' -#define MEMBER_OF 269 -#define TYPE 270 -#define STRING 271 -#define PARM_WRAPPER 272 -#define QUALIFIER 273 +enum { + LBRACE = '{', + RBRACE = '}', + WORD = 257, + LBRACE0, + RBRACE0, + IDENTIFIER, + EXTERN, + STATIC, + TYPEDEF, + STRUCT, + MODIFIER, + OP, + UNION, + ENUM, + MEMBER_OF, + TYPE, + STRING, + PARM_WRAPPER, + QUALIFIER +}; typedef struct { char *str; diff --git a/src/symbol.c b/src/symbol.c index e4cf657..a4ca34f 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -23,6 +23,7 @@ static Hash_table *symbol_table; static struct linked_list *static_symbol_list; static struct linked_list *auto_symbol_list; static struct linked_list *static_func_list; +static struct linked_list *unit_local_list; static void append_symbol(struct linked_list **plist, Symbol *sp) @@ -99,7 +100,7 @@ install(char *name, int flags) if (((flags & INSTALL_CHECK_LOCAL) && canonical_filename && strcmp(filename, canonical_filename)) || (flags & INSTALL_UNIT_LOCAL)) { - sym->flag = symbol_temp; + sym->flag = symbol_local; append_symbol(&static_symbol_list, sym); } else sym->flag = symbol_none; @@ -222,9 +223,17 @@ static_free(void *data) if (!t) return; - if (sym->flag == symbol_temp) - delete_symbol(sym); - else { + if (sym->flag == symbol_local) { + /* In xref mode, eligible unit-local symbols are retained in + unit_local_list for further processing. + Otherwise, they are deleted. */ + if (print_option == PRINT_XREF && include_symbol(sym)) { + unlink_symbol(sym); + linked_list_append(&unit_local_list, sym); + } else { + delete_symbol(sym); + } + } else { unlink_symbol(sym); if (symbol_is_function(sym)) linked_list_append(&static_func_list, sym); @@ -317,12 +326,14 @@ collect_symbols(Symbol ***return_sym, int (*sel)(Symbol *p), size_t size; size = hash_get_n_entries(symbol_table) - + linked_list_size(static_func_list); + + linked_list_size(static_func_list) + + linked_list_size(unit_local_list); cdata.sym = xcalloc(size + reserved_slots, sizeof(*cdata.sym)); cdata.index = 0; cdata.sel = sel; hash_do_for_each(symbol_table, collect_processor, &cdata); linked_list_iterate(&static_func_list, collect_list_entry, &cdata); + linked_list_iterate(&unit_local_list, collect_list_entry, &cdata); cdata.sym = xrealloc(cdata.sym, (cdata.index + reserved_slots) * sizeof(*cdata.sym)); diff --git a/tests/Makefile.am b/tests/Makefile.am index d78b7c5..2dfe751 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -60,12 +60,9 @@ TESTSUITE_AT = \ reverse.at\ ssblock.at\ static.at\ - struct00.at\ - struct01.at\ - struct02.at\ - struct03.at\ - struct04.at\ + struct.at\ testsuite.at\ + typedef.at\ version.at TESTSUITE = $(srcdir)/testsuite diff --git a/tests/struct.at b/tests/struct.at new file mode 100644 index 0000000..aed1a9c --- /dev/null +++ b/tests/struct.at @@ -0,0 +1,105 @@ +AT_BANNER([struct]) + +CFLOW_TEST([struct definition followed by attribute], +[struct struct-attr attribute], +[struct bar { + struct foo *dummy; +} __attribute__((aligned(8))); + +int +main(int argc, char **argv) +{ +} +], +[main() <int main (int argc, char **argv) at prog:6> +]) + +CFLOW_OPT([--symbol __attribute__:wrapper],[ +CFLOW_TEST([struct definition followed by wrapper], +[struct struct01 struct-wrapper wrapper], +[struct bar { + struct foo *dummy; +} __attribute__((aligned(8))); + +int +main(int argc, char **argv) +{ +} +], +[main() <int main (int argc, char **argv) at prog:6> +]) +]) + +CFLOW_TEST([ANSI C function returning a struct], +[struct struct02 ret-struct], +[struct s * +foo(int arg) +{ + bar(); +} +int +main(int argc, char **argv) +{ + foo(); +} +], +[main() <int main (int argc, char **argv) at prog:7>: + foo() <struct s *foo (int arg) at prog:2>: + bar() +]) + +CFLOW_TEST([K&R C function returning a struct], +[struct struct03 ret-struct], +[struct s * +foo(arg) + int arg; +{ + bar(); +} +int +main(argc, argv) + int argc; + char **argv; +{ + foo(); +} +], +[main() <int main (argc, argv) at prog:8>: + foo() <struct s *foo (arg) at prog:2>: + bar() +]) + +CFLOW_OPT([-m foo],[ +CFLOW_TEST([struct as argument], +[struct struct04 arg-struct], +[int +foo(struct bar *x) +{ +} +], +[foo() <int foo (struct bar *x) at prog:2> +]) +]) + +CFLOW_OPT([-x -ix],[ +CFLOW_TEST([struct variable], +[struct struct05 var-struct], +[struct { int x; int y; } point; +], +[point * prog:1 struct { ... } point +]) +]) + +CFLOW_OPT([-x -ix],[ +CFLOW_TEST([array of structs], +[struct struct06 arr-struct], +[[struct X { + char *name; +} X[] = { + { "foo" }, +}; +]], +[[X * prog:3 struct X { char *name } X[] +]]) +]) + diff --git a/tests/struct02.at b/tests/struct02.at deleted file mode 100644 index ab5ce20..0000000 --- a/tests/struct02.at +++ /dev/null @@ -1,37 +0,0 @@ -# This file is part of GNU cflow testsuite. -*- Autotest -*- -# Copyright (C) 2014-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([ANSI C function returning a struct]) -AT_KEYWORDS([struct struct02 ret-struct]) - -CFLOW_CHECK( -struct s * -foo(int arg) -{ - bar(); -} -int -main(int argc, char **argv) -{ - foo(); -} -], -[main() <int main (int argc, char **argv) at prog:7>: - foo() <struct s *foo (int arg) at prog:2>: - bar() -]) - -AT_CLEANUP diff --git a/tests/struct03.at b/tests/struct03.at deleted file mode 100644 index a6f11f8..0000000 --- a/tests/struct03.at +++ /dev/null @@ -1,40 +0,0 @@ -# This file is part of GNU cflow testsuite. -*- Autotest -*- -# Copyright (C) 2014-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([K&R C function returning a struct]) -AT_KEYWORDS([struct struct03 ret-struct]) - -CFLOW_CHECK( -struct s * -foo(arg) - int arg; -{ - bar(); -} -int -main(argc, argv) - int argc; - char **argv; -{ - foo(); -} -], -[main() <int main (argc, argv) at prog:8>: - foo() <struct s *foo (arg) at prog:2>: - bar() -]) - -AT_CLEANUP diff --git a/tests/struct04.at b/tests/struct04.at deleted file mode 100644 index afaab9e..0000000 --- a/tests/struct04.at +++ /dev/null @@ -1,31 +0,0 @@ -# This file is part of GNU cflow testsuite. -*- Autotest -*- -# Copyright (C) 2014-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([struct as argument]) -AT_KEYWORDS([struct struct04 arg-struct]) - -CFLOW_OPT([-m foo],[ -CFLOW_CHECK([ -int -foo(struct bar *x) -{ -} -], -[foo() <int foo (struct bar *x) at prog:3> -]) -]) - -AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index baf997b..8d3ba47 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -40,6 +40,13 @@ m4_pushdef([TEST_CFLOW_OPTIONS],[$1]) $2 m4_popdef([TEST_CFLOW_OPTIONS])]) +m4_pushdef([CFLOW_TEST], +[AT_SETUP([$1]) +AT_KEYWORDS([$2]) +CFLOW_CHECK(m4_shift(m4_shift($@))) +AT_CLEANUP +]) + AT_INIT CFLOW_TEST_INIT @@ -65,13 +72,11 @@ m4_include([nfarg.at]) m4_include([hiding.at]) m4_include([multi.at]) m4_include([bartest.at]) -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]) +m4_include([struct.at]) +m4_include([typedef.at]) + # End of testsuite.at diff --git a/tests/struct01.at b/tests/typedef.at index fd42b23..4f4b862 100644 --- a/tests/struct01.at +++ b/tests/typedef.at @@ -1,5 +1,5 @@ # This file is part of GNU cflow testsuite. -*- Autotest -*- -# Copyright (C) 2011-2019 Sergey Poznyakoff +# Copyright (C) 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 @@ -14,23 +14,46 @@ # 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([struct definition followed by wrapper]) -AT_KEYWORDS([struct struct01 struct-wrapper wrapper]) +AT_BANNER([typedefs]) -CFLOW_OPT([--symbol __attribute__:wrapper],[ -CFLOW_CHECK( -[struct bar { - struct foo *dummy; -} __attribute__((aligned(8))); +CFLOW_OPT([-x -it],[ +CFLOW_TEST([structs with same members],[typedef typedef00], +[typedef struct x { + char **foo; +} X; +typedef struct y { + char **foo; +} Y; +], +[X t prog:3 +Y t prog:6 +]) + +CFLOW_TEST([structs with tags matching typedef],[typedef typedef01], +[typedef struct X { + char **foo; +} X; +typedef struct Y { + char **foo; +} Y; +], +[X t prog:3 +Y t prog:6 +]) -int -main(int argc, char **argv) -{ -} +CFLOW_TEST([typedef to pointer],[typedef typedef02], +[typedef struct X { + char **foo; +} **X; ], -[main() <int main (int argc, char **argv) at prog:6> +[X t prog:3 ]) + +CFLOW_TEST([modifiers],[typedef typedef03], +[typedef struct X const *Y; +], +[Y t prog:1 ]) -AT_CLEANUP +]) |