21 want_raii_info =
False
26 def log(msg, indent=0):
29 sys.stderr.write(
'%s%s\n' % (
' ' * indent, msg))
33 if not isinstance(return_type, gcc.PointerType):
35 if not isinstance(return_type.dereference, gcc.RecordType):
37 if str(return_type.dereference.name) ==
'cleanup':
42 "Return True if the function DECL is a cleanup constructor; False otherwise"
43 return is_cleanup_type(decl.type.type)
and (
not decl.name
or str(decl.name) !=
'make_final_cleanup')
45 destructor_names = set([
'do_cleanups',
'discard_cleanups'])
48 return decl.name
in destructor_names
52 special_names = set([
'do_final_cleanups',
'discard_final_cleanups',
53 'save_cleanups',
'save_final_cleanups',
54 'restore_cleanups',
'restore_final_cleanups',
55 'exceptions_state_mc_init',
56 'make_my_cleanup2',
'make_final_cleanup',
'all_cleanups',
57 'save_my_cleanups',
'quit_target'])
60 return decl.name
in special_names
89 self.
aliases = dict(other.aliases)
92 if definition == argument:
95 argument = self.
aliases[argument]
97 definition = self.
aliases[definition]
98 return definition == argument
101 log(
'noting assignment %s = %s' % (lhs, rhs), 4)
113 log(
'merge checking %s' % var, 4)
115 if isinstance(var, Dummy):
116 log(
'=> merge dummy', 5)
119 if other._find_var(var.var) >= 0:
120 log (
'=> merge found', 5)
122 log(
'=>merge not found', 5)
124 if found_named
and counter <
len(self.
cleanups) - 1:
125 log (
'merging to %d' % counter, 4)
134 log(
'merging non-empty other', 4)
144 obj =
Dummy(location)
147 log(
'pushing %s' % lhs, 4)
150 gcc.permerror(location,
'reassigning to known cleanup')
151 gcc.inform(self.
cleanups[idx].location,
152 'previous assignment is here')
153 self.cleanups.append(obj)
159 if isinstance(self.
cleanups[i], Dummy):
167 def pop(self, location, back_to):
173 gcc.permerror(location,
'destructor call with unknown argument')
178 log(
'verify %s' % arg, 4)
180 and not isinstance(self.
cleanups[0], Dummy)
190 for item
in reversed(self.
cleanups):
191 gcc.inform(item.location,
'leaked cleanup')
205 if isinstance(bb.gimple, list):
206 for stmt
in bb.gimple:
214 if not isinstance(bb.gimple, list):
216 curloc = self.fun.end
217 for stmt
in bb.gimple:
220 if isinstance(stmt, gcc.GimpleCall)
and stmt.fndecl:
222 log(
'saw constructor %s in bb=%d' % (str(stmt.fndecl), bb.index), 2)
224 master_cleanup.push(curloc, stmt.lhs)
226 if str(stmt.fndecl.name) !=
'do_cleanups':
228 log(
'saw destructor %s in bb=%d, bb_from=%d, argument=%s'
229 % (str(stmt.fndecl.name), bb.index, bb_from, str(stmt.args[0])),
231 master_cleanup.pop(curloc, stmt.args[0])
235 elif isinstance(stmt, gcc.GimpleAssign):
236 if isinstance(stmt.lhs, gcc.VarDecl)
and isinstance(stmt.rhs[0], gcc.VarDecl):
237 master_cleanup.note_assignment(stmt.lhs, stmt.rhs[0])
238 elif isinstance(stmt, gcc.GimpleReturn):
240 if not master_cleanup.verify(curloc, stmt.retval):
241 gcc.permerror(curloc,
242 'constructor does not return master cleanup')
244 if not master_cleanup.isempty():
246 gcc.permerror(curloc,
'cleanup stack is not empty at return')
247 self.bad_returns.add(curloc)
248 master_cleanup.inform()
253 log(
'traverse_bbs %d from %d' % (bb.index, bb_from), 1)
279 self.seen_edges.add(edge)
285 for edge
in bb.succs:
286 self.
traverse_bbs(edge, edge.dest, bb.index, master_cleanup)
289 if not self.fun.cfg
or not self.fun.decl:
299 if str(self.fun.decl.name) ==
'gdb_xml_create_parser_and_cleanup_1':
303 gcc.inform(self.fun.start,
'function %s is a special constructor' % (self.fun.decl.name))
311 entry_bb = self.fun.cfg.entry
315 gcc.inform(self.fun.decl.location,
316 'function %s could be converted to RAII' % (self.fun.decl.name))
324 log(
"Starting " + fun.decl.name)
326 dot = gccutils.cfg_to_dot(fun.cfg, fun.decl.name)
327 gccutils.invoke_dot(dot, name=fun.decl.name)
329 what = checker.check_cleanups()
331 log(fun.decl.name +
': ' + what, 2)
335 ps.register_after(
'cfg')
def compute_master(self, bb, bb_from, master_cleanup)
def pop(self, location, back_to)
def _find_var(self, back_to)
def needs_special_treatment(decl)
def is_cleanup_type(return_type)
def guess_bb_location(self, bb)
def __init__(self, var, location)
def verify(self, location, arg)
def push(self, location, lhs)
def traverse_bbs(self, edge, bb, bb_from, entry_master)
def compare_vars(self, definition, argument)
def __init__(self, location)
def note_assignment(self, lhs, rhs)
const ULONGEST const LONGEST len