summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-02-10 12:21:03 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-02-10 12:21:03 (GMT)
commitb4038ea16c1709367f5c84939919785686481b55 (patch) (side-by-side diff)
tree118e2ebaf20bc82d04c4b7ec49dc0030aa1a1ac8
parenta80f1c42bd5f63f79aa562cde5467aaf6ca54d89 (diff)
downloadcflow-b4038ea16c1709367f5c84939919785686481b55.tar.gz
cflow-b4038ea16c1709367f5c84939919785686481b55.tar.bz2
Fix processing of typedef struct and struct declarations. Fix --xref mode.
Some constucts were processed incorrectly (see typedef.at for examples). Unit-local types were not displayed in xref mode. * src/cflow.h (symbol_temp): Rename to symbol_temp. All uses changed. * src/output.c (tree_output): In all_functions mode: print all functions without explicit caller. * src/parser.c (save_token): Process curly braces. (fake_struct): Don't restore stack upon encountering identifier or modifier. See typedef.at for testcases. (parse_variable_declaration): restore stack only if type_end is -1 (no tag encountered). See struct06 in struct.at (skip_struct): Minor change. * src/parser.h: Redefine token types as enum. * src/symbol.c (unit_local_list): New static. (static_free): Preserve unit-local symbols in unit_local_list in xref mode. (collect_symbols): Consider symbols from unit_local_list. * tests/Makefile.am: Add new testcases. * tests/testsuite.at (CFLOW_TEST): New macro. Include new testcases. * tests/struct.at: New file. * tests/typedef.at: New file. * tests/struct01.at: Remove. * tests/struct02.at: Remove. * tests/struct03.at: Remove. * tests/struct04.at: Remove. * .gitignore: Update.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitignore7
-rw-r--r--src/cflow.h4
-rw-r--r--src/output.c4
-rw-r--r--src/parser.c37
-rw-r--r--src/parser.h40
-rw-r--r--src/symbol.c21
-rw-r--r--tests/Makefile.am7
-rw-r--r--tests/struct.at105
-rw-r--r--tests/struct02.at37
-rw-r--r--tests/struct03.at40
-rw-r--r--tests/struct04.at31
-rw-r--r--tests/testsuite.at15
-rw-r--r--tests/typedef.at (renamed from tests/struct01.at)51
13 files changed, 223 insertions, 176 deletions
diff --git a/.gitignore b/.gitignore
index 9ed9226..099af3c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
--- a/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
+++ b/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
+++ b/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
+++ b/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
+])

Return to:

Send suggestions and report system problems to the System administrator.