Skip to content

Commit c4a6546

Browse files
committed
tests/examples/find-global-state: report on uses of global state, rather than just decls
1 parent 32607d4 commit c4a6546

File tree

4 files changed

+64
-10
lines changed

4 files changed

+64
-10
lines changed

docs/working-with-c.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ these warnings are emitted on stderr:
7676

7777
Finding global variables
7878
------------------------
79-
This example adds a pass that warns about global variables:
79+
This example adds a pass that warns about uses of global variables:
8080

8181
.. code-block:: bash
8282

tests/examples/find-global-state/input.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,13 @@ int test3(int k)
4747
/* We should *not* report about __FUNCTION__ here: */
4848
printf("%s:%i:%s\n", __FILE__, __LINE__, __FUNCTION__);
4949
}
50+
51+
int test4()
52+
{
53+
return foo;
54+
}
55+
56+
int test6()
57+
{
58+
return bar.f;
59+
}

tests/examples/find-global-state/script.py

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@
1818
import gcc
1919
from gccutils import get_src_for_loc
2020

21-
def on_pass_execution(p, fn):
22-
if p.name == '*free_lang_data':
21+
DEBUG=0
22+
23+
class StateFinder:
24+
def __init__(self):
25+
# Locate all declarations of variables holding "global" state:
26+
self.global_decls = set()
27+
2328
for var in gcc.get_variables():
2429
type_ = var.decl.type
2530

@@ -30,10 +35,48 @@ def on_pass_execution(p, fn):
3035
if hasattr(item_type, 'const'):
3136
if item_type.const:
3237
continue
38+
self.global_decls.add(var.decl)
39+
if DEBUG:
40+
print('self.global_decls: %r' % self.global_decls)
41+
42+
self.state_users = set()
43+
44+
def find_state_users(self, node, loc):
45+
if isinstance(node, gcc.VarDecl):
46+
if node in self.global_decls:
47+
# store the state users for later replay, so that
48+
# we can eliminate duplicates
49+
# e.g. two references to "q" in "q += p"
50+
# and replay in source-location order:
51+
self.state_users.add( (loc, node) )
52+
53+
def flush(self):
54+
# Emit warnings, sorted by source location:
55+
for loc, node in sorted(self.state_users,
56+
key=lambda pair:pair[0]):
57+
gcc.inform(loc,
58+
'use of global state "%s %s" here'
59+
% (node.type, node))
60+
61+
def on_pass_execution(p, fn):
62+
if p.name == '*free_lang_data':
63+
sf = StateFinder()
64+
65+
# Locate uses of such variables:
66+
for node in gcc.get_callgraph_nodes():
67+
fun = node.decl.function
68+
if fun:
69+
cfg = fun.cfg
70+
if cfg:
71+
for bb in cfg.basic_blocks:
72+
stmts = bb.gimple
73+
if stmts:
74+
for stmt in stmts:
75+
stmt.walk_tree(sf.find_state_users,
76+
stmt.loc)
3377

34-
gcc.inform(var.decl.location,
35-
'global state "%s %s" defined here'
36-
% (type_, var.decl))
78+
# Flush the data that was found:
79+
sf.flush()
3780

3881
gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION,
3982
on_pass_execution)
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
tests/examples/find-global-state/input.c:40:14: note: global state "int q" defined here
2-
tests/examples/find-global-state/input.c:26:3: note: global state "struct
1+
tests/examples/find-global-state/input.c:41:nn: note: use of global state "int q" here
2+
tests/examples/find-global-state/input.c:42:nn: note: use of global state "int q" here
3+
tests/examples/find-global-state/input.c:53:nn: note: use of global state "int foo" here
4+
tests/examples/find-global-state/input.c:58:nn: note: use of global state "struct
35
{
46
int f;
5-
} bar" defined here
6-
tests/examples/find-global-state/input.c:22:12: note: global state "int a_global" defined here
7+
} bar" here

0 commit comments

Comments
 (0)