diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 783b83615d0..7c97fc71992 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -2815,6 +2815,16 @@ ui_printf (const char *arg, struct ui_file *stream) { size_t val = value_as_long (val_args[i]); + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL + gdb_printf (stream, current_substring, val); + DIAGNOSTIC_POP + break; + } + case ptrdiff_t_arg: + { + ptrdiff_t val = value_as_long (val_args[i]); + DIAGNOSTIC_PUSH DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL gdb_printf (stream, current_substring, val); diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c index 8445fcc1aa2..82796932e1d 100644 --- a/gdb/testsuite/gdb.base/printcmds.c +++ b/gdb/testsuite/gdb.base/printcmds.c @@ -2,6 +2,8 @@ It is explicitly unsigned to avoid differences due to native characters being either signed or unsigned. */ #include +#include + unsigned char ctable1[256] = { 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, @@ -77,6 +79,10 @@ charptr teststring2 = "more contents"; const char *teststring3 = "this is a longer test string that we can use"; +/* For testing printf with %z (size_t) and %t (ptrdiff_t) length modifiers. */ +size_t test_size = 1234; +ptrdiff_t test_ptrdiff = -5678; + /* Test printing of a struct containing character arrays. */ struct some_arrays { diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index bc100f93df9..32a952f01a5 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -908,6 +908,10 @@ proc test_printf {} { # PR cli/14977. gdb_test "printf \"%s\\n\", 0" "\\(null\\)" + # Test %z (size_t) and %t (ptrdiff_t) length modifiers. + gdb_test "printf \"%zu\\n\", test_size" "1234" + gdb_test "printf \"%td\\n\", test_ptrdiff" "-5678" + with_max_value_size 20 { gdb_test {printf "%s", teststring3} \ "^printed string requires 45 bytes, which is more than max-value-size" diff --git a/gdb/ui-out.c b/gdb/ui-out.c index 4f20e6b9347..87874e22530 100644 --- a/gdb/ui-out.c +++ b/gdb/ui-out.c @@ -682,6 +682,24 @@ ui_out::vmessage (const ui_file_style &in_style, const char *format, } } break; + case ptrdiff_t_arg: + { + ptrdiff_t val = va_arg (args, ptrdiff_t); + switch (piece.n_int_args) + { + case 0: + call_do_message (style, current_substring, val); + break; + case 1: + call_do_message (style, current_substring, intvals[0], val); + break; + case 2: + call_do_message (style, current_substring, + intvals[0], intvals[1], val); + break; + } + } + break; case double_arg: call_do_message (style, current_substring, va_arg (args, double)); break; diff --git a/gdb/unittests/format_pieces-selftests.c b/gdb/unittests/format_pieces-selftests.c index af574ccc900..c5f3cf74f1d 100644 --- a/gdb/unittests/format_pieces-selftests.c +++ b/gdb/unittests/format_pieces-selftests.c @@ -105,40 +105,44 @@ test_gdb_formats () static void test_format_int_sizes () { - check ("Hello\\t %hu%lu%llu%zu", /* ARI: %ll */ + check ("Hello\\t %hu%lu%llu%zu%tu", /* ARI: %ll */ { {"Hello\t ", literal_piece, 0}, {"%hu", int_arg, 0}, {"%lu", long_arg, 0}, {"%" LL "u", long_long_arg, 0}, {"%zu", size_t_arg, 0}, + {"%tu", ptrdiff_t_arg, 0}, }); - check ("Hello\\t %hx%lx%llx%zx", /* ARI: %ll */ + check ("Hello\\t %hx%lx%llx%zx%tx", /* ARI: %ll */ { {"Hello\t ", literal_piece, 0}, {"%hx", int_arg, 0}, {"%lx", long_arg, 0}, {"%" LL "x", long_long_arg, 0}, {"%zx", size_t_arg, 0}, + {"%tx", ptrdiff_t_arg, 0}, }); - check ("Hello\\t %ho%lo%llo%zo", /* ARI: %ll */ + check ("Hello\\t %ho%lo%llo%zo%to", /* ARI: %ll */ { {"Hello\t ", literal_piece, 0}, {"%ho", int_arg, 0}, {"%lo", long_arg, 0}, {"%" LL "o", long_long_arg, 0}, {"%zo", size_t_arg, 0}, + {"%to", ptrdiff_t_arg, 0}, }); - check ("Hello\\t %hd%ld%lld%zd", /* ARI: %ll */ + check ("Hello\\t %hd%ld%lld%zd%td", /* ARI: %ll */ { {"Hello\t ", literal_piece, 0}, {"%hd", int_arg, 0}, {"%ld", long_arg, 0}, {"%" LL "d", long_long_arg, 0}, {"%zd", size_t_arg, 0}, + {"%td", ptrdiff_t_arg, 0}, }); } diff --git a/gdbserver/ax.cc b/gdbserver/ax.cc index 44fcf315729..4993bed2532 100644 --- a/gdbserver/ax.cc +++ b/gdbserver/ax.cc @@ -908,6 +908,14 @@ ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format, break; } + case ptrdiff_t_arg: + { + ptrdiff_t val = args[i]; + + printf (current_substring, val); + break; + } + case literal_piece: /* Print a portion of the format string that has no directives. Note that this will not include any diff --git a/gdbsupport/format.cc b/gdbsupport/format.cc index b515a95114e..43995edf453 100644 --- a/gdbsupport/format.cc +++ b/gdbsupport/format.cc @@ -111,6 +111,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions, int seen_big_l = 0, seen_h = 0, seen_big_h = 0; int seen_big_d = 0, seen_double_big_d = 0; int seen_size_t = 0; + int seen_ptrdiff_t = 0; int bad = 0; int n_int_args = 0; bool seen_i64 = false; @@ -224,6 +225,11 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions, seen_size_t = 1; f++; break; + case 't': + /* For ptrdiff_t. */ + seen_ptrdiff_t = 1; + f++; + break; case 'I': /* Support the Windows '%I64' extension, because an earlier call to format_pieces might have converted %lld @@ -257,6 +263,8 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions, case 'i': if (seen_size_t) this_argclass = size_t_arg; + else if (seen_ptrdiff_t) + this_argclass = ptrdiff_t_arg; else if (lcount == 0) this_argclass = int_arg; else if (lcount == 1) @@ -334,7 +342,8 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions, if (lcount > 1 || seen_h || seen_big_h || seen_big_h || seen_big_d || seen_double_big_d || seen_size_t - || seen_prec || seen_zero || seen_space || seen_plus) + || seen_ptrdiff_t || seen_prec || seen_zero || seen_space + || seen_plus) bad = 1; this_argclass = value_arg; diff --git a/gdbsupport/format.h b/gdbsupport/format.h index 91bcf1db55a..ced10e46a71 100644 --- a/gdbsupport/format.h +++ b/gdbsupport/format.h @@ -36,7 +36,7 @@ enum argclass { literal_piece, - int_arg, long_arg, long_long_arg, size_t_arg, ptr_arg, + int_arg, long_arg, long_long_arg, size_t_arg, ptrdiff_t_arg, ptr_arg, string_arg, wide_string_arg, wide_char_arg, double_arg, long_double_arg, dec32float_arg, dec64float_arg, dec128float_arg,