Remove the exception and cleanup checkers
authorTom Tromey <tom@tromey.com>
Mon, 24 Dec 2018 21:56:03 +0000 (14:56 -0700)
committerTom Tromey <tom@tromey.com>
Sat, 5 Jan 2019 15:49:50 +0000 (08:49 -0700)
Now that gdb is transitioning away from cleanups, there is no reason
to keep the cleanup and exception checker scripts around.  This patch
removes them.

gdb/ChangeLog
2019-01-05  Tom Tromey  <tom@tromey.com>

* contrib/cleanup_check.py: Remove.
* contrib/gcc-with-excheck: Remove.
* contrib/exsummary.py: Remove.
* contrib/excheck.py: Remove.

gdb/ChangeLog
gdb/contrib/cleanup_check.py [deleted file]
gdb/contrib/excheck.py [deleted file]
gdb/contrib/exsummary.py [deleted file]
gdb/contrib/gcc-with-excheck [deleted file]

index 09485a028c37721388f61bc3a2c3207eebddefcd..4b60367ffb031095f254bd14484ef1683f3bca94 100644 (file)
@@ -1,3 +1,10 @@
+2019-01-05  Tom Tromey  <tom@tromey.com>
+
+       * contrib/cleanup_check.py: Remove.
+       * contrib/gcc-with-excheck: Remove.
+       * contrib/exsummary.py: Remove.
+       * contrib/excheck.py: Remove.
+
 2019-01-05  Joel Brobecker  <brobecker@adacore.com>
 
        * thread.c (delete_thread_1): Add gdb_assert that THR is not
