From 408456f53eccd9b2280840aff8fa99f865024544 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Sun, 21 Feb 2021 21:45:04 -0800 Subject: [PATCH] [llvm][utils] Support dereferencing llvm::Optional lldb formatter Add deref support to `llvm::Optional` in `lldbDataFormatters.py`. This creates a synthetic provider that adds dereference support, but otherwise proxies all access to the underlying value. With this change, an optional value can be displayed by running `v *someOptional`, and its contents can be accessed with the arrow `operator->`, for example `v someOpt->HasThing`. This matches expressions usable from expression evaluation. See also D97165 and D97524. Differential Revision: https://reviews.llvm.org/D97525 --- llvm/utils/lldbDataFormatters.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/llvm/utils/lldbDataFormatters.py b/llvm/utils/lldbDataFormatters.py index b5daa09bdeec..b95bf84ab108 100644 --- a/llvm/utils/lldbDataFormatters.py +++ b/llvm/utils/lldbDataFormatters.py @@ -4,6 +4,8 @@ LLDB Formatters for LLVM data types. Load into LLDB with 'command script import /path/to/lldbDataFormatters.py' """ +import lldb + def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand('type category define -e llvm -l c++') debugger.HandleCommand('type synthetic add -w llvm ' @@ -15,6 +17,9 @@ def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand('type synthetic add -w llvm ' '-l lldbDataFormatters.ArrayRefSynthProvider ' '-x "^llvm::ArrayRef<.+>$"') + debugger.HandleCommand('type synthetic add -w llvm ' + '-l lldbDataFormatters.OptionalSynthProvider ' + '-x "^llvm::Optional<.+>$"') debugger.HandleCommand('type summary add -w llvm ' '-F lldbDataFormatters.OptionalSummaryProvider ' '-x "^llvm::Optional<.+>$"') @@ -97,7 +102,7 @@ class ArrayRefSynthProvider: self.type_size = self.data_type.GetByteSize() assert self.type_size != 0 -def OptionalSummaryProvider(valobj, internal_dict): +def GetOptionalValue(valobj): storage = valobj.GetChildMemberWithName('Storage') if not storage: storage = valobj @@ -108,11 +113,32 @@ def OptionalSummaryProvider(valobj, internal_dict): return '' if hasVal == 0: - return 'None' + return None underlying_type = storage.GetType().GetTemplateArgumentType(0) storage = storage.GetChildMemberWithName('value') - return str(storage.Cast(underlying_type)) + return storage.Cast(underlying_type) + +def OptionalSummaryProvider(valobj, internal_dict): + return GetOptionalValue(valobj).summary + +class OptionalSynthProvider: + """Provides deref support to llvm::Optional""" + def __init__(self, valobj, internal_dict): + self.valobj = valobj + + def num_children(self): + return self.valobj.num_children + + def get_child_index(self, name): + if name == '$$dereference$$': + return self.valobj.num_children + 1 + return self.valobj.GetIndexOfChildWithName(name) + + def get_child_at_index(self, index): + if index < self.valobj.num_children: + return self.valobj.GetChildAtIndex(index) + return GetOptionalValue(self.valobj) or lldb.SBValue() def SmallStringSummaryProvider(valobj, internal_dict): num_elements = valobj.GetNumChildren()