diff options
Diffstat (limited to 'utils/libcxx/sym_check/diff.py')
-rw-r--r-- | utils/libcxx/sym_check/diff.py | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/utils/libcxx/sym_check/diff.py b/utils/libcxx/sym_check/diff.py new file mode 100644 index 000000000000..0821ef6f780a --- /dev/null +++ b/utils/libcxx/sym_check/diff.py @@ -0,0 +1,103 @@ +# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80: +#===----------------------------------------------------------------------===## +# +# The LLVM Compiler Infrastructure +# +# This file is dual licensed under the MIT and the University of Illinois Open +# Source Licenses. See LICENSE.TXT for details. +# +#===----------------------------------------------------------------------===## +""" +diff - A set of functions for diff-ing two symbol lists. +""" + +from libcxx.sym_check import util + + +def _symbol_difference(lhs, rhs): + lhs_names = set((n['name'] for n in lhs)) + rhs_names = set((n['name'] for n in rhs)) + diff_names = lhs_names - rhs_names + return [n for n in lhs if n['name'] in diff_names] + + +def _find_by_key(sym_list, k): + for sym in sym_list: + if sym['name'] == k: + return sym + return None + + +def added_symbols(old, new): + return _symbol_difference(new, old) + + +def removed_symbols(old, new): + return _symbol_difference(old, new) + + +def changed_symbols(old, new): + changed = [] + for old_sym in old: + if old_sym in new: + continue + new_sym = _find_by_key(new, old_sym['name']) + if (new_sym is not None and not new_sym in old + and old_sym != new_sym): + changed += [(old_sym, new_sym)] + return changed + + +def diff(old, new): + added = added_symbols(old, new) + removed = removed_symbols(old, new) + changed = changed_symbols(old, new) + return added, removed, changed + + +def report_diff(added_syms, removed_syms, changed_syms, names_only=False, + demangle=True): + def maybe_demangle(name): + return util.demangle_symbol(name) if demangle else name + + report = '' + for sym in added_syms: + report += 'Symbol added: %s\n' % maybe_demangle(sym['name']) + if not names_only: + report += ' %s\n\n' % sym + if added_syms and names_only: + report += '\n' + for sym in removed_syms: + report += 'SYMBOL REMOVED: %s\n' % maybe_demangle(sym['name']) + if not names_only: + report += ' %s\n\n' % sym + if removed_syms and names_only: + report += '\n' + if not names_only: + for sym_pair in changed_syms: + old_sym, new_sym = sym_pair + old_str = '\n OLD SYMBOL: %s' % old_sym + new_str = '\n NEW SYMBOL: %s' % new_sym + report += ('SYMBOL CHANGED: %s%s%s\n\n' % + (maybe_demangle(old_sym['name']), + old_str, new_str)) + + added = bool(len(added_syms) != 0) + abi_break = bool(len(removed_syms)) + if not names_only: + abi_break = abi_break or len(changed_syms) + if added or abi_break: + report += 'Summary\n' + report += ' Added: %d\n' % len(added_syms) + report += ' Removed: %d\n' % len(removed_syms) + if not names_only: + report += ' Changed: %d\n' % len(changed_syms) + if not abi_break: + report += 'Symbols added.' + else: + report += 'ABI BREAKAGE: SYMBOLS ADDED OR REMOVED!' + else: + report += 'Symbols match.' + is_different = abi_break or bool(len(added_syms)) \ + or bool(len(changed_syms)) + return report, abi_break, is_different |