/* PR tree-optimization/91183 - strlen of a strcpy result with a conditional source not folded Runtime test to verify that multibyte stores are handled correctly. { dg-do run } { dg-options "-O2 -Wall" } */ #include "strlenopt.h" #define CHAR_BIT __CHAR_BIT__ typedef __UINT16_TYPE__ uint16_t; typedef __UINT32_TYPE__ uint32_t; #define NOIPA __attribute__ ((noclone, noinline, noipa)) /* Prevent the optimizer from detemining invariants from prior tests. */ NOIPA void terminate (void) { __builtin_abort (); } #define VERIFY(expr, str) \ do { \ const unsigned expect = strlen (str); \ const unsigned len = strlen (expr); \ if (len != expect) \ { \ __builtin_printf ("line %i: strlen(%s) == %u failed: " \ "got %u with a = \"%.*s\"\n", \ __LINE__, #expr, expect, len, \ (int)sizeof a, a); \ terminate (); \ } \ if (memcmp (a, str, expect + 1)) \ { \ __builtin_printf ("line %i: expected string \"%s\", " \ "got a = \"%.*s\"\n", \ __LINE__, str, (int)sizeof a, a); \ terminate (); \ } \ } while (0) #define ELT(s, i) ((s "\0\0\0\0")[i]) #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # define I16(s) (((uint16_t)ELT (s, 0) << 8) + (uint16_t)ELT (s, 1)) # define I32(s) \ (((uint32_t)ELT (s, 0) << 24) \ + ((uint32_t)ELT (s, 1) << 16) \ + ((uint32_t)ELT (s, 2) << 8) \ + (uint32_t)ELT (s, 3)) #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ # define I16(s) (((uint16_t)ELT (s, 1) << 8) + (uint16_t)ELT (s, 0)) # define I32(s) \ (((uint32_t)ELT (s, 3) << 24) \ + ((uint32_t)ELT (s, 2) << 16) \ + ((uint32_t)ELT (s, 1) << 8) \ + (uint32_t)ELT (s, 0)) #endif char a[32]; NOIPA void i16_1 (void) { *(uint16_t*)a = I16 ("12"); *(uint16_t*)(a + 2) = I16 ("3"); VERIFY (a, "123"); *(uint16_t*)(a + 1) = I16 ("23"); VERIFY (a, "123"); *(uint16_t*)(a) = I16 ("12"); VERIFY (a, "123"); *(uint16_t*)(a + 1) = I16 ("2"); VERIFY (a, "12"); *(uint16_t*)(a + 3) = I16 ("45"); *(uint16_t*)(a + 2) = I16 ("34"); VERIFY (a, "12345"); } NOIPA void i16_2 (void) { strcpy (a, "12"); strcat (a, "34"); *(uint16_t*)a = I16 ("12"); VERIFY (a, "1234"); *(uint16_t*)(a + 1) = I16 ("12"); VERIFY (a, "1124"); *(uint16_t*)(a + 2) = I16 ("12"); VERIFY (a, "1112"); *(uint16_t*)(a + 3) = I16 ("12"); VERIFY (a, "11112"); *(uint16_t*)(a + 4) = I16 ("12"); VERIFY (a, "111112"); } NOIPA void i32_1 (void) { *(uint32_t*)a = I32 ("1234"); VERIFY (a, "1234"); *(uint32_t*)(a + 1) = I32 ("2345"); VERIFY (a, "12345"); } NOIPA void i32_2 (void) { strcpy (a, "12"); strcat (a, "34"); *(uint32_t*)a = I32 ("1234"); VERIFY (a, "1234"); *(uint32_t*)(a + 4) = I32 ("567"); VERIFY (a, "1234567"); *(uint32_t*)(a + 7) = I32 ("89\0"); VERIFY (a, "123456789"); *(uint32_t*)(a + 3) = I32 ("4567"); VERIFY (a, "123456789"); *(uint32_t*)(a + 2) = I32 ("3456"); VERIFY (a, "123456789"); *(uint32_t*)(a + 1) = I32 ("2345"); VERIFY (a, "123456789"); } NOIPA void i32_3 (void) { strcpy (a, "1234"); strcat (a, "5678"); *(uint32_t*)a = I32 ("1234"); VERIFY (a, "12345678"); *(uint32_t*)(a + 1) = I32 ("234"); VERIFY (a, "1234"); *(uint32_t*)(a + 2) = I32 ("3456"); VERIFY (a, "12345678"); *(uint32_t*)(a + 3) = I32 ("4567"); VERIFY (a, "12345678"); *(uint32_t*)(a + 4) = I32 ("5678"); VERIFY (a, "12345678"); *(uint32_t*)(a + 5) = I32 ("6789"); VERIFY (a, "123456789"); *(uint32_t*)(a + 6) = I32 ("789A"); VERIFY (a, "123456789A"); } volatile int vzero = 0; NOIPA void i32_4 (void) { strcpy (a, "1234"); strcat (a, "5678"); *(uint32_t*)a = vzero ? I32 ("1\0\0\0") : I32 ("1234"); VERIFY (a, "12345678"); *(uint32_t*)a = vzero ? I32 ("12\0\0") : I32 ("1234"); VERIFY (a, "12345678"); *(uint32_t*)a = vzero ? I32 ("123\0") : I32 ("1234"); VERIFY (a, "12345678"); *(uint32_t*)a = vzero ? I32 ("1234") : I32 ("1234"); VERIFY (a, "12345678"); *(uint32_t*)a = vzero ? I32 ("1235") : I32 ("1234"); VERIFY (a, "12345678"); *(uint32_t*)a = vzero ? I32 ("1234") : I32 ("123\0"); VERIFY (a, "123"); *(uint32_t*)(a + 3) = vzero ? I32 ("456\0") : I32 ("4567"); VERIFY (a, "12345678"); } int main () { memset (a, 0, sizeof a); i16_1 (); memset (a, 0, sizeof a); i16_2 (); memset (a, 0, sizeof a); i32_1 (); memset (a, 0, sizeof a); i32_2 (); memset (a, 0, sizeof a); i32_3 (); memset (a, 0, sizeof a); i32_4 (); }