diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 059cf2e8f79f440a8396f7a1acbb1597824876d9..1be4ea02992c90c6b923239a1c6c60b32158ef9e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3143,6 +3143,7 @@ else BUILD_CPPLIB = $(CPPLIB) $(LIBIBERTY) build/genmatch$(build_exeext): BUILD_LIBDEPS += $(LIBINTL_DEP) $(LIBICONV_DEP) build/genmatch$(build_exeext): BUILD_LIBS += $(LIBINTL) $(LIBICONV) +build/genmatch.o: BUILD_CPPFLAGS += -DGENMATCH_SELFTESTS endif build/genmatch$(build_exeext) : $(BUILD_CPPLIB) \ diff --git a/gcc/config.in b/gcc/config.in index 7fcabbe5061d6908cbc4de0f356ccd32995d9905..3fc4666d60b56ecc0b7832fb340a49456773e374 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1018,6 +1018,13 @@ #endif +/* Define to 1 if we found a declaration for 'fmemopen', otherwise define to + 0. */ +#ifndef USED_FOR_TARGET +#undef HAVE_DECL_FMEMOPEN +#endif + + /* Define to 1 if we found a declaration for 'fprintf_unlocked', otherwise define to 0. */ #ifndef USED_FOR_TARGET diff --git a/gcc/configure b/gcc/configure index 5acc42c1e4d931f32655a0c272a6917dfdb86e4f..47c58036530f7f689fe6e0e183ddee4f2e2739b4 100755 --- a/gcc/configure +++ b/gcc/configure @@ -12084,7 +12084,7 @@ for ac_func in getenv atol atoll asprintf sbrk abort atof getcwd getwd \ madvise stpcpy strnlen strsignal strverscmp \ strtol strtoul strtoll strtoull setenv unsetenv \ errno snprintf vsnprintf vasprintf malloc realloc calloc \ - free getopt clock getpagesize ffs clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked + free getopt clock getpagesize ffs fmemopen clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked do ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5 diff --git a/gcc/configure.ac b/gcc/configure.ac index 23f4884eff9e44b29a3b1f768ff7fed27676913e..dc8346a7b823722fe58fcf68d9bcdd88fc341aa9 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1629,7 +1629,7 @@ gcc_AC_CHECK_DECLS(getenv atol atoll asprintf sbrk abort atof getcwd getwd \ madvise stpcpy strnlen strsignal strverscmp \ strtol strtoul strtoll strtoull setenv unsetenv \ errno snprintf vsnprintf vasprintf malloc realloc calloc \ - free getopt clock getpagesize ffs gcc_UNLOCKED_FUNCS, , ,[ + free getopt clock getpagesize ffs fmemopen gcc_UNLOCKED_FUNCS, , ,[ #include "ansidecl.h" #include "system.h"]) diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc index 1acd9216b3b0e7d5a97ec699f4ee6293e8197086..170bf6162b5d6967ed47b3d089db3af4017fd0a8 100644 --- a/gcc/genmatch.cc +++ b/gcc/genmatch.cc @@ -585,6 +585,138 @@ diag_vfprintf (FILE *f, int err_no, const char *msg, va_list *ap) fprintf (f, "%s", q); } +#if defined(GENMATCH_SELFTESTS) && defined(HAVE_DECL_FMEMOPEN) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsuggest-attribute=format" + +static void +test_diag_vfprintf (const char *expected, const char *msg, ...) +{ + char buf[256]; + va_list ap; + FILE *f = fmemopen (buf, 256, "w"); + gcc_assert (f != NULL); + va_start (ap, msg); + diag_vfprintf (f, 0, msg, &ap); + va_end (ap); + fclose (f); + gcc_assert (strcmp (buf, expected) == 0); +} + +#pragma GCC diagnostic pop + +static void +genmatch_diag_selftests (void) +{ + /* Verify that plain text is passed through unchanged. */ + test_diag_vfprintf ("unformatted", "unformatted"); + + /* Verify various individual format codes, in the order listed in the + comment for pp_format above. For each code, we append a second + argument with a known bit pattern (0x12345678), to ensure that we + are consuming arguments correctly. */ + test_diag_vfprintf ("-27 12345678", "%d %x", -27, 0x12345678); + test_diag_vfprintf ("-5 12345678", "%i %x", -5, 0x12345678); + test_diag_vfprintf ("10 12345678", "%u %x", 10, 0x12345678); + test_diag_vfprintf ("17 12345678", "%o %x", 15, 0x12345678); + test_diag_vfprintf ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678); + test_diag_vfprintf ("-27 12345678", "%ld %x", (long)-27, 0x12345678); + test_diag_vfprintf ("-5 12345678", "%li %x", (long)-5, 0x12345678); + test_diag_vfprintf ("10 12345678", "%lu %x", (long)10, 0x12345678); + test_diag_vfprintf ("17 12345678", "%lo %x", (long)15, 0x12345678); + test_diag_vfprintf ("cafebabe 12345678", "%lx %x", (long)0xcafebabe, + 0x12345678); + test_diag_vfprintf ("-27 12345678", "%lld %x", (long long)-27, 0x12345678); + test_diag_vfprintf ("-5 12345678", "%lli %x", (long long)-5, 0x12345678); + test_diag_vfprintf ("10 12345678", "%llu %x", (long long)10, 0x12345678); + test_diag_vfprintf ("17 12345678", "%llo %x", (long long)15, 0x12345678); + test_diag_vfprintf ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe, + 0x12345678); + test_diag_vfprintf ("-27 12345678", "%wd %x", HOST_WIDE_INT_C (-27), + 0x12345678); + test_diag_vfprintf ("-5 12345678", "%wi %x", HOST_WIDE_INT_C (-5), + 0x12345678); + test_diag_vfprintf ("10 12345678", "%wu %x", HOST_WIDE_INT_UC (10), + 0x12345678); + test_diag_vfprintf ("17 12345678", "%wo %x", HOST_WIDE_INT_C (15), + 0x12345678); + test_diag_vfprintf ("0xcafebabe 12345678", "%wx %x", + HOST_WIDE_INT_C (0xcafebabe), 0x12345678); + test_diag_vfprintf ("-27 12345678", "%zd %x", (ssize_t)-27, 0x12345678); + test_diag_vfprintf ("-5 12345678", "%zi %x", (ssize_t)-5, 0x12345678); + test_diag_vfprintf ("10 12345678", "%zu %x", (size_t)10, 0x12345678); + test_diag_vfprintf ("17 12345678", "%zo %x", (size_t)15, 0x12345678); + test_diag_vfprintf ("cafebabe 12345678", "%zx %x", (size_t)0xcafebabe, + 0x12345678); + test_diag_vfprintf ("-27 12345678", "%td %x", (ptrdiff_t)-27, 0x12345678); + test_diag_vfprintf ("-5 12345678", "%ti %x", (ptrdiff_t)-5, 0x12345678); + test_diag_vfprintf ("10 12345678", "%tu %x", (ptrdiff_t)10, 0x12345678); + test_diag_vfprintf ("17 12345678", "%to %x", (ptrdiff_t)15, 0x12345678); + test_diag_vfprintf ("1afebabe 12345678", "%tx %x", (ptrdiff_t)0x1afebabe, + 0x12345678); + test_diag_vfprintf ("1.000000 12345678", "%f %x", 1.0, 0x12345678); + test_diag_vfprintf ("A 12345678", "%c %x", 'A', 0x12345678); + test_diag_vfprintf ("hello world 12345678", "%s %x", "hello world", + 0x12345678); + + /* Not nul-terminated. */ + char arr[5] = { '1', '2', '3', '4', '5' }; + test_diag_vfprintf ("123 12345678", "%.*s %x", 3, arr, 0x12345678); + test_diag_vfprintf ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678); + test_diag_vfprintf ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678); + + /* We can't test for %p; the pointer is printed in an implementation-defined + manner. */ + test_diag_vfprintf ("normal colored normal 12345678", + "normal %rcolored%R normal %x", + "error", 0x12345678); + + /* TODO: + %m: strerror(text->err_no) - does not consume a value *ap. */ + test_diag_vfprintf ("% 12345678", "%% %x", 0x12345678); + test_diag_vfprintf ("' 12345678", "%< %x", 0x12345678); + test_diag_vfprintf ("' 12345678", "%> %x", 0x12345678); + test_diag_vfprintf ("' 12345678", "%' %x", 0x12345678); + test_diag_vfprintf ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678); + test_diag_vfprintf ("abc 12345678", "%.3s %x", "abcdef", 0x12345678); + + /* Verify flag 'q'. */ + test_diag_vfprintf ("'foo' 12345678", "%qs %x", "foo", 0x12345678); + + /* Verify %Z. */ + int v[] = { 1, 2, 3 }; + test_diag_vfprintf ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678); + + int v2[] = { 0 }; + test_diag_vfprintf ("0 12345678", "%Z %x", v2, 1, 0x12345678); + + /* Verify that combinations work, along with unformatted text. */ + test_diag_vfprintf ("the quick brown fox jumps over the lazy dog", + "the %s %s %s jumps over the %s %s", + "quick", "brown", "fox", "lazy", "dog"); + test_diag_vfprintf ("item 3 of 7", "item %i of %i", 3, 7); + test_diag_vfprintf ("problem with 'bar' at line 10", + "problem with %qs at line %i", "bar", 10); + + /* Verified numbered args. */ + test_diag_vfprintf ("foo: second bar: first", + "foo: %2$s bar: %1$s", "first", "second"); + test_diag_vfprintf ("foo: 1066 bar: 1776", + "foo: %2$i bar: %1$i", 1776, 1066); + test_diag_vfprintf ("foo: second bar: 1776", + "foo: %2$s bar: %1$i", 1776, "second"); + test_diag_vfprintf ("foo: sec bar: 3360", + "foo: %3$.*2$s bar: %1$o", 1776, 3, "second"); + test_diag_vfprintf ("foo: seco bar: 3360", + "foo: %2$.4s bar: %1$o", 1776, "second"); +} +#else +static void +genmatch_diag_selftests (void) +{ +} +#endif + static bool #if GCC_VERSION >= 4001 __attribute__((format (gcc_diag, 5, 0))) @@ -6082,6 +6214,8 @@ main (int argc, char **argv) return 1; } + genmatch_diag_selftests (); + if (!s_include_file) s_include_file = s_header_file; diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc index 6f36d4a2015eff0070d5f5f37b011055ddaa0c2f..a3f369132dd0449470fb66309761baeab95986a5 100644 --- a/gcc/pretty-print.cc +++ b/gcc/pretty-print.cc @@ -3474,6 +3474,14 @@ test_pp_format () "foo: second bar: 1776", "foo: %2$s bar: %1$i", 1776, "second"); + assert_pp_format (SELFTEST_LOCATION, + "foo: sec bar: 3360", + "foo: %3$.*2$s bar: %1$o", + 1776, 3, "second"); + assert_pp_format (SELFTEST_LOCATION, + "foo: seco bar: 3360", + "foo: %2$.4s bar: %1$o", + 1776, "second"); } static void