summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/strlenopt-84.c
blob: d6102b6e6f572c45965dfdf44ec2fdf80f8a1206 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* PR tree-optimization/83821 - local aggregate initialization defeats
   strlen optimization
   Verify that stores that overwrite an interior nul are correctly
   reflected in strlen results.
   { dg-do run }
   { dg-options "-O2 -Wall" } */

#define false (0 == 1)
#define true (0 == 0)
#define assert(e)							\
  ((e) ? (void)0 : (__builtin_printf ("assertion failed on line %i\n",	\
				      __LINE__), __builtin_abort ()))

#define ATTR(...) __attribute__ ((__VA_ARGS__))

static inline int ATTR (always_inline)
assign_and_get_length (char *p, _Bool clear)
{
  p[0] = 'a';

  if (clear)
    p[1] = 0;

  p[2] = 'c';

  if (clear)
    p[3] = 0;

  p[1] = 'b';

  return __builtin_strlen (p);
}

ATTR (noipa) void array_get_length (void)
{
  char a[4];
  unsigned n = assign_and_get_length (a, true);
  assert (n == 3);
}

ATTR (noipa) void clear_array_get_length (void)
{
  char a[4] = { };
  unsigned n = assign_and_get_length (a, false);
  assert (n == 3);
}

ATTR (noipa) void calloc_get_length (void)
{
  char *p = __builtin_calloc (5, 1);
  unsigned n = assign_and_get_length (p, false);
  assert (n == 3);
}

ATTR (noipa) void malloc_get_length (void)
{
  char *p = __builtin_malloc (5);
  unsigned n = assign_and_get_length (p, true);
  assert (n == 3);
}

ATTR (noipa) void vla_get_length (int n)
{
  char a[n];
  unsigned len = assign_and_get_length (a, true);
  assert (len == 3);
}


static inline void ATTR (always_inline)
assign_and_test_length (char *p, _Bool clear)
{
  p[0] = 'a';

  if (clear)
    p[1] = 0;

  p[2] = 'c';

  if (clear)
    p[3] = 0;

  unsigned n0 =  __builtin_strlen (p);

  p[1] = 'b';

  unsigned n1 =  __builtin_strlen (p);
  assert (n0 != n1);
}

ATTR (noipa) void array_test_length (void)
{
  char a[4];
  assign_and_test_length (a, true);
}

ATTR (noipa) void clear_array_test_length (void)
{
  char a[4] = { };
  assign_and_test_length (a, false);
}

ATTR (noipa) void calloc_test_length (void)
{
  char *p = __builtin_calloc (5, 1);
  assign_and_test_length (p, false);
}

ATTR (noipa) void malloc_test_length (void)
{
  char *p = __builtin_malloc (5);
  assign_and_test_length (p, true);
}

ATTR (noipa) void vla_test_length (int n)
{
  char a[n];
  assign_and_test_length (a, true);
}

int main (void)
{
  array_get_length ();
  clear_array_get_length ();
  calloc_get_length ();
  malloc_get_length ();
  vla_get_length (4);

  array_test_length ();
  clear_array_test_length ();
  calloc_test_length ();
  malloc_test_length ();
  vla_test_length (4);
}