diff --git a/gdb/contrib/cleanup_check.py b/gdb/contrib/cleanup_check.py
deleted file mode 100644 (file)
index be6babb..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-#   Copyright 2013-2019 Free Software Foundation, Inc.
-#
-#   This 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 of the License, 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/>.
-
-import gcc
-import gccutils
-import sys
-
-want_raii_info = False
-
-logging = False
-show_cfg = False
-
-def log(msg, indent=0):
-    global logging
-    if logging:
-        sys.stderr.write('%s%s\n' % ('  ' * indent, msg))
-        sys.stderr.flush()
-
-def is_cleanup_type(return_type):
-    if not isinstance(return_type, gcc.PointerType):
-        return False
-    if not isinstance(return_type.dereference, gcc.RecordType):
-        return False
-    if str(return_type.dereference.name) == 'cleanup':
-        return True
-    return False
-
-def is_constructor(decl):
-    "Return True if the function DECL is a cleanup constructor; False otherwise"
-    return is_cleanup_type(decl.type.type) and (not decl.name or str(decl.name) != 'make_final_cleanup')
-
-destructor_names = set(['do_cleanups', 'discard_cleanups'])
-
-def is_destructor(decl):
-    return decl.name in destructor_names
-
-# This list is just much too long... we should probably have an
-# attribute instead.
-special_names = set(['do_final_cleanups', 'discard_final_cleanups',
-                     'save_cleanups', 'save_final_cleanups',
-                     'restore_cleanups', 'restore_final_cleanups',
-                     'exceptions_state_mc_init',
-                     'make_my_cleanup2', 'make_final_cleanup', 'all_cleanups',
-                     'save_my_cleanups', 'quit_target'])
-
-def needs_special_treatment(decl):
-    return decl.name in special_names
-
-# Sometimes we need a new placeholder object that isn't the same as
-# anything else.
-class Dummy(object):
-    def __init__(self, location):
-        self.location = location
-
-# A wrapper for a cleanup which has been assigned to a variable.
-# This holds the variable and the location.
-class Cleanup(object):
-    def __init__(self, var, location):
-        self.var = var
-        self.location = location
-
-# A class representing a master cleanup.  This holds a stack of
-# cleanup objects and supports a merging operation.
-class MasterCleanup(object):
-    # Create a new MasterCleanup object.  OTHER, if given, is a
-    # MasterCleanup object to copy.
-    def __init__(self, other = None):
-        # 'cleanups' is a list of cleanups.  Each element is either a
-        # Dummy, for an anonymous cleanup, or a Cleanup, for a cleanup
-        # which was assigned to a variable.
-        if other is None:
-            self.cleanups = []
-            self.aliases = {}
-        else:
-            self.cleanups = other.cleanups[:]
-            self.aliases = dict(other.aliases)
-
-    def compare_vars(self, definition, argument):
-        if definition == argument:
-            return True
-        if argument in self.aliases:
-            argument = self.aliases[argument]
-        if definition in self.aliases:
-            definition = self.aliases[definition]
-        return definition == argument
-
-    def note_assignment(self, lhs, rhs):
-        log('noting assignment %s = %s' % (lhs, rhs), 4)
-        self.aliases[lhs] = rhs
-
-    # Merge with another MasterCleanup.
-    # Returns True if this resulted in a change to our state.
-    def merge(self, other):
-        # We do explicit iteration like this so we can easily
-        # update the list after the loop.
-        counter = -1
-        found_named = False
-        for counter in range(len(self.cleanups) - 1, -1, -1):
-            var = self.cleanups[counter]
-            log('merge checking %s' % var, 4)
-            # Only interested in named cleanups.
-            if isinstance(var, Dummy):
-                log('=> merge dummy', 5)
-                continue
-            # Now see if VAR is found in OTHER.
-            if other._find_var(var.var) >= 0:
-                log ('=> merge found', 5)
-                break
-            log('=>merge not found', 5)
-            found_named = True
-        if found_named and counter < len(self.cleanups) - 1:
-            log ('merging to %d' % counter, 4)
-            if counter < 0:
-                self.cleanups = []
-            else:
-                self.cleanups = self.cleanups[0:counter]
-            return True
-        # If SELF is empty but OTHER has some cleanups, then consider
-        # that a change as well.
-        if len(self.cleanups) == 0 and len(other.cleanups) > 0:
-            log('merging non-empty other', 4)
-            self.cleanups = other.cleanups[:]
-            return True
-        return False
-
-    # Push a new constructor onto our stack.  LHS is the
-    # left-hand-side of the GimpleCall statement.  It may be None,
-    # meaning that this constructor's value wasn't used.
-    def push(self, location, lhs):
-        if lhs is None:
-            obj = Dummy(location)
-        else:
-            obj = Cleanup(lhs, location)
-        log('pushing %s' % lhs, 4)
-        idx = self._find_var(lhs)
-        if idx >= 0:
-            gcc.permerror(location, 'reassigning to known cleanup')
-            gcc.inform(self.cleanups[idx].location,
-                       'previous assignment is here')
-        self.cleanups.append(obj)
-
-    # A helper for merge and pop that finds BACK_TO in self.cleanups,
-    # and returns the index, or -1 if not found.
-    def _find_var(self, back_to):
-        for i in range(len(self.cleanups) - 1, -1, -1):
-            if isinstance(self.cleanups[i], Dummy):
-                continue
-            if self.compare_vars(self.cleanups[i].var, back_to):
-                return i
-        return -1
-
-    # Pop constructors until we find one matching BACK_TO.
-    # This is invoked when we see a do_cleanups call.
-    def pop(self, location, back_to):
-        log('pop:', 4)
-        i = self._find_var(back_to)
-        if i >= 0:
-            self.cleanups = self.cleanups[0:i]
-        else:
-            gcc.permerror(location, 'destructor call with unknown argument')
-
-    # Check whether ARG is the current master cleanup.  Return True if
-    # all is well.
-    def verify(self, location, arg):
-        log('verify %s' % arg, 4)
-        return (len(self.cleanups) > 0
-                and not isinstance(self.cleanups[0], Dummy)
-                and self.compare_vars(self.cleanups[0].var, arg))
-
-    # Check whether SELF is empty.
-    def isempty(self):
-        log('isempty: len = %d' % len(self.cleanups), 4)
-        return len(self.cleanups) == 0
-
-    # Emit informational warnings about the cleanup stack.
-    def inform(self):
-        for item in reversed(self.cleanups):
-            gcc.inform(item.location, 'leaked cleanup')
-
-class CleanupChecker:
-    def __init__(self, fun):
-        self.fun = fun
-        self.seen_edges = set()
-        self.bad_returns = set()
-
-        # This maps BB indices to a list of master cleanups for the
-        # BB.
-        self.master_cleanups = {}
-
-    # Pick a reasonable location for the basic block BB.
-    def guess_bb_location(self, bb):
-        if isinstance(bb.gimple, list):
-            for stmt in bb.gimple:
-                if stmt.loc:
-                    return stmt.loc
-        return self.fun.end
-
-    # Compute the master cleanup list for BB.
-    # Modifies MASTER_CLEANUP in place.
-    def compute_master(self, bb, bb_from, master_cleanup):
-        if not isinstance(bb.gimple, list):
-            return
-        curloc = self.fun.end
-        for stmt in bb.gimple:
-            if stmt.loc:
-                curloc = stmt.loc
-            if isinstance(stmt, gcc.GimpleCall) and stmt.fndecl:
-                if is_constructor(stmt.fndecl):
-                    log('saw constructor %s in bb=%d' % (str(stmt.fndecl), bb.index), 2)
-                    self.cleanup_aware = True
-                    master_cleanup.push(curloc, stmt.lhs)
-                elif is_destructor(stmt.fndecl):
-                    if str(stmt.fndecl.name) != 'do_cleanups':
-                        self.only_do_cleanups_seen = False
-                    log('saw destructor %s in bb=%d, bb_from=%d, argument=%s'
-                        % (str(stmt.fndecl.name), bb.index, bb_from, str(stmt.args[0])),
-                        2)
-                    master_cleanup.pop(curloc, stmt.args[0])
-                elif needs_special_treatment(stmt.fndecl):
-                    pass
-                    # gcc.permerror(curloc, 'function needs special treatment')
-            elif isinstance(stmt, gcc.GimpleAssign):
-                if isinstance(stmt.lhs, gcc.VarDecl) and isinstance(stmt.rhs[0], gcc.VarDecl):
-                    master_cleanup.note_assignment(stmt.lhs, stmt.rhs[0])
-            elif isinstance(stmt, gcc.GimpleReturn):
-                if self.is_constructor:
-                    if not master_cleanup.verify(curloc, stmt.retval):
-                        gcc.permerror(curloc,
-                                      'constructor does not return master cleanup')
-                elif not self.is_special_constructor:
-                    if not master_cleanup.isempty():
-                        if curloc not in self.bad_returns:
-                            gcc.permerror(curloc, 'cleanup stack is not empty at return')
-                            self.bad_returns.add(curloc)
-                            master_cleanup.inform()
-
-    # Traverse a basic block, updating the master cleanup information
-    # and propagating to other blocks.
-    def traverse_bbs(self, edge, bb, bb_from, entry_master):
-        log('traverse_bbs %d from %d' % (bb.index, bb_from), 1)
-
-        # Propagate the entry MasterCleanup though this block.
-        master_cleanup = MasterCleanup(entry_master)
-        self.compute_master(bb, bb_from, master_cleanup)
-
-        modified = False
-        if bb.index in self.master_cleanups:
-            # Merge the newly-computed MasterCleanup into the one we
-            # have already computed.  If this resulted in a
-            # significant change, then we need to re-propagate.
-            modified = self.master_cleanups[bb.index].merge(master_cleanup)
-        else:
-            self.master_cleanups[bb.index] = master_cleanup
-            modified = True
-
-        # EDGE is None for the entry BB.
-        if edge is not None:
-            # If merging cleanups caused a change, check to see if we
-            # have a bad loop.
-            if edge in self.seen_edges:
-                # This error doesn't really help.
-                # if modified:
-                #     gcc.permerror(self.guess_bb_location(bb),
-                #                   'invalid cleanup use in loop')
-                return
-            self.seen_edges.add(edge)
-
-        if not modified:
-            return
-
-        # Now propagate to successor nodes.
-        for edge in bb.succs:
-            self.traverse_bbs(edge, edge.dest, bb.index, master_cleanup)
-
-    def check_cleanups(self):
-        if not self.fun.cfg or not self.fun.decl:
-            return 'ignored'
-        if is_destructor(self.fun.decl):
-            return 'destructor'
-        if needs_special_treatment(self.fun.decl):
-            return 'special'
-
-        self.is_constructor = is_constructor(self.fun.decl)
-        self.is_special_constructor = not self.is_constructor and str(self.fun.decl.name).find('with_cleanup') > -1
-        # Yuck.
-        if str(self.fun.decl.name) == 'gdb_xml_create_parser_and_cleanup_1':
-            self.is_special_constructor = True
-
-        if self.is_special_constructor:
-            gcc.inform(self.fun.start, 'function %s is a special constructor' % (self.fun.decl.name))
-
-        # If we only see do_cleanups calls, and this function is not
-        # itself a constructor, then we can convert it easily to RAII.
-        self.only_do_cleanups_seen = not self.is_constructor
-        # If we ever call a constructor, then we are "cleanup-aware".
-        self.cleanup_aware = False
-
-        entry_bb = self.fun.cfg.entry
-        master_cleanup = MasterCleanup()
-        self.traverse_bbs(None, entry_bb, -1, master_cleanup)
-        if want_raii_info and self.only_do_cleanups_seen and self.cleanup_aware:
-            gcc.inform(self.fun.decl.location,
-                       'function %s could be converted to RAII' % (self.fun.decl.name))
-        if self.is_constructor:
-            return 'constructor'
-        return 'OK'
-
-class CheckerPass(gcc.GimplePass):
-    def execute(self, fun):
-        if fun.decl:
-            log("Starting " + fun.decl.name)
-            if show_cfg:
-                dot = gccutils.cfg_to_dot(fun.cfg, fun.decl.name)
-                gccutils.invoke_dot(dot, name=fun.decl.name)
-        checker = CleanupChecker(fun)
-        what = checker.check_cleanups()
-        if fun.decl:
-            log(fun.decl.name + ': ' + what, 2)
-
-ps = CheckerPass(name = 'check-cleanups')
-# We need the cfg, but we want a relatively high-level Gimple.
-ps.register_after('cfg')
diff --git a/gdb/contrib/excheck.py b/gdb/contrib/excheck.py
deleted file mode 100644 (file)
index 4d53f05..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-#   Copyright 2011-2019 Free Software Foundation, Inc.
-#
-#   This 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 of the License, 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/>.
-
-# This is a GCC plugin that computes some exception-handling data for
-# gdb.  This data can then be summarized and checked by the
-# exsummary.py script.
-
-# To use:
-# * First, install the GCC Python plugin.  See
-#   https://fedorahosted.org/gcc-python-plugin/
-# * export PYTHON_PLUGIN=/full/path/to/plugin/directory
-#   This should be the directory holding "python.so".
-# * cd build/gdb; make mostlyclean
-# * make CC=.../gcc-with-excheck
-#   This will write a number of .py files in the build directory.
-# * python .../exsummary.py
-#   This will show the violations.
-
-import gcc
-import gccutils
-import sys
-
-# Where our output goes.
-output_file = None
-
-# Cleanup functions require special treatment, because they take a
-# function argument, but in theory the function must be nothrow.
-cleanup_functions = {
-    'make_cleanup': 1,
-    'make_cleanup_dtor': 1,
-    'make_final_cleanup': 1,
-    'make_my_cleanup2': 1,
-    'make_my_cleanup': 1
-}
-
-# Functions which may throw but which we want to ignore.
-ignore_functions = {
-    # This one is super special.
-    'exceptions_state_mc': 1,
-    # gdb generally pretends that internal_error cannot throw, even
-    # though it can.
-    'internal_error': 1,
-    # do_cleanups and friends are supposedly nothrow but we don't want
-    # to run afoul of the indirect function call logic.
-    'do_cleanups': 1,
-    'do_final_cleanups': 1
-}
-
-# Functions which take a function argument, but which are not
-# interesting, usually because the argument is not called in the
-# current context.
-non_passthrough_functions = {
-    'signal': 1,
-    'add_internal_function': 1
-}
-
-# Return True if the type is from Python.
-def type_is_pythonic(t):
-    if isinstance(t, gcc.ArrayType):
-        t = t.type
-    if not isinstance(t, gcc.RecordType):
-        return False
-    # Hack.
-    return str(t).find('struct Py') == 0
-
-# Examine all the fields of a struct.  We don't currently need any
-# sort of recursion, so this is simple for now.
-def examine_struct_fields(initializer):
-    global output_file
-    for idx2, value2 in initializer.elements:
-        if isinstance(idx2, gcc.Declaration):
-            if isinstance(value2, gcc.AddrExpr):
-                value2 = value2.operand
-                if isinstance(value2, gcc.FunctionDecl):
-                    output_file.write("declare_nothrow(%s)\n"
-                                      % repr(str(value2.name)))
-
-# Examine all global variables looking for pointers to functions in
-# structures whose types were defined by Python.
-def examine_globals():
-    global output_file
-    vars = gcc.get_variables()
-    for var in vars:
-        if not isinstance(var.decl, gcc.VarDecl):
-            continue
-        output_file.write("################\n")
-        output_file.write("# Analysis for %s\n" % var.decl.name)
-        if not var.decl.initial:
-            continue
-        if not type_is_pythonic(var.decl.type):
-            continue
-
-        if isinstance(var.decl.type, gcc.ArrayType):
-            for idx, value in var.decl.initial.elements:
-                examine_struct_fields(value)
-        else:
-            gccutils.check_isinstance(var.decl.type, gcc.RecordType)
-            examine_struct_fields(var.decl.initial)
-
-# Called at the end of compilation to write out some data derived from
-# globals and to close the output.
-def close_output(*args):
-    global output_file
-    examine_globals()
-    output_file.close()
-
-# The pass which derives some exception-checking information.  We take
-# a two-step approach: first we get a call graph from the compiler.
-# This is emitted by the plugin as Python code.  Then, we run a second
-# program that reads all the generated Python and uses it to get a
-# global view of exception routes in gdb.
-class GdbExceptionChecker(gcc.GimplePass):
-    def __init__(self, output_file):
-        gcc.GimplePass.__init__(self, 'gdb_exception_checker')
-        self.output_file = output_file
-
-    def log(self, obj):
-        self.output_file.write("# %s\n" % str(obj))
-
-    # Return true if FN is a call to a method on a Python object.
-    # We know these cannot throw in the gdb sense.
-    def fn_is_python_ignorable(self, fn):
-        if not isinstance(fn, gcc.SsaName):
-            return False
-        stmt = fn.def_stmt
-        if not isinstance(stmt, gcc.GimpleAssign):
-            return False
-        if stmt.exprcode is not gcc.ComponentRef:
-            return False
-        rhs = stmt.rhs[0]
-        if not isinstance(rhs, gcc.ComponentRef):
-            return False
-        if not isinstance(rhs.field, gcc.FieldDecl):
-            return False
-        return rhs.field.name == 'tp_dealloc' or rhs.field.name == 'tp_free'
-
-    # Decode a function call and write something to the output.
-    # THIS_FUN is the enclosing function that we are processing.
-    # FNDECL is the call to process; it might not actually be a DECL
-    # node.
-    # LOC is the location of the call.
-    def handle_one_fndecl(self, this_fun, fndecl, loc):
-        callee_name = ''
-        if isinstance(fndecl, gcc.AddrExpr):
-            fndecl = fndecl.operand
-        if isinstance(fndecl, gcc.FunctionDecl):
-            # Ordinary call to a named function.
-            callee_name = str(fndecl.name)
-            self.output_file.write("function_call(%s, %s, %s)\n"
-                                   % (repr(callee_name),
-                                      repr(this_fun.decl.name),
-                                      repr(str(loc))))
-        elif self.fn_is_python_ignorable(fndecl):
-            # Call to tp_dealloc.
-            pass
-        elif (isinstance(fndecl, gcc.SsaName)
-              and isinstance(fndecl.var, gcc.ParmDecl)):
-            # We can ignore an indirect call via a parameter to the
-            # current function, because this is handled via the rule
-            # for passthrough functions.
-            pass
-        else:
-            # Any other indirect call.
-            self.output_file.write("has_indirect_call(%s, %s)\n"
-                                   % (repr(this_fun.decl.name),
-                                      repr(str(loc))))
-        return callee_name
-
-    # This does most of the work for examine_one_bb.
-    # THIS_FUN is the enclosing function.
-    # BB is the basic block to process.
-    # Returns True if this block is the header of a TRY_CATCH, False
-    # otherwise.
-    def examine_one_bb_inner(self, this_fun, bb):
-        if not bb.gimple:
-            return False
-        try_catch = False
-        for stmt in bb.gimple:
-            loc = stmt.loc
-            if not loc:
-                loc = this_fun.decl.location
-            if not isinstance(stmt, gcc.GimpleCall):
-                continue
-            callee_name = self.handle_one_fndecl(this_fun, stmt.fn, loc)
-
-            if callee_name == 'exceptions_state_mc_action_iter':
-                try_catch = True
-
-            global non_passthrough_functions
-            if callee_name in non_passthrough_functions:
-                continue
-
-            # We have to specially handle calls where an argument to
-            # the call is itself a function, e.g., qsort.  In general
-            # we model these as "passthrough" -- we assume that in
-            # addition to the call the qsort there is also a call to
-            # the argument function.
-            for arg in stmt.args:
-                # We are only interested in arguments which are functions.
-                t = arg.type
-                if isinstance(t, gcc.PointerType):
-                    t = t.dereference
-                if not isinstance(t, gcc.FunctionType):
-                    continue
-
-                if isinstance(arg, gcc.AddrExpr):
-                    arg = arg.operand
-
-                global cleanup_functions
-                if callee_name in cleanup_functions:
-                    if not isinstance(arg, gcc.FunctionDecl):
-                        gcc.inform(loc, 'cleanup argument not a DECL: %s' % repr(arg))
-                    else:
-                        # Cleanups must be nothrow.
-                        self.output_file.write("declare_cleanup(%s)\n"
-                                               % repr(str(arg.name)))
-                else:
-                    # Assume we have a passthrough function, like
-                    # qsort or an iterator.  We model this by
-                    # pretending there is an ordinary call at this
-                    # point.
-                    self.handle_one_fndecl(this_fun, arg, loc)
-        return try_catch
-
-    # Examine all the calls in a basic block and generate output for
-    # them.
-    # THIS_FUN is the enclosing function.
-    # BB is the basic block to examine.
-    # BB_WORKLIST is a list of basic blocks to work on; we add the
-    # appropriate successor blocks to this.
-    # SEEN_BBS is a map whose keys are basic blocks we have already
-    # processed.  We use this to ensure that we only visit a given
-    # block once.
-    def examine_one_bb(self, this_fun, bb, bb_worklist, seen_bbs):
-        try_catch = self.examine_one_bb_inner(this_fun, bb)
-        for edge in bb.succs:
-            if edge.dest in seen_bbs:
-                continue
-            seen_bbs[edge.dest] = 1
-            if try_catch:
-                # This is bogus, but we magically know the right
-                # answer.
-                if edge.false_value:
-                    bb_worklist.append(edge.dest)
-            else:
-                bb_worklist.append(edge.dest)
-
-    # Iterate over all basic blocks in THIS_FUN.
-    def iterate_bbs(self, this_fun):
-        # Iteration must be in control-flow order, because if we see a
-        # TRY_CATCH construct we need to drop all the contained blocks.
-        bb_worklist = [this_fun.cfg.entry]
-        seen_bbs = {}
-        seen_bbs[this_fun.cfg.entry] = 1
-        for bb in bb_worklist:
-            self.examine_one_bb(this_fun, bb, bb_worklist, seen_bbs)
-
-    def execute(self, fun):
-        if fun and fun.cfg and fun.decl:
-            self.output_file.write("################\n")
-            self.output_file.write("# Analysis for %s\n" % fun.decl.name)
-            self.output_file.write("define_function(%s, %s)\n"
-                                   % (repr(fun.decl.name),
-                                      repr(str(fun.decl.location))))
-
-            global ignore_functions
-            if fun.decl.name not in ignore_functions:
-                self.iterate_bbs(fun)
-
-def main(**kwargs):
-    global output_file
-    output_file = open(gcc.get_dump_base_name() + '.gdb_exc.py', 'w')
-    # We used to use attributes here, but there didn't seem to be a
-    # big benefit over hard-coding.
-    output_file.write('declare_throw("throw_exception")\n')
-    output_file.write('declare_throw("throw_verror")\n')
-    output_file.write('declare_throw("throw_vfatal")\n')
-    output_file.write('declare_throw("throw_error")\n')
-    gcc.register_callback(gcc.PLUGIN_FINISH_UNIT, close_output)
-    ps = GdbExceptionChecker(output_file)
-    ps.register_after('ssa')
-
-main()
diff --git a/gdb/contrib/exsummary.py b/gdb/contrib/exsummary.py
deleted file mode 100644 (file)
index f3f7c60..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-#   Copyright 2011-2019 Free Software Foundation, Inc.
-#
-#   This 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 of the License, 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/>.
-
-import sys
-import glob
-
-# Compute the summary information from the files created by
-# excheck.py.  Run in the build directory where you used the
-# excheck.py plugin.
-
-class Function:
-    def __init__(self, name):
-        self.name = name
-        self.location = None
-        self.callers = []
-        self.can_throw = False
-        self.marked_nothrow = False
-        self.reason = None
-
-    def log(self, message):
-        print "%s: note: %s" % (self.location, message)
-
-    def set_location(self, location):
-        self.location = location
-
-    # CALLER is an Edge.
-    def add_caller(self, caller):
-        # self.log("adding call from %s" % caller.from_fn.name)
-        self.callers.append(caller)
-        # self.log("len = %d" % len(self.callers))
-
-    def consistency_check(self):
-        if self.marked_nothrow and self.can_throw:
-            print ("%s: error: %s marked as both 'throw' and 'nothrow'"
-                   % (self.location, self.name))
-
-    def declare_nothrow(self):
-        self.marked_nothrow = True
-        self.consistency_check()
-
-    def declare_throw(self):
-        result = not self.can_throw # Return True the first time
-        self.can_throw = True
-        self.consistency_check()
-        return result
-
-    def print_stack(self, is_indirect):
-        if is_indirect:
-            print ("%s: error: function %s is marked nothrow but is assumed to throw due to indirect call"
-                   % (self.location, self.name))
-        else:
-            print ("%s: error: function %s is marked nothrow but can throw"
-                   % (self.location, self.name))
-
-        edge = self.reason
-        while edge is not None:
-            print ("%s: info: via call to %s"
-                   % (edge.location, edge.to_fn.name))
-            edge = edge.to_fn.reason
-
-    def mark_throw(self, edge, work_list, is_indirect):
-        if not self.can_throw:
-            # self.log("can throw")
-            self.can_throw = True
-            self.reason = edge
-            if self.marked_nothrow:
-                self.print_stack(is_indirect)
-            else:
-                # Do this in the 'else' to avoid extra error
-                # propagation.
-                work_list.append(self)
-
-class Edge:
-    def __init__(self, from_fn, to_fn, location):
-        self.from_fn = from_fn
-        self.to_fn = to_fn
-        self.location = location
-
-# Work list of known-throwing functions.
-work_list = []
-# Map from function name to Function object.
-function_map = {}
-# Work list of indirect calls.
-indirect_functions = []
-# Whether we should process cleanup functions as well.
-process_cleanups = False
-# Whether we should process indirect function calls.
-process_indirect = False
-
-def declare(fn_name):
-    global function_map
-    if fn_name not in function_map:
-        function_map[fn_name] = Function(fn_name)
-    return function_map[fn_name]
-
-def define_function(fn_name, location):
-    fn = declare(fn_name)
-    fn.set_location(location)
-
-def declare_throw(fn_name):
-    global work_list
-    fn = declare(fn_name)
-    if fn.declare_throw():
-        work_list.append(fn)
-
-def declare_nothrow(fn_name):
-    fn = declare(fn_name)
-    fn.declare_nothrow()
-
-def declare_cleanup(fn_name):
-    global process_cleanups
-    fn = declare(fn_name)
-    if process_cleanups:
-        fn.declare_nothrow()
-
-def function_call(to, frm, location):
-    to_fn = declare(to)
-    frm_fn = declare(frm)
-    to_fn.add_caller(Edge(frm_fn, to_fn, location))
-
-def has_indirect_call(fn_name, location):
-    global indirect_functions
-    fn = declare(fn_name)
-    phony = Function("<indirect call>")
-    phony.add_caller(Edge(fn, phony, location))
-    indirect_functions.append(phony)
-
-def mark_functions(worklist, is_indirect):
-    for callee in worklist:
-        for edge in callee.callers:
-            edge.from_fn.mark_throw(edge, worklist, is_indirect)
-
-def help_and_exit():
-    print "Usage: exsummary [OPTION]..."
-    print ""
-    print "Read the .py files from the exception checker plugin and"
-    print "generate an error summary."
-    print ""
-    print "  --cleanups     Include invalid behavior in cleanups"
-    print "  --indirect     Include assumed errors due to indirect function calls"
-    sys.exit(0)
-
-def main():
-    global work_list
-    global indirect_functions
-    global process_cleanups
-    global process_indirect
-
-    for arg in sys.argv:
-        if arg == '--cleanups':
-            process_cleanups = True
-        elif arg == '--indirect':
-            process_indirect = True
-        elif arg == '--help':
-            help_and_exit()
-
-    for fname in sorted(glob.glob('*.c.gdb_exc.py')):
-        execfile(fname)
-    print "================"
-    print "= Ordinary marking"
-    print "================"
-    mark_functions(work_list, False)
-    if process_indirect:
-        print "================"
-        print "= Indirect marking"
-        print "================"
-        mark_functions(indirect_functions, True)
-    return 0
-
-if __name__ == '__main__':
-    status = main()
-    sys.exit(status)
diff --git a/gdb/contrib/gcc-with-excheck b/gdb/contrib/gcc-with-excheck
deleted file mode 100755 (executable)
index c4b0570..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/sh
-#   Copyright 2011-2019 Free Software Foundation, Inc.
-#
-#   This 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 of the License, 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/>.
-
-# You must set PYTHON_PLUGIN in the environment.
-# It should be the directory holding the "python.so" file.
-# Usage: gcc-with-excheck [-Xx|-Xc] [--] ARGS
-# -Xx means to invoke the exception checker.
-# -Xc means to invoke the cleanup checker.
-# -- means stop processing -X options.
-# ARGS are passed to gcc.
-
-GCC=${GCC:-gcc}
-exdir=`dirname $0`
-
-pargs=
-while true; do
-    case "$1" in
-       -Xc)
-           pargs="$pargs -fplugin-arg-python-script=$exdir/cleanup_check.py"
-           ;;
-       -Xx)
-           pargs="$pargs -fplugin-arg-python-script=$exdir/excheck.py"
-           ;;
-       -X*)
-           echo "unrecognized argument $1" 1>&2
-           exit 1
-           ;;
-       --)
-           shift
-           break
-           ;;
-       *)
-           break
-           ;;
-    esac
-    shift
-done
-
-# Recent versions of the Python plugin build two .so files in
-# different directories, so we have to set this.  This will be fixed
-# upstream at some point.
-export LD_LIBRARY_PATH=$PYTHON_PLUGIN:$PYTHON_PLUGIN/gcc-c-api
-
-gcc -fplugin=$PYTHON_PLUGIN/python.so $pargs "$@"