[Lldb-commits] [lldb] [lldb] Format `atomic<shared_ptr>` on MSVC STL (PR #237631)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Mon Nov 2 10:55:58 PST 2026
================
@@ -51,60 +72,131 @@ llvm::Expected<uint32_t> lldb_private::formatters::
lldb::ValueObjectSP
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::GetChildAtIndex(
uint32_t idx) {
- if (idx == 0 && m_storage && m_element_type.IsValid())
- return m_storage->Cast(m_element_type)->Clone("Value");
+ if (idx == 0 && m_storage)
+ return m_storage;
return nullptr;
}
lldb::ChildCacheState
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::Update() {
- m_storage = nullptr;
- m_element_type.Clear();
-
- ValueObjectSP storage_sp = m_backend.GetChildMemberWithName("_Storage");
- if (!storage_sp)
- return lldb::ChildCacheState::eRefetch;
-
- CompilerType backend_type = m_backend.GetCompilerType();
- if (!backend_type)
- return lldb::ChildCacheState::eRefetch;
-
- m_element_type = backend_type.GetTypeTemplateArgument(0);
- if (!m_element_type) {
- // PDB doesn't have info about templates, so use value_type which equals T.
- m_element_type = backend_type.GetDirectNestedTypeWithName("value_type");
-
- if (!m_element_type)
- return lldb::ChildCacheState::eRefetch;
+ m_storage.reset();
+
+ if (m_is_smart_ptr) {
+ ValueObjectSP ptr = m_backend.GetChildMemberWithName("_Ptr");
+ if (!ptr)
+ return lldb::eRefetch;
+ m_storage = ValueOfAtomic(*ptr);
+ } else {
+ m_storage = ValueOfAtomic(m_backend);
}
- m_storage = storage_sp.get();
- return lldb::ChildCacheState::eRefetch;
+ if (m_storage)
+ m_storage = m_storage->Clone("Value");
+
+ return lldb::eRefetch;
}
llvm::Expected<size_t>
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::
GetIndexOfChildWithName(llvm::StringRef name) {
- if (name == "Value")
+ if (name == "Value" || (m_is_smart_ptr && name == "$$dereference$$"))
return 0;
return llvm::createStringErrorV("type has no child named '{0}'", name);
}
lldb_private::SyntheticChildrenFrontEnd *
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEndCreator(
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
- if (valobj_sp && IsMsvcStlAtomic(*valobj_sp))
- return new MsvcStlAtomicSyntheticFrontEnd(valobj_sp);
+ bool is_smart_ptr = false;
+ if (valobj_sp && IsMsvcStlAtomic(*valobj_sp, &is_smart_ptr))
+ return new MsvcStlAtomicSyntheticFrontEnd(valobj_sp, is_smart_ptr);
return nullptr;
}
+static CompilerType FindLockedPointeeType(Target &target,
+ const CompilerType &locked_ptr_type) {
+ ConstString locked_name = locked_ptr_type.GetTypeName();
+ llvm::StringRef pointee_name = locked_name;
+ if (!pointee_name.consume_front("std::_Locked_pointer<"))
+ return {};
+ if (!pointee_name.consume_back(">"))
+ return {};
+
+ TypeQuery query(pointee_name, TypeQueryOptions::e_find_one);
+ TypeResults results;
+ target.GetImages().FindTypes(/*search_first=*/nullptr, query, results);
+ if (TypeSP type_sp = results.GetFirstType())
+ return type_sp->GetFullCompilerType();
+ return {};
+}
+
+static bool AtomicSharedPtrSummaryProvider(ValueObject &ptr,
+ ValueObject &rep_wrap,
+ Stream &stream,
+ const TypeSummaryOptions &options) {
+ // rep_wrap: _Locked_pointer<_Ref_count_base> {
+ // static constexpr uintptr_t _Lock_mask = 3;
+ // static constexpr uintptr_t _Ptr_value_mask = ~_Lock_mask;
+ //
+ // atomic<uintptr_t> Storage_;
+ // }
+ ValueObjectSP rep_storage_sp = rep_wrap.GetChildAtIndex(0);
+ if (!rep_storage_sp)
+ return false;
+ ValueObjectSP rep_ptr_sp = ValueOfAtomic(*rep_storage_sp);
+ if (!rep_ptr_sp)
+ return false;
+
+ bool ok = false;
+ uint64_t rep_ptr_val = rep_ptr_sp->GetValueAsUnsigned(0, &ok);
+ if (!ok)
+ return false;
+
+ CompilerType rep_type = rep_wrap.GetCompilerType();
+ if (!rep_type)
+ return false;
+ CompilerDecl ptr_value_decl =
+ rep_type.GetStaticFieldWithName("_Ptr_value_mask");
+ if (!ptr_value_decl)
+ return false;
+ uint64_t rep_ptr_mask = ptr_value_decl.GetConstantValue().ULongLong(~(3ULL));
+ rep_ptr_val &= rep_ptr_mask;
+
+ CompilerType ref_count_base = rep_type.GetTypeTemplateArgument(0);
+ if (!ref_count_base) {
+ // PDB: Search for the type by name, as it doesn't know about templates.
+ // Unfortunately, there's no typedef inside the type.
+ TargetSP target = rep_wrap.GetTargetSP();
+ if (!target)
+ return false;
+ ref_count_base = FindLockedPointeeType(*target, rep_type);
+ if (!ref_count_base)
+ return false;
+ }
+
+ ValueObjectSP rep = ValueObject::CreateValueObjectFromAddress(
+ "", rep_ptr_val, rep_wrap.GetExecutionContextRef(), ref_count_base);
+ if (!rep)
+ return false;
+
+ return formatters::DumpMsvcStlSmartPointerSummary(ptr, *rep, rep_ptr_val,
+ stream, options);
+}
+
bool lldb_private::formatters::MsvcStlAtomicSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- ValueObjectSP synth_sp = valobj.GetSyntheticValue();
- if (!synth_sp)
+ ValueObjectSP non_synth = valobj.GetNonSyntheticValue();
+ if (!non_synth)
return false;
+ ValueObjectSP value_sp = valobj.GetChildAtIndex(0);
----------------
charles-zablit wrote:
```suggestion
ValueObjectSP value_sp = valobj.GetSyntheticValue()->GetChildAtIndex(0);
```
This matches the old code.
https://github.com/llvm/llvm-project/pull/237631
More information about the lldb-commits
mailing list