/* Verify that sprintf calls with arrays or struct of arrays don't cause -Wrestrict false positives. { dg-do compile } { dg-options "-O2 -Wall -Wrestrict -ftrack-macro-expansion=0" } */ #define sprintf(d, f, ...) (sprintf (d, f, __VA_ARGS__), sink (d)) extern void sink (void*, ...); extern int (sprintf) (char*, const char*, ...); extern char ca[][2][8]; void test_array_of_arrays (void) { sprintf (ca[0][0], "%s", ca[0][0]); // { dg-warning "-Wrestrict" } sprintf (ca[0][0], "%s", ca[0][1]); sprintf (ca[0][0], "%s", ca[1][0]); sprintf (ca[0][0], "%s", ca[1][1]); sprintf (ca[0][1], "%s", ca[0][0]); sprintf (ca[0][1], "%s", ca[0][1]); // { dg-warning "-Wrestrict" } sprintf (ca[0][1], "%s", ca[1][0]); sprintf (ca[0][1], "%s", ca[1][1]); sprintf (ca[1][0], "%s", ca[0][0]); sprintf (ca[1][0], "%s", ca[0][1]); sprintf (ca[1][0], "%s", ca[1][0]); // { dg-warning "-Wrestrict" } sprintf (ca[1][0], "%s", ca[1][1]); sprintf (ca[1][1], "%s", ca[0][0]); sprintf (ca[1][1], "%s", ca[0][1]); sprintf (ca[1][1], "%s", ca[1][0]); sprintf (ca[1][1], "%s", ca[1][1]); // { dg-warning "-Wrestrict" } } struct A { char a[2][2][8]; char b[2][2][8]; char c[2][2][8]; }; extern struct A aa[][2]; void test_array_of_structs (void) { // Verify that calls with the same elements of the same array trigger // warnings as expected. sprintf (aa[0][0].a[0][0], "%s", aa[0][0].a[0][0]); // { dg-warning "-Wrestrict" } sprintf (aa[0][0].a[0][1], "%s", aa[0][0].a[0][1]); // { dg-warning "-Wrestrict" } sprintf (aa[0][0].a[1][0], "%s", aa[0][0].a[1][0]); // { dg-warning "-Wrestrict" } sprintf (aa[0][0].a[1][1], "%s", aa[0][0].a[1][1]); // { dg-warning "-Wrestrict" } sprintf (aa[0][1].a[0][0], "%s", aa[0][1].a[0][0]); // { dg-warning "-Wrestrict" } sprintf (aa[0][1].a[0][1], "%s", aa[0][1].a[0][1]); // { dg-warning "-Wrestrict" } sprintf (aa[0][1].a[1][0], "%s", aa[0][1].a[1][0]); // { dg-warning "-Wrestrict" } sprintf (aa[0][1].a[1][1], "%s", aa[0][1].a[1][1]); // { dg-warning "-Wrestrict" } sprintf (aa[1][0].a[0][0], "%s", aa[1][0].a[0][0]); // { dg-warning "-Wrestrict" } sprintf (aa[1][0].a[0][1], "%s", aa[1][0].a[0][1]); // { dg-warning "-Wrestrict" } sprintf (aa[1][0].a[1][0], "%s", aa[1][0].a[1][0]); // { dg-warning "-Wrestrict" } sprintf (aa[1][0].a[1][1], "%s", aa[1][0].a[1][1]); // { dg-warning "-Wrestrict" } sprintf (aa[1][1].a[0][0], "%s", aa[1][1].a[0][0]); // { dg-warning "-Wrestrict" } sprintf (aa[1][1].a[0][1], "%s", aa[1][1].a[0][1]); // { dg-warning "-Wrestrict" } sprintf (aa[1][1].a[1][0], "%s", aa[1][1].a[1][0]); // { dg-warning "-Wrestrict" } sprintf (aa[1][1].a[1][1], "%s", aa[1][1].a[1][1]); // { dg-warning "-Wrestrict" } #define NOWARN() // Exhaustively verify that calls with different elements of the same // array don't cause false positives. #undef NOWARN #define NOWARN(D, S) \ sprintf (D[0][0], "%s", S[0][0]); \ sprintf (D[0][0], "%s", S[0][1]); \ sprintf (D[0][0], "%s", S[1][0]); \ sprintf (D[0][0], "%s", S[1][1]); \ sprintf (D[0][1], "%s", S[0][0]); \ sprintf (D[0][1], "%s", S[0][1]); \ sprintf (D[0][1], "%s", S[1][0]); \ sprintf (D[0][1], "%s", S[1][1]); \ sprintf (D[1][0], "%s", S[0][0]); \ sprintf (D[1][0], "%s", S[0][1]); \ sprintf (D[1][0], "%s", S[1][0]); \ sprintf (D[1][0], "%s", S[1][1]); \ sprintf (D[1][1], "%s", S[0][0]); \ sprintf (D[1][1], "%s", S[0][1]); \ sprintf (D[1][1], "%s", S[1][0]); \ sprintf (D[1][1], "%s", S[1][1]) NOWARN (aa[0][0].a, aa[0][1].a); NOWARN (aa[0][0].a, aa[1][0].a); NOWARN (aa[0][0].a, aa[1][1].a); NOWARN (aa[0][1].a, aa[0][0].a); NOWARN (aa[0][1].a, aa[1][0].a); NOWARN (aa[0][1].a, aa[1][1].a); NOWARN (aa[1][0].a, aa[0][0].a); NOWARN (aa[1][0].a, aa[0][1].a); NOWARN (aa[1][0].a, aa[1][1].a); #define NOWARN_MEM(M1, M2) \ NOWARN (aa[0][0].M1, aa[0][0].M2); \ NOWARN (aa[0][0].M1, aa[0][1].M2); \ NOWARN (aa[0][0].M1, aa[1][0].M2); \ NOWARN (aa[0][0].M1, aa[1][1].M2) NOWARN_MEM (a, b); NOWARN_MEM (a, c); NOWARN_MEM (b, a); NOWARN_MEM (b, c); NOWARN_MEM (c, a); NOWARN_MEM (c, b); }