diff --git a/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.cpp b/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.cpp --- a/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.cpp +++ b/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.cpp @@ -24,7 +24,13 @@ llvm::StringRef StringRef = "bar"; llvm::Twine Twine = llvm::Twine(SmallString) + StringRef; llvm::PointerIntPair PointerIntPair(IntPtr, 1); -llvm::PointerUnion PointerUnion(IntPtr); + +struct alignas(8) Z {}; +llvm::PointerUnion PointerUnion(IntPtr); + +// No members which instantiate PointerUnionUIntTraits (e.g. get()) +// are called, and this instance will therefore be raw-printed. +llvm::PointerUnion RawPrintingPointerUnion(nullptr); using IlistTag = llvm::ilist_tag; using SimpleIlistTag = llvm::ilist_tag; diff --git a/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.gdb b/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.gdb --- a/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.gdb +++ b/debuginfo-tests/llvm-prettyprinters/gdb/llvm-support.gdb @@ -1,4 +1,4 @@ -# RUN: gdb -q -batch -n -iex 'source %llvm_src_root/utils/gdb-scripts/prettyprinters.py' -x %s %llvm_tools_dir/check-gdb-llvm-support | FileCheck %s +# RUN: gdb -q -batch -n -iex 'source %llvm_src_root/utils/gdb-scripts/prettyprinters.py' -x %s %llvm_tools_dir/check-gdb-llvm-support | FileCheck %s --dump-input-on-failure break main run @@ -39,12 +39,15 @@ # CHECK: "\"foo\"\"bar\"" p Twine -# CHECK: llvm::PointerIntPair = {pointer = 0xabc, value = 1} +# CHECK: {pointer = 0xabc, value = 1} p PointerIntPair -# CHECK: llvm::PointerUnion containing int * = {pointer = 0xabc} +# CHECK: Containing int * = {pointer = 0xabc} p PointerUnion +# CHECK: PointerUnionMembers, +p RawPrintingPointerUnion + # Switch to print pretty adds newlines to the following statements. set print pretty diff --git a/llvm/utils/gdb-scripts/prettyprinters.py b/llvm/utils/gdb-scripts/prettyprinters.py --- a/llvm/utils/gdb-scripts/prettyprinters.py +++ b/llvm/utils/gdb-scripts/prettyprinters.py @@ -316,25 +316,12 @@ def to_string(self): return self.string_from_twine_object(self._val) -def make_printer(string = None, children = None, hint = None): - """Create a printer from the parameters.""" - class Printer : pass - printer = Printer() - if string: - setattr(printer, 'to_string', lambda: string) - if children: - setattr(printer, 'children', lambda: children) - if hint: - setattr(printer, 'display_hint', lambda: hint) - return printer - def get_pointer_int_pair(val): """Get tuple from llvm::PointerIntPair.""" info_name = val.type.template_argument(4).strip_typedefs().name - try: - enum_type = gdb.lookup_type(info_name + '::MaskAndShiftConstants') - except gdb.error: - return (None, None) + # Note: this throws a gdb.error if the info type is not used (by means of a + # call to getPointer() or similar) in the current translation unit. + enum_type = gdb.lookup_type(info_name + '::MaskAndShiftConstants') enum_dict = gdb.types.make_enum_dict(enum_type) ptr_mask = enum_dict[info_name + '::PointerBitMask'] int_shift = enum_dict[info_name + '::IntShift'] @@ -344,26 +331,48 @@ value = ((pair_union >> int_shift) & int_mask) return (pointer, value) +class PointerIntPairPrinter: + """Print a PointerIntPair.""" + + def __init__(self, pointer, value): + self.pointer = pointer + self.value = value + + def children(self): + yield ('pointer', self.pointer) + yield ('value', self.value) + def make_pointer_int_pair_printer(val): """Factory for an llvm::PointerIntPair printer.""" - pointer, value = get_pointer_int_pair(val) - if not pointer or not value: - return None + try: + pointer, value = get_pointer_int_pair(val) + except gdb.error: + return None # If PointerIntPair cannot be analyzed, print as raw value. pointer_type = val.type.template_argument(0) value_type = val.type.template_argument(2) - string = 'llvm::PointerIntPair<%s>' % pointer_type - children = [('pointer', pointer.cast(pointer_type)), - ('value', value.cast(value_type))] - return make_printer(string, children) + return PointerIntPairPrinter(pointer.cast(pointer_type), + value.cast(value_type)) + +class PointerUnionPrinter: + """Print a PointerUnion.""" + + def __init__(self, pointer): + self.pointer = pointer + + def children(self): + yield ('pointer', self.pointer) + + def to_string(self): + return "Containing %s" % self.pointer.type def make_pointer_union_printer(val): """Factory for an llvm::PointerUnion printer.""" - pointer, value = get_pointer_int_pair(val['Val']) - if not pointer or not value: - return None + try: + pointer, value = get_pointer_int_pair(val['Val']) + except gdb.error: + return None # If PointerIntPair cannot be analyzed, print as raw value. pointer_type = val.type.template_argument(int(value)) - string = 'llvm::PointerUnion containing %s' % pointer_type - return make_printer(string, [('pointer', pointer.cast(pointer_type))]) + return PointerUnionPrinter(pointer.cast(pointer_type)) class IlistNodePrinter: """Print an llvm::ilist_node object."""