57
57
#include " llvm/ADT/STLExtras.h"
58
58
#include " llvm/ADT/StringRef.h"
59
59
#include " llvm/Support/Compiler.h"
60
+ #include " llvm/Support/Regex.h"
60
61
#include " llvm/TargetParser/Triple.h"
61
62
62
63
#include < cctype>
@@ -658,6 +659,37 @@ static char ConvertValueObjectStyleToChar(
658
659
return ' \0 ' ;
659
660
}
660
661
662
+ // / Options supported by format_provider<T> for integral arithmetic types.
663
+ // / See table in FormatProviders.h.
664
+ static llvm::Regex LLVMFormatPattern{" x[-+]?\\ d*|n|d" , llvm::Regex::IgnoreCase};
665
+
666
+ static bool DumpValueWithLLVMFormat (Stream &s, llvm::StringRef options,
667
+ ValueObject &valobj) {
668
+ std::string formatted;
669
+ std::string llvm_format = (" {0:" + options + " }" ).str ();
670
+
671
+ auto type_info = valobj.GetTypeInfo ();
672
+ if ((type_info & eTypeIsInteger) && LLVMFormatPattern.match (options)) {
673
+ if (type_info & eTypeIsSigned) {
674
+ bool success = false ;
675
+ int64_t integer = valobj.GetValueAsSigned (0 , &success);
676
+ if (success)
677
+ formatted = llvm::formatv (llvm_format.data (), integer);
678
+ } else {
679
+ bool success = false ;
680
+ uint64_t integer = valobj.GetValueAsUnsigned (0 , &success);
681
+ if (success)
682
+ formatted = llvm::formatv (llvm_format.data (), integer);
683
+ }
684
+ }
685
+
686
+ if (formatted.empty ())
687
+ return false ;
688
+
689
+ s.Write (formatted.data (), formatted.size ());
690
+ return true ;
691
+ }
692
+
661
693
static bool DumpValue (Stream &s, const SymbolContext *sc,
662
694
const ExecutionContext *exe_ctx,
663
695
const FormatEntity::Entry &entry, ValueObject *valobj) {
@@ -728,9 +760,12 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
728
760
return RunScriptFormatKeyword (s, sc, exe_ctx, valobj, entry.string .c_str ());
729
761
}
730
762
731
- llvm::StringRef subpath (entry.string );
763
+ auto split = llvm::StringRef (entry.string ).split (' :' );
764
+ auto subpath = split.first ;
765
+ auto llvm_format = split.second ;
766
+
732
767
// simplest case ${var}, just print valobj's value
733
- if (entry. string .empty ()) {
768
+ if (subpath .empty ()) {
734
769
if (entry.printf_format .empty () && entry.fmt == eFormatDefault &&
735
770
entry.number == ValueObject::eValueObjectRepresentationStyleValue)
736
771
was_plain_var = true ;
@@ -739,22 +774,19 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
739
774
target = valobj;
740
775
} else // this is ${var.something} or multiple .something nested
741
776
{
742
- if (entry. string [0 ] == ' [' )
777
+ if (subpath [0 ] == ' [' )
743
778
was_var_indexed = true ;
744
779
ScanBracketedRange (subpath, close_bracket_index,
745
780
var_name_final_if_array_range, index_lower,
746
781
index_higher);
747
782
748
783
Status error;
749
784
750
- const std::string &expr_path = entry.string ;
751
-
752
- LLDB_LOGF (log, " [Debugger::FormatPrompt] symbol to expand: %s" ,
753
- expr_path.c_str ());
785
+ LLDB_LOG (log, " [Debugger::FormatPrompt] symbol to expand: {0}" , subpath);
754
786
755
787
target =
756
788
valobj
757
- ->GetValueForExpressionPath (expr_path. c_str () , &reason_to_stop,
789
+ ->GetValueForExpressionPath (subpath , &reason_to_stop,
758
790
&final_value_type, options, &what_next)
759
791
.get ();
760
792
@@ -883,8 +915,18 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
883
915
}
884
916
885
917
if (!is_array_range) {
886
- LLDB_LOGF (log,
887
- " [Debugger::FormatPrompt] dumping ordinary printable output" );
918
+ if (!llvm_format.empty ()) {
919
+ if (DumpValueWithLLVMFormat (s, llvm_format, *target)) {
920
+ LLDB_LOGF (log, " dumping using llvm format" );
921
+ return true ;
922
+ } else {
923
+ LLDB_LOG (
924
+ log,
925
+ " empty output using llvm format '{0}' - with type info flags {1}" ,
926
+ entry.printf_format , target->GetTypeInfo ());
927
+ }
928
+ }
929
+ LLDB_LOGF (log, " dumping ordinary printable output" );
888
930
return target->DumpPrintableRepresentation (s, val_obj_display,
889
931
custom_format);
890
932
} else {
@@ -2227,6 +2269,16 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
2227
2269
if (error.Fail ())
2228
2270
return error;
2229
2271
2272
+ llvm::StringRef entry_string (entry.string );
2273
+ if (entry_string.contains (' :' )) {
2274
+ auto [_, llvm_format] = entry_string.split (' :' );
2275
+ if (!llvm_format.empty () && !LLVMFormatPattern.match (llvm_format)) {
2276
+ error.SetErrorStringWithFormat (" invalid llvm format: '%s'" ,
2277
+ llvm_format.data ());
2278
+ return error;
2279
+ }
2280
+ }
2281
+
2230
2282
if (verify_is_thread_id) {
2231
2283
if (entry.type != Entry::Type::ThreadID &&
2232
2284
entry.type != Entry::Type::ThreadProtocolID) {
0 commit comments