1 //===-- LibCxx.cpp --------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/FormatEntity.h"
13 #include "lldb/DataFormatters/FormattersHelpers.h"
14 #include "lldb/DataFormatters/StringPrinter.h"
15 #include "lldb/DataFormatters/TypeSummary.h"
16 #include "lldb/DataFormatters/VectorIterator.h"
17 #include "lldb/Target/SectionLoadList.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Utility/ConstString.h"
20 #include "lldb/Utility/DataBufferHeap.h"
21 #include "lldb/Utility/Endian.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/Stream.h"
24 #include "lldb/ValueObject/ValueObject.h"
25 #include "lldb/ValueObject/ValueObjectConstResult.h"
27 #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
28 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
29 #include "lldb/lldb-enumerations.h"
30 #include "lldb/lldb-forward.h"
35 using namespace lldb_private
;
36 using namespace lldb_private::formatters
;
38 static void consumeInlineNamespace(llvm::StringRef
&name
) {
39 // Delete past an inline namespace, if any: __[a-zA-Z0-9_]+::
41 if (scratch
.consume_front("__") && std::isalnum(scratch
[0])) {
42 scratch
= scratch
.drop_while([](char c
) { return std::isalnum(c
); });
43 if (scratch
.consume_front("::")) {
44 // Successfully consumed a namespace.
50 bool lldb_private::formatters::isOldCompressedPairLayout(
51 ValueObject
&pair_obj
) {
52 return isStdTemplate(pair_obj
.GetTypeName(), "__compressed_pair");
55 bool lldb_private::formatters::isStdTemplate(ConstString type_name
,
56 llvm::StringRef type
) {
57 llvm::StringRef name
= type_name
.GetStringRef();
58 // The type name may be prefixed with `std::__<inline-namespace>::`.
59 if (name
.consume_front("std::"))
60 consumeInlineNamespace(name
);
61 return name
.consume_front(type
) && name
.starts_with("<");
64 lldb::ValueObjectSP
lldb_private::formatters::GetChildMemberWithName(
65 ValueObject
&obj
, llvm::ArrayRef
<ConstString
> alternative_names
) {
66 for (ConstString name
: alternative_names
) {
67 lldb::ValueObjectSP child_sp
= obj
.GetChildMemberWithName(name
);
76 lldb_private::formatters::GetFirstValueOfLibCXXCompressedPair(
79 ValueObjectSP first_child
= pair
.GetChildAtIndex(0);
81 value
= first_child
->GetChildMemberWithName("__value_");
83 // pre-c88580c member name
84 value
= pair
.GetChildMemberWithName("__first_");
90 lldb_private::formatters::GetSecondValueOfLibCXXCompressedPair(
93 if (pair
.GetNumChildrenIgnoringErrors() > 1) {
94 ValueObjectSP second_child
= pair
.GetChildAtIndex(1);
96 value
= second_child
->GetChildMemberWithName("__value_");
100 // pre-c88580c member name
101 value
= pair
.GetChildMemberWithName("__second_");
106 bool lldb_private::formatters::LibcxxFunctionSummaryProvider(
107 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
109 ValueObjectSP
valobj_sp(valobj
.GetNonSyntheticValue());
114 ExecutionContext
exe_ctx(valobj_sp
->GetExecutionContextRef());
115 Process
*process
= exe_ctx
.GetProcessPtr();
117 if (process
== nullptr)
120 CPPLanguageRuntime
*cpp_runtime
= CPPLanguageRuntime::Get(*process
);
125 CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info
=
126 cpp_runtime
->FindLibCppStdFunctionCallableInfo(valobj_sp
);
128 switch (callable_info
.callable_case
) {
129 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid
:
130 stream
.Printf(" __f_ = %" PRIu64
, callable_info
.member_f_pointer_value
);
133 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda
:
135 " Lambda in File %s at Line %u",
136 callable_info
.callable_line_entry
.GetFile().GetFilename().GetCString(),
137 callable_info
.callable_line_entry
.line
);
139 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject
:
141 " Function in File %s at Line %u",
142 callable_info
.callable_line_entry
.GetFile().GetFilename().GetCString(),
143 callable_info
.callable_line_entry
.line
);
145 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction
:
146 stream
.Printf(" Function = %s ",
147 callable_info
.callable_symbol
.GetName().GetCString());
154 bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
155 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
156 ValueObjectSP
valobj_sp(valobj
.GetNonSyntheticValue());
159 ValueObjectSP
ptr_sp(valobj_sp
->GetChildMemberWithName("__ptr_"));
160 ValueObjectSP
count_sp(
161 valobj_sp
->GetChildAtNamePath({"__cntrl_", "__shared_owners_"}));
162 ValueObjectSP
weakcount_sp(
163 valobj_sp
->GetChildAtNamePath({"__cntrl_", "__shared_weak_owners_"}));
168 if (ptr_sp
->GetValueAsUnsigned(0) == 0) {
169 stream
.Printf("nullptr");
172 bool print_pointee
= false;
174 ValueObjectSP pointee_sp
= ptr_sp
->Dereference(error
);
175 if (pointee_sp
&& error
.Success()) {
176 if (pointee_sp
->DumpPrintableRepresentation(
177 stream
, ValueObject::eValueObjectRepresentationStyleSummary
,
178 lldb::eFormatInvalid
,
179 ValueObject::PrintableRepresentationSpecialCases::eDisable
,
181 print_pointee
= true;
184 stream
.Printf("ptr = 0x%" PRIx64
, ptr_sp
->GetValueAsUnsigned(0));
188 stream
.Printf(" strong=%" PRIu64
, 1 + count_sp
->GetValueAsUnsigned(0));
191 stream
.Printf(" weak=%" PRIu64
, 1 + weakcount_sp
->GetValueAsUnsigned(0));
196 bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
197 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
198 ValueObjectSP
valobj_sp(valobj
.GetNonSyntheticValue());
202 ValueObjectSP
ptr_sp(valobj_sp
->GetChildMemberWithName("__ptr_"));
206 if (isOldCompressedPairLayout(*ptr_sp
))
207 ptr_sp
= GetFirstValueOfLibCXXCompressedPair(*ptr_sp
);
212 if (ptr_sp
->GetValueAsUnsigned(0) == 0) {
213 stream
.Printf("nullptr");
216 bool print_pointee
= false;
218 ValueObjectSP pointee_sp
= ptr_sp
->Dereference(error
);
219 if (pointee_sp
&& error
.Success()) {
220 if (pointee_sp
->DumpPrintableRepresentation(
221 stream
, ValueObject::eValueObjectRepresentationStyleSummary
,
222 lldb::eFormatInvalid
,
223 ValueObject::PrintableRepresentationSpecialCases::eDisable
,
225 print_pointee
= true;
228 stream
.Printf("ptr = 0x%" PRIx64
, ptr_sp
->GetValueAsUnsigned(0));
235 (lldb) fr var ibeg --raw --ptr-depth 1 -T
236 (std::__1::__wrap_iter<int *>) ibeg = {
237 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
243 SyntheticChildrenFrontEnd
*
244 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
245 CXXSyntheticChildren
*, lldb::ValueObjectSP valobj_sp
) {
246 return (valobj_sp
? new VectorIteratorSyntheticFrontEnd(
247 valobj_sp
, {ConstString("__i_"), ConstString("__i")})
251 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
252 LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
)
253 : SyntheticChildrenFrontEnd(*valobj_sp
), m_cntrl(nullptr) {
258 llvm::Expected
<uint32_t> lldb_private::formatters::
259 LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren() {
260 return (m_cntrl
? 1 : 0);
264 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
267 return lldb::ValueObjectSP();
269 ValueObjectSP valobj_sp
= m_backend
.GetSP();
271 return lldb::ValueObjectSP();
274 return valobj_sp
->GetChildMemberWithName("__ptr_");
277 if (auto ptr_sp
= valobj_sp
->GetChildMemberWithName("__ptr_")) {
280 valobj_sp
->GetCompilerType()
281 .GetTypeTemplateArgument(0).GetPointerType();
282 ValueObjectSP cast_ptr_sp
= ptr_sp
->Cast(value_type_sp
);
283 ValueObjectSP value_sp
= cast_ptr_sp
->Dereference(status
);
284 if (status
.Success()) {
290 return lldb::ValueObjectSP();
293 lldb::ChildCacheState
294 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
297 ValueObjectSP valobj_sp
= m_backend
.GetSP();
299 return lldb::ChildCacheState::eRefetch
;
301 TargetSP
target_sp(valobj_sp
->GetTargetSP());
303 return lldb::ChildCacheState::eRefetch
;
305 lldb::ValueObjectSP
cntrl_sp(valobj_sp
->GetChildMemberWithName("__cntrl_"));
307 m_cntrl
= cntrl_sp
.get(); // need to store the raw pointer to avoid a circular
309 return lldb::ChildCacheState::eRefetch
;
312 bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
313 MightHaveChildren() {
317 size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
318 GetIndexOfChildWithName(ConstString name
) {
319 if (name
== "__ptr_")
321 if (name
== "$$dereference$$")
326 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
327 ~LibcxxSharedPtrSyntheticFrontEnd() = default;
329 SyntheticChildrenFrontEnd
*
330 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
331 CXXSyntheticChildren
*, lldb::ValueObjectSP valobj_sp
) {
332 return (valobj_sp
? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp
)
336 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
337 LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
)
338 : SyntheticChildrenFrontEnd(*valobj_sp
) {
343 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
344 ~LibcxxUniquePtrSyntheticFrontEnd() = default;
346 SyntheticChildrenFrontEnd
*
347 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
348 CXXSyntheticChildren
*, lldb::ValueObjectSP valobj_sp
) {
349 return (valobj_sp
? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp
)
353 llvm::Expected
<uint32_t> lldb_private::formatters::
354 LibcxxUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
356 return m_deleter_sp
? 2 : 1;
361 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
364 return lldb::ValueObjectSP();
367 return m_value_ptr_sp
;
374 auto value_sp
= m_value_ptr_sp
->Dereference(status
);
375 if (status
.Success()) {
380 return lldb::ValueObjectSP();
383 lldb::ChildCacheState
384 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
385 ValueObjectSP valobj_sp
= m_backend
.GetSP();
387 return lldb::ChildCacheState::eRefetch
;
389 ValueObjectSP
ptr_sp(valobj_sp
->GetChildMemberWithName("__ptr_"));
391 return lldb::ChildCacheState::eRefetch
;
393 // Retrieve the actual pointer and the deleter, and clone them to give them
394 // user-friendly names.
395 if (isOldCompressedPairLayout(*ptr_sp
)) {
396 if (ValueObjectSP value_pointer_sp
=
397 GetFirstValueOfLibCXXCompressedPair(*ptr_sp
))
398 m_value_ptr_sp
= value_pointer_sp
->Clone(ConstString("pointer"));
400 if (ValueObjectSP deleter_sp
=
401 GetSecondValueOfLibCXXCompressedPair(*ptr_sp
))
402 m_deleter_sp
= deleter_sp
->Clone(ConstString("deleter"));
404 m_value_ptr_sp
= ptr_sp
->Clone(ConstString("pointer"));
406 if (ValueObjectSP deleter_sp
=
407 valobj_sp
->GetChildMemberWithName("__deleter_"))
408 if (deleter_sp
->GetNumChildrenIgnoringErrors() > 0)
409 m_deleter_sp
= deleter_sp
->Clone(ConstString("deleter"));
412 return lldb::ChildCacheState::eRefetch
;
415 bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
416 MightHaveChildren() {
420 size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
421 GetIndexOfChildWithName(ConstString name
) {
422 if (name
== "pointer")
424 if (name
== "deleter")
426 if (name
== "$$dereference$$")
431 bool lldb_private::formatters::LibcxxContainerSummaryProvider(
432 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
433 if (valobj
.IsPointerType()) {
434 uint64_t value
= valobj
.GetValueAsUnsigned(0);
437 stream
.Printf("0x%016" PRIx64
" ", value
);
439 return FormatEntity::FormatStringRef("size=${svar%#}", stream
, nullptr,
440 nullptr, nullptr, &valobj
, false, false);
443 /// The field layout in a libc++ string (cap, side, data or data, size, cap).
445 enum class StringLayout
{ CSD
, DSC
};
448 static ValueObjectSP
ExtractLibCxxStringData(ValueObject
&valobj
) {
449 if (auto rep_sp
= valobj
.GetChildMemberWithName("__rep_"))
452 ValueObjectSP valobj_r_sp
= valobj
.GetChildMemberWithName("__r_");
453 if (!valobj_r_sp
|| !valobj_r_sp
->GetError().Success())
456 if (!isOldCompressedPairLayout(*valobj_r_sp
))
459 return GetFirstValueOfLibCXXCompressedPair(*valobj_r_sp
);
462 /// Determine the size in bytes of \p valobj (a libc++ std::string object) and
463 /// extract its data payload. Return the size + payload pair.
464 // TODO: Support big-endian architectures.
465 static std::optional
<std::pair
<uint64_t, ValueObjectSP
>>
466 ExtractLibcxxStringInfo(ValueObject
&valobj
) {
467 ValueObjectSP valobj_rep_sp
= ExtractLibCxxStringData(valobj
);
468 if (!valobj_rep_sp
|| !valobj_rep_sp
->GetError().Success())
471 ValueObjectSP l
= valobj_rep_sp
->GetChildMemberWithName("__l");
475 StringLayout layout
= l
->GetIndexOfChildWithName("__data_") == 0
479 bool short_mode
= false; // this means the string is in short-mode and the
480 // data is stored inline
481 bool using_bitmasks
= true; // Whether the class uses bitmasks for the mode
482 // flag (pre-D123580).
484 uint64_t size_mode_value
= 0;
486 ValueObjectSP short_sp
= valobj_rep_sp
->GetChildMemberWithName("__s");
490 ValueObjectSP is_long
= short_sp
->GetChildMemberWithName("__is_long_");
491 ValueObjectSP size_sp
= short_sp
->GetChildMemberWithName("__size_");
496 using_bitmasks
= false;
497 short_mode
= !is_long
->GetValueAsUnsigned(/*fail_value=*/0);
498 size
= size_sp
->GetValueAsUnsigned(/*fail_value=*/0);
500 // The string mode is encoded in the size field.
501 size_mode_value
= size_sp
->GetValueAsUnsigned(0);
502 uint8_t mode_mask
= layout
== StringLayout::DSC
? 0x80 : 1;
503 short_mode
= (size_mode_value
& mode_mask
) == 0;
507 ValueObjectSP location_sp
= short_sp
->GetChildMemberWithName("__data_");
509 size
= (layout
== StringLayout::DSC
) ? size_mode_value
510 : ((size_mode_value
>> 1) % 256);
515 // When the small-string optimization takes place, the data must fit in the
516 // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
517 // likely that the string isn't initialized and we're reading garbage.
518 ExecutionContext
exe_ctx(location_sp
->GetExecutionContextRef());
519 const std::optional
<uint64_t> max_bytes
=
520 location_sp
->GetCompilerType().GetByteSize(
521 exe_ctx
.GetBestExecutionContextScope());
522 if (!max_bytes
|| size
> *max_bytes
)
525 return std::make_pair(size
, location_sp
);
528 // we can use the layout_decider object as the data pointer
529 ValueObjectSP location_sp
= l
->GetChildMemberWithName("__data_");
530 ValueObjectSP size_vo
= l
->GetChildMemberWithName("__size_");
531 ValueObjectSP capacity_vo
= l
->GetChildMemberWithName("__cap_");
532 if (!size_vo
|| !location_sp
|| !capacity_vo
)
534 size
= size_vo
->GetValueAsUnsigned(LLDB_INVALID_OFFSET
);
535 uint64_t capacity
= capacity_vo
->GetValueAsUnsigned(LLDB_INVALID_OFFSET
);
536 if (!using_bitmasks
&& layout
== StringLayout::CSD
)
538 if (size
== LLDB_INVALID_OFFSET
|| capacity
== LLDB_INVALID_OFFSET
||
541 return std::make_pair(size
, location_sp
);
545 LibcxxWStringSummaryProvider(ValueObject
&valobj
, Stream
&stream
,
546 const TypeSummaryOptions
&summary_options
,
547 ValueObjectSP location_sp
, size_t size
) {
549 stream
.Printf("L\"\"");
555 StringPrinter::ReadBufferAndDumpToStreamOptions
options(valobj
);
556 if (summary_options
.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped
) {
557 const auto max_size
= valobj
.GetTargetSP()->GetMaximumSizeOfStringSummary();
558 if (size
> max_size
) {
560 options
.SetIsTruncated(true);
564 DataExtractor extractor
;
565 const size_t bytes_read
= location_sp
->GetPointeeData(extractor
, 0, size
);
566 if (bytes_read
< size
)
569 // std::wstring::size() is measured in 'characters', not bytes
570 TypeSystemClangSP scratch_ts_sp
=
571 ScratchTypeSystemClang::GetForTarget(*valobj
.GetTargetSP());
576 scratch_ts_sp
->GetBasicType(lldb::eBasicTypeWChar
).GetByteSize(nullptr);
580 options
.SetData(std::move(extractor
));
581 options
.SetStream(&stream
);
582 options
.SetPrefixToken("L");
583 options
.SetQuote('"');
584 options
.SetSourceSize(size
);
585 options
.SetBinaryZeroIsTerminator(false);
587 switch (*wchar_t_size
) {
589 return StringPrinter::ReadBufferAndDumpToStream
<
590 lldb_private::formatters::StringPrinter::StringElementType::UTF8
>(
595 return StringPrinter::ReadBufferAndDumpToStream
<
596 lldb_private::formatters::StringPrinter::StringElementType::UTF16
>(
601 return StringPrinter::ReadBufferAndDumpToStream
<
602 lldb_private::formatters::StringPrinter::StringElementType::UTF32
>(
608 bool lldb_private::formatters::LibcxxWStringSummaryProvider(
609 ValueObject
&valobj
, Stream
&stream
,
610 const TypeSummaryOptions
&summary_options
) {
611 auto string_info
= ExtractLibcxxStringInfo(valobj
);
615 ValueObjectSP location_sp
;
616 std::tie(size
, location_sp
) = *string_info
;
618 return ::LibcxxWStringSummaryProvider(valobj
, stream
, summary_options
,
622 template <StringPrinter::StringElementType element_type
>
624 LibcxxStringSummaryProvider(ValueObject
&valobj
, Stream
&stream
,
625 const TypeSummaryOptions
&summary_options
,
626 std::string prefix_token
, ValueObjectSP location_sp
,
630 stream
.Printf("\"\"");
637 StringPrinter::ReadBufferAndDumpToStreamOptions
options(valobj
);
639 if (summary_options
.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped
) {
640 const auto max_size
= valobj
.GetTargetSP()->GetMaximumSizeOfStringSummary();
641 if (size
> max_size
) {
643 options
.SetIsTruncated(true);
648 DataExtractor extractor
;
649 const size_t bytes_read
= location_sp
->GetPointeeData(extractor
, 0, size
);
650 if (bytes_read
< size
)
653 options
.SetData(std::move(extractor
));
655 options
.SetStream(&stream
);
656 if (prefix_token
.empty())
657 options
.SetPrefixToken(nullptr);
659 options
.SetPrefixToken(prefix_token
);
660 options
.SetQuote('"');
661 options
.SetSourceSize(size
);
662 options
.SetBinaryZeroIsTerminator(false);
663 return StringPrinter::ReadBufferAndDumpToStream
<element_type
>(options
);
666 template <StringPrinter::StringElementType element_type
>
668 LibcxxStringSummaryProvider(ValueObject
&valobj
, Stream
&stream
,
669 const TypeSummaryOptions
&summary_options
,
670 std::string prefix_token
) {
671 auto string_info
= ExtractLibcxxStringInfo(valobj
);
675 ValueObjectSP location_sp
;
676 std::tie(size
, location_sp
) = *string_info
;
678 return LibcxxStringSummaryProvider
<element_type
>(
679 valobj
, stream
, summary_options
, prefix_token
, location_sp
, size
);
681 template <StringPrinter::StringElementType element_type
>
682 static bool formatStringImpl(ValueObject
&valobj
, Stream
&stream
,
683 const TypeSummaryOptions
&summary_options
,
684 std::string prefix_token
) {
685 StreamString scratch_stream
;
686 const bool success
= LibcxxStringSummaryProvider
<element_type
>(
687 valobj
, scratch_stream
, summary_options
, prefix_token
);
689 stream
<< scratch_stream
.GetData();
691 stream
<< "Summary Unavailable";
695 bool lldb_private::formatters::LibcxxStringSummaryProviderASCII(
696 ValueObject
&valobj
, Stream
&stream
,
697 const TypeSummaryOptions
&summary_options
) {
698 return formatStringImpl
<StringPrinter::StringElementType::ASCII
>(
699 valobj
, stream
, summary_options
, "");
702 bool lldb_private::formatters::LibcxxStringSummaryProviderUTF16(
703 ValueObject
&valobj
, Stream
&stream
,
704 const TypeSummaryOptions
&summary_options
) {
705 return formatStringImpl
<StringPrinter::StringElementType::UTF16
>(
706 valobj
, stream
, summary_options
, "u");
709 bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32(
710 ValueObject
&valobj
, Stream
&stream
,
711 const TypeSummaryOptions
&summary_options
) {
712 return formatStringImpl
<StringPrinter::StringElementType::UTF32
>(
713 valobj
, stream
, summary_options
, "U");
716 static std::tuple
<bool, ValueObjectSP
, size_t>
717 LibcxxExtractStringViewData(ValueObject
& valobj
) {
718 auto dataobj
= GetChildMemberWithName(
719 valobj
, {ConstString("__data_"), ConstString("__data")});
720 auto sizeobj
= GetChildMemberWithName(
721 valobj
, {ConstString("__size_"), ConstString("__size")});
722 if (!dataobj
|| !sizeobj
)
723 return std::make_tuple
<bool,ValueObjectSP
,size_t>(false, {}, {});
725 if (!dataobj
->GetError().Success() || !sizeobj
->GetError().Success())
726 return std::make_tuple
<bool,ValueObjectSP
,size_t>(false, {}, {});
729 uint64_t size
= sizeobj
->GetValueAsUnsigned(0, &success
);
731 return std::make_tuple
<bool,ValueObjectSP
,size_t>(false, {}, {});
733 return std::make_tuple(true,dataobj
,size
);
736 template <StringPrinter::StringElementType element_type
>
737 static bool formatStringViewImpl(ValueObject
&valobj
, Stream
&stream
,
738 const TypeSummaryOptions
&summary_options
,
739 std::string prefix_token
) {
742 ValueObjectSP dataobj
;
744 std::tie(success
, dataobj
, size
) = LibcxxExtractStringViewData(valobj
);
747 stream
<< "Summary Unavailable";
751 return LibcxxStringSummaryProvider
<element_type
>(
752 valobj
, stream
, summary_options
, prefix_token
, dataobj
, size
);
755 bool lldb_private::formatters::LibcxxStringViewSummaryProviderASCII(
756 ValueObject
&valobj
, Stream
&stream
,
757 const TypeSummaryOptions
&summary_options
) {
758 return formatStringViewImpl
<StringPrinter::StringElementType::ASCII
>(
759 valobj
, stream
, summary_options
, "");
762 bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16(
763 ValueObject
&valobj
, Stream
&stream
,
764 const TypeSummaryOptions
&summary_options
) {
765 return formatStringViewImpl
<StringPrinter::StringElementType::UTF16
>(
766 valobj
, stream
, summary_options
, "u");
769 bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32(
770 ValueObject
&valobj
, Stream
&stream
,
771 const TypeSummaryOptions
&summary_options
) {
772 return formatStringViewImpl
<StringPrinter::StringElementType::UTF32
>(
773 valobj
, stream
, summary_options
, "U");
776 bool lldb_private::formatters::LibcxxWStringViewSummaryProvider(
777 ValueObject
&valobj
, Stream
&stream
,
778 const TypeSummaryOptions
&summary_options
) {
781 ValueObjectSP dataobj
;
783 std::tie(success
, dataobj
, size
) = LibcxxExtractStringViewData(valobj
);
786 stream
<< "Summary Unavailable";
790 return ::LibcxxWStringSummaryProvider(valobj
, stream
, summary_options
,
795 LibcxxChronoTimePointSecondsSummaryProvider(ValueObject
&valobj
, Stream
&stream
,
796 const TypeSummaryOptions
&options
,
798 ValueObjectSP ptr_sp
= valobj
.GetChildMemberWithName("__d_");
801 ptr_sp
= ptr_sp
->GetChildMemberWithName("__rep_");
806 // The date time in the chrono library is valid in the range
807 // [-32767-01-01T00:00:00Z, 32767-12-31T23:59:59Z]. A 64-bit time_t has a
808 // larger range, the function strftime is not able to format the entire range
809 // of time_t. The exact point has not been investigated; it's limited to
811 const std::time_t chrono_timestamp_min
=
812 -1'096'193'779'200; // -32767-01-01T00:00:00Z
813 const std::time_t chrono_timestamp_max
=
814 971'890'963'199; // 32767-12-31T23:59:59Z
816 const std::time_t chrono_timestamp_min
= -43'200; // 1969-12-31T12:00:00Z
817 const std::time_t chrono_timestamp_max
=
818 32'536'850'399; // 3001-01-19T21:59:59
821 const std::time_t seconds
= ptr_sp
->GetValueAsSigned(0);
822 if (seconds
< chrono_timestamp_min
|| seconds
> chrono_timestamp_max
)
823 stream
.Printf("timestamp=%" PRId64
" s", static_cast<int64_t>(seconds
));
825 std::array
<char, 128> str
;
827 std::strftime(str
.data(), str
.size(), fmt
, gmtime(&seconds
));
831 stream
.Printf("date/time=%s timestamp=%" PRId64
" s", str
.data(),
832 static_cast<int64_t>(seconds
));
838 bool lldb_private::formatters::LibcxxChronoSysSecondsSummaryProvider(
839 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
840 return LibcxxChronoTimePointSecondsSummaryProvider(valobj
, stream
, options
,
844 bool lldb_private::formatters::LibcxxChronoLocalSecondsSummaryProvider(
845 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
846 return LibcxxChronoTimePointSecondsSummaryProvider(valobj
, stream
, options
,
851 LibcxxChronoTimepointDaysSummaryProvider(ValueObject
&valobj
, Stream
&stream
,
852 const TypeSummaryOptions
&options
,
854 ValueObjectSP ptr_sp
= valobj
.GetChildMemberWithName("__d_");
857 ptr_sp
= ptr_sp
->GetChildMemberWithName("__rep_");
862 // The date time in the chrono library is valid in the range
863 // [-32767-01-01Z, 32767-12-31Z]. A 32-bit time_t has a larger range, the
864 // function strftime is not able to format the entire range of time_t. The
865 // exact point has not been investigated; it's limited to chrono's range.
866 const int chrono_timestamp_min
= -12'687'428; // -32767-01-01Z
867 const int chrono_timestamp_max
= 11'248'737; // 32767-12-31Z
869 const int chrono_timestamp_min
= 0; // 1970-01-01Z
870 const int chrono_timestamp_max
= 376'583; // 3001-01-19Z
873 const int days
= ptr_sp
->GetValueAsSigned(0);
874 if (days
< chrono_timestamp_min
|| days
> chrono_timestamp_max
)
875 stream
.Printf("timestamp=%d days", days
);
878 const std::time_t seconds
= std::time_t(86400) * days
;
880 std::array
<char, 128> str
;
882 std::strftime(str
.data(), str
.size(), fmt
, gmtime(&seconds
));
886 stream
.Printf("date=%s timestamp=%d days", str
.data(), days
);
892 bool lldb_private::formatters::LibcxxChronoSysDaysSummaryProvider(
893 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
894 return LibcxxChronoTimepointDaysSummaryProvider(valobj
, stream
, options
,
898 bool lldb_private::formatters::LibcxxChronoLocalDaysSummaryProvider(
899 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
900 return LibcxxChronoTimepointDaysSummaryProvider(valobj
, stream
, options
,
904 bool lldb_private::formatters::LibcxxChronoMonthSummaryProvider(
905 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
906 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
907 // uses C++17 it's not possible to use the ostream operator directly.
908 static const std::array
<std::string_view
, 12> months
= {
909 "January", "February", "March", "April", "May", "June",
910 "July", "August", "September", "October", "November", "December"};
912 ValueObjectSP ptr_sp
= valobj
.GetChildMemberWithName("__m_");
916 const unsigned month
= ptr_sp
->GetValueAsUnsigned(0);
917 if (month
>= 1 && month
<= 12)
918 stream
<< "month=" << months
[month
- 1];
920 stream
.Printf("month=%u", month
);
925 bool lldb_private::formatters::LibcxxChronoWeekdaySummaryProvider(
926 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
927 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
928 // uses C++17 it's not possible to use the ostream operator directly.
929 static const std::array
<std::string_view
, 7> weekdays
= {
930 "Sunday", "Monday", "Tuesday", "Wednesday",
931 "Thursday", "Friday", "Saturday"};
933 ValueObjectSP ptr_sp
= valobj
.GetChildMemberWithName("__wd_");
937 const unsigned weekday
= ptr_sp
->GetValueAsUnsigned(0);
939 stream
<< "weekday=" << weekdays
[weekday
];
941 stream
.Printf("weekday=%u", weekday
);
946 bool lldb_private::formatters::LibcxxChronoYearMonthDaySummaryProvider(
947 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
948 ValueObjectSP ptr_sp
= valobj
.GetChildMemberWithName("__y_");
951 ptr_sp
= ptr_sp
->GetChildMemberWithName("__y_");
954 int year
= ptr_sp
->GetValueAsSigned(0);
956 ptr_sp
= valobj
.GetChildMemberWithName("__m_");
959 ptr_sp
= ptr_sp
->GetChildMemberWithName("__m_");
962 const unsigned month
= ptr_sp
->GetValueAsUnsigned(0);
964 ptr_sp
= valobj
.GetChildMemberWithName("__d_");
967 ptr_sp
= ptr_sp
->GetChildMemberWithName("__d_");
970 const unsigned day
= ptr_sp
->GetValueAsUnsigned(0);
977 stream
.Printf("%04d-%02u-%02u", year
, month
, day
);