blob: b537296779074a878a5325c6aff3f42ff74e1735 [file] [log] [blame]
/* PR tree-optimization/84468 - Inconsistent -Wstringop-truncation warnings
with -O2
{ dg-do compile }
{ dg-options "-O2 -Wstringop-truncation -ftrack-macro-expansion=0 -g" } */
#define strncpy __builtin_strncpy
struct A
{
char a[4];
};
void no_pred_succ_lit (struct A *p)
{
/* The following is folded early on, before the strncpy statement
has a basic block. Verify that the case is handled gracefully
(i.e., there's no assumption that the statement does have
a basic block). */
strncpy (p->a, "1234", sizeof p->a - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
}
/* Verify a strncpy call in a basic block with no predecessor or
successor. */
void no_pred_succ (struct A *p, const struct A *q)
{
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
}
/* Verify a strncpy call in a basic block with no successor. */
void no_succ (struct A *p, const struct A *q)
{
if (q->a)
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
}
/* Verify a strncpy call in a basic block with nul assignment in
a successor block. */
void succ (struct A *p, const struct A *q)
{
/* Verify that the assignment suppresses the warning for the conditional
strcnpy call. The conditional should be folded to true since the
address of an array can never be null (see bug 84470). */
if (q->a)
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */
p->a[sizeof p->a - 1] = 0;
}
void succ_2 (struct A *p, const struct A *q, int i)
{
/* Same as above but with a conditional that cannot be eliminated. */
if (i < 0)
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */
p->a[sizeof p->a - 1] = 0;
}
/* Verify a strncpy call in a basic block with nul assignment in
the next successor block. */
int next_succ (struct A *p, const struct A *q, int i, int j)
{
/* Same as above but with a nested conditionals with else clauses. */
if (i < 0)
{
if (j < 0)
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */
}
else
__builtin_strcpy (p->a, q->a);
p->a[sizeof p->a - 1] = 0;
return 0;
}
int next_succ_1 (struct A *p, const struct A *q, int i, int j)
{
/* Same as above but with a nested conditionals with else clauses. */
if (i < 0)
{
if (j < 0)
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */
else
strncpy (p->a, q->a, sizeof p->a - 2); /* { dg-bogus "\\\[-Wstringop-truncation" } */
}
p->a[sizeof p->a - 2] = 0;
return 1;
}
int next_succ_2 (struct A *p, const struct A *q, int i, int j)
{
/* Same as above but with a nested conditionals with else clauses. */
if (i < 0)
{
if (j < 0)
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-bogus "\\\[-Wstringop-truncation" } */
else
strncpy (p->a, q->a, sizeof p->a - 2); /* { dg-bogus "\\\[-Wstringop-truncation" } */
}
else
__builtin_strcpy (p->a, q->a);
p->a[sizeof p->a - 2] = 0;
return 2;
}
void cond_succ_warn (struct A *p, const struct A *q, int i)
{
/* Verify that a conditional assignment doesn't suppress the warning. */
strncpy (p->a, q->a, sizeof p->a - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
if (i < 0)
p->a[sizeof p->a - 1] = 0;
}
void cond_succ_nowarn (struct A *p, const struct A *q)
{
/* Verify that distinct but provably equivalent conditionals are
recognized and don't trigger the warning. */
if (p != q)
strncpy (p->a, q->a, sizeof p->a - 1);
if (p->a != q->a)
p->a[sizeof p->a - 1] = 0;
}