[gdb] Add pretty printer for Expected
authorFangrui Song <maskray@google.com>
Mon, 25 Jun 2018 23:38:48 +0000 (23:38 +0000)
committerFangrui Song <maskray@google.com>
Mon, 25 Jun 2018 23:38:48 +0000 (23:38 +0000)
Reviewers: dblaikie

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D48512

llvm-svn: 335554

llvm/utils/gdb-scripts/prettyprinters.py

index f2dec01..83f4392 100644 (file)
@@ -1,4 +1,17 @@
 import gdb.printing
+
+class Iterator:
+  def __iter__(self):
+    return self
+
+  # Python 2 compatibility
+  def next(self):
+    return self.__next__()
+
+  def children(self):
+    return self
+
+
 class SmallStringPrinter:
   """Print an llvm::SmallString object."""
 
@@ -103,34 +116,44 @@ class ArrayRefPrinter:
   def display_hint (self):
     return 'array'
 
-class OptionalPrinter:
-  """Print an llvm::Optional object."""
+class ExpectedPrinter(Iterator):
+  """Print an llvm::Expected object."""
 
-  def __init__(self, value):
-    self.value = value
+  def __init__(self, val):
+    self.val = val
 
-  class _iterator:
-    def __init__(self, member, empty):
-      self.member = member
-      self.done = empty
+  def __next__(self):
+    val = self.val
+    if val is None:
+      raise StopIteration
+    self.val = None
+    if val['HasError']:
+      return ('error', val['ErrorStorage'].address.cast(
+          gdb.lookup_type('llvm::ErrorInfoBase').pointer()).dereference())
+    return ('value', val['TStorage'].address.cast(
+        val.type.template_argument(0).pointer()).dereference())
 
-    def __iter__(self):
-      return self
+  def to_string(self):
+    return 'llvm::Expected{}'.format(' is error' if self.val['HasError'] else '')
 
-    def next(self):
-      if self.done:
-        raise StopIteration
-      self.done = True
-      return ('value', self.member.dereference())
+class OptionalPrinter(Iterator):
+  """Print an llvm::Optional object."""
 
-  def children(self):
-    if not self.value['Storage']['hasVal']:
-      return self._iterator('', True)
-    return self._iterator(self.value['Storage']['storage']['buffer'].address.cast(
-        self.value.type.template_argument(0).pointer()), False)
+  def __init__(self, val):
+    self.val = val
+
+  def __next__(self):
+    val = self.val
+    if val is None:
+      raise StopIteration
+    self.val = None
+    if not val['Storage']['hasVal']:
+      raise StopIteration
+    return ('value', val['Storage']['storage']['buffer'].address.cast(
+        val.type.template_argument(0).pointer()).dereference())
 
   def to_string(self):
-    return 'llvm::Optional is %sinitialized' % ('' if self.value['Storage']['hasVal'] else 'not ')
+    return 'llvm::Optional{}'.format('' if self.val['Storage']['hasVal'] else ' is not initialized')
 
 class DenseMapPrinter:
   "Print a DenseMap"
@@ -315,6 +338,7 @@ pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinte
 pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter)
 pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter)
 pp.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter)
+pp.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter)
 pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter)
 pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter)
 pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter)