Mercurial > hg > CbC > CbC_gcc
diff gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c Fri Oct 27 22:46:09 2017 +0900 @@ -0,0 +1,296 @@ +/* Test to verify that the return value of calls to __builtin_sprintf + is not folded if the call isn't fully specified, even if it would + otherwise produce a known number of bytes on output, and that if + the return value is in a known range the range is not made + available to subsequent passes and doesn't affect branching and + the removal of code. + The test is compiled with warnings disabled to make sure the absence + of optimizations does not depend on the presence of warnings. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fprintf-return-value -fdump-tree-optimized -w" } */ + +#ifndef LINE +# define LINE 0 +#endif + +#define INT_MAX __INT_MAX__ +#define INT_MIN (-INT_MAX - 1) + +#define LONG_MAX __LONG_MAX__ +#define LONG_MIN (-LONG_MAX - 1) + +char *buf; +char buf8k [8192]; + +#define concat(a, b) a ## b +#define CAT(a, b) concat (a, b) + +/* Calls to this function must not be eliminated. */ +void must_not_eliminate (void); + +#define EQL(expect, size, fmt, ...) \ + void __attribute__ ((noinline, noclone)) \ + CAT (test_on_line_, __LINE__)(void) \ + { \ + if (!LINE || LINE == __LINE__) \ + { \ + char *dst = size < 0 ? buf : buf8k + sizeof buf8k - size; \ + int result = __builtin_sprintf (dst, fmt, __VA_ARGS__); \ + if (result != expect) \ + must_not_eliminate (); \ + } \ + } + +/* Verify that the return value or range or return values from the call + to the formatted function is not treated as a constant or made available + to subsequent optimization passes. */ +#define RNG(min, max, size, fmt, ...) \ + void __attribute__ ((noinline, noclone)) \ + CAT (test_on_line_, __LINE__)(void) \ + { \ + if (!LINE || LINE == __LINE__) \ + { \ + char *dst = size < 0 ? buf : buf8k + sizeof buf8k - size; \ + int result = __builtin_sprintf (dst, fmt, __VA_ARGS__); \ + if (result < min || max < result) \ + must_not_eliminate (); \ + } \ + } + +typedef __SIZE_TYPE__ size_t; + +volatile int i; +volatile unsigned u; +volatile long li; +volatile unsigned long lu; +volatile size_t sz; +volatile char *str; + +volatile double d; +volatile long double ld; + +/* Verify that overflowing the destination object disables the return + value optimization. */ +EQL (0, 0, "%c", ' '); +EQL (0, 0, "%c", i) +EQL (0, 0, "%-s", ""); + +EQL (1, 1, "%c", 'x'); +EQL (1, 1, "%-s", "x"); + +EQL (1, 2, "%c", 'x'); + +EQL (4, 4, "%4c", 'x'); + +/* Verify that exceeding the environmental limit of 4095 bytes for + a single conversion specification disables the return value + folding. */ +EQL ( 4096, sizeof buf8k, "%4096c", 'x'); + +EQL (INT_MAX, -1, "%*c", INT_MAX, 'x'); + +EQL ( 4096, sizeof buf8k, "%4096.4094f", 1.0); +EQL ( 4096, sizeof buf8k, "%.4094f", 1.0); +EQL ( 4097, sizeof buf8k, "%.4095f", 1.0); + +enum { imax2 = (INT_MAX / 2) * 2 }; +EQL (imax2, -1, "%*c%*c", INT_MAX / 2, 'x', INT_MAX / 2, 'y'); + +/* Verify that range information for calls that overflow the destination + isn't available. + + +-- lower bound of the tested range + | +-- upper bound of the tested range + | | +-- size of destination buffer + | | | +-- format string + | | | | +-- argument(s) + | | | | | + V V V V V */ +RNG (0, 0, 0, "%hhi", i) +RNG (0, 0, 1, "%hhi", i) +RNG (0, 1, 1, "%hhi", i) +RNG (0, 0, 2, "%hhi", i) +RNG (0, 1, 2, "%hhi", i) +RNG (0, 2, 2, "%hhi", i) +RNG (0, 0, 3, "%hhi", i) +RNG (0, 1, 3, "%hhi", i) +RNG (0, 2, 3, "%hhi", i) +RNG (0, 3, 3, "%hhi", i) +RNG (0, 0, 4, "%hhi", i) +RNG (0, 1, 4, "%hhi", i) +RNG (0, 2, 4, "%hhi", i) +RNG (0, 3, 4, "%hhi", i) +RNG (0, 4, 4, "%hhi", i) + +RNG (0, 0, 0, "%hhu", i) +RNG (0, 0, 1, "%hhu", i) +RNG (0, 1, 1, "%hhu", i) +RNG (0, 0, 2, "%hhu", i) +RNG (0, 1, 2, "%hhu", i) +RNG (0, 2, 2, "%hhu", i) +RNG (0, 0, 3, "%hhu", i) +RNG (0, 1, 3, "%hhu", i) +RNG (0, 2, 3, "%hhu", i) +RNG (0, 3, 3, "%hhu", i) + +RNG (0, 0, 0, "%i", i) + +RNG (0, 0, 1, "%i", i) +RNG (0, 1, 1, "%i", i) + +RNG (0, 0, 2, "%i", i) +RNG (0, 1, 2, "%i", i) +RNG (0, 2, 2, "%i", i) + +RNG (0, 0, 3, "%i", i) +RNG (0, 1, 3, "%i", i) +RNG (0, 2, 3, "%i", i) +RNG (0, 3, 3, "%i", i) + +RNG (0, 0, 4, "%i", i) +RNG (0, 1, 4, "%i", i) +RNG (0, 2, 4, "%i", i) +RNG (0, 3, 4, "%i", i) +RNG (0, 4, 4, "%i", i) + +RNG (0, 0, 5, "%i", i) +RNG (0, 1, 5, "%i", i) +RNG (0, 2, 5, "%i", i) +RNG (0, 3, 5, "%i", i) +RNG (0, 4, 5, "%i", i) +RNG (0, 5, 5, "%i", i) + +RNG (0, 0, 6, "%i", i) +RNG (0, 1, 6, "%i", i) +RNG (0, 2, 6, "%i", i) +RNG (0, 3, 6, "%i", i) +RNG (0, 4, 6, "%i", i) +RNG (0, 5, 6, "%i", i) +RNG (0, 6, 6, "%i", i) + +RNG (0, 0, 7, "%i", i) +RNG (0, 1, 7, "%i", i) +RNG (0, 2, 7, "%i", i) +RNG (0, 3, 7, "%i", i) +RNG (0, 4, 7, "%i", i) +RNG (0, 5, 7, "%i", i) +RNG (0, 6, 7, "%i", i) + +RNG (4, 4, 32, "%i", i) +RNG (4, 4, 32, "%u", u) +RNG (4, 4, 32, "%li", li) +RNG (4, 4, 32, "%lu", lu) +RNG (4, 4, 32, "%zu", sz) + +/* Exercise bug 78586. */ +RNG (4, 4, 32, "%lu", (unsigned long)i) +RNG (4, 4, 32, "%lu", (unsigned long)u) +RNG (4, 4, 32, "%lu", (unsigned long)li) +RNG (4, 4, 32, "%lu", (unsigned long)lu) +RNG (4, 4, 32, "%lu", (unsigned long)sz) + + +#if __SIZEOF_INT__ == 4 + +/* A 32-bit int takes up at most 11 bytes (-2147483648) not including + the terminating nul. */ +RNG (0, 7, 7, "%i", i) + +RNG (0, 0, 8, "%i", i) +RNG (0, 1, 8, "%i", i) +RNG (0, 2, 8, "%i", i) +RNG (0, 3, 8, "%i", i) +RNG (0, 4, 8, "%i", i) +RNG (0, 5, 8, "%i", i) +RNG (0, 6, 8, "%i", i) +RNG (0, 7, 8, "%i", i) +RNG (0, 8, 8, "%i", i) + +RNG (0, 0, 9, "%i", i) +RNG (0, 1, 9, "%i", i) +RNG (0, 2, 9, "%i", i) +RNG (0, 3, 9, "%i", i) +RNG (0, 4, 9, "%i", i) +RNG (0, 5, 9, "%i", i) +RNG (0, 6, 9, "%i", i) +RNG (0, 7, 9, "%i", i) +RNG (0, 8, 9, "%i", i) +RNG (0, 9, 9, "%i", i) + +RNG (0, 0, 10, "%i", i) +RNG (0, 1, 10, "%i", i) +RNG (0, 2, 10, "%i", i) +RNG (0, 3, 10, "%i", i) +RNG (0, 4, 10, "%i", i) +RNG (0, 5, 10, "%i", i) +RNG (0, 6, 10, "%i", i) +RNG (0, 7, 10, "%i", i) +RNG (0, 8, 10, "%i", i) +RNG (0, 9, 10, "%i", i) +RNG (0, 10, 10, "%i", i) + +#endif + +/* Verify that the output of a "%a" directive with no precision is not + considered constant or within a known range (the number of digits + after the decimal point is unspecified in this case). The hardcoded + ranges correspond to Glibc values. */ +RNG (6, 6, 7, "%a", 0.0) /* Glibc output: "0x0p+0" */ +RNG (6, 6, 7, "%a", d) +RNG (6, 6, 7, "%.4096a", d) + +RNG (6, 6, 7, "%La", 0.0L) /* Glibc output: "0x0p+0" */ +RNG (6, 6, 7, "%La", ld) +RNG (6, 6, 7, "%.4096La", ld) + +/* Verify that the pound flag with unknown precision prevents the %g + directive from trimming trailing zeros as it otherwise does. As + a consequence, the result must be assumed to be as large as + precision. */ +RNG (1, 315, 316, "%#.*g", i, d); +RNG (1, 4095, 4096, "%#.*g", i, d); +RNG (1, 4095, 4096, "%#.*g", i, 0.0); + +/* Verify that the result of formatting an unknown string isn't optimized + into a non-negative range. The string could be longer that 4,095 bytes, + resulting in the formatting function having undefined behavior (and + returning a negative value as Glibc can for some directives). */ +RNG (0, INT_MAX, -1, "%-s", str); + +/* Verify the result of a conditional expression involving a string + literal and an unknown string isn't optimized. */ +RNG (0, 1, 4, "%-s", i ? str : "123"); +RNG (0, 1, 4, "%-s", i ? "123" : str); + +/* Verfy that the output involving wide strings is not optimized + (the output is actually bounded by a function of MB_LEN_MAX + which should be at least 6 to accommodate UTF-8 but this isn't + implemented yet). */ +RNG (0, 5, 7, "%ls", L"1"); +RNG (0, 6, 8, "%s%ls", "1", L"2"); + +/* Verify that no call to abort has been eliminated and that each call + is at the beginning of a basic block (and thus the result of a branch). + This latter test tries to verify that the test preceding the call to + the must_not_eliminate() function has not been eliminated either. + + The expected output looks something like this: + + <bb 2>: + result_3 = __builtin_sprintf (&MEM[(void *)&buf8k + 8192B], "%c", 32); + if (result_3 != 0) + goto <bb 3>; [50.0%] [count: INV] + else + goto <bb 4>; [50.0%] [count: INV] + + <bb 3>[50.0%] [count: INV]: + must_not_eliminate (); + +*/ + +/* Only conditional calls to must_not_eliminate must be made (with + any probability): + { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\] \\\[count: \[0-9INV\]*\\\]:\n *must_not_eliminate" 127 "optimized" { target { ilp32 || lp64 } } } } + { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\] \\\[count: \[0-9INV\]*\\\]:\n *must_not_eliminate" 96 "optimized" { target { { ! ilp32 } && { ! lp64 } } } } } + No unconditional calls to abort should be made: + { dg-final { scan-tree-dump-not ";\n *must_not_eliminate" "optimized" } } */