blob: 7981818b3be9f5e1c75f59b540a8a6a8a0db09e9 [file] [log] [blame]
/* Test to verify that a function that returns either the address
of a local variable or a non-local via a MAX_EXPR or MIN_EXPR
doesn't return null when the result of the expression is
the latter. */
#define NOIPA __attribute__ ((noclone, noinline, noipa))
#define A(expr) \
((expr) \
? (void)0 \
: (__builtin_printf ("assertion failed on line %i: %s\n", \
__LINE__, #expr), \
__builtin_abort ()))
typedef __UINTPTR_TYPE__ uintptr_t;
/* Return a bigger value than P. The address still points (just
past) the local variable pointed to by P so the caller does
return the address of a local variable but that's hidden from
GCC by the attribute and the point of the test is to verify
that the address in the return statement in the caller isn't
replaced by null when GCC cannot prove the address doesn't
reference a non-local variable. */
NOIPA char* get_max_2 (char *p)
{
return p + 1;
}
NOIPA char* get_max_3 (char *p, char *q)
{
return p < q ? q + 1 : p + 1;
}
/* Analogous to the above. The expressions are undefined because
they form an address prior to the beginning of the object but
it's hidden from GCC by the attributes. */
NOIPA char* get_min_2 (char *p)
{
return p - 1;
}
NOIPA char* get_min_3 (char *p, char *q)
{
return p < q ? p - 1 : q - 1;
}
NOIPA void* test_max_2 (void)
{
char c;
char *p = get_max_2 (&c);
void *q = p > &c ? p : &c; /* MAX_EXPR */
return q;
}
NOIPA void* test_max_3 (void)
{
char c;
char d;
char *p = get_max_3 (&c, &d);
void *q = p < &c ? &c < &d ? &d : &c : p;
return q;
}
NOIPA void* test_min_2 (void)
{
char c;
char *p = get_min_2 (&c);
void *q = p < &c ? p : &c; /* MIN_EXPR" */
return q;
}
NOIPA void* test_min_3 (void)
{
char c;
char d;
char *p = get_min_3 (&c, &d);
void *q = p > &c ? &c > &d ? &d : &c : p;
return q;
}
NOIPA void* test_min_3_phi (int i)
{
char a, b;
char *p0 = &a;
char *p1 = &b;
char *p2 = get_min_3 (&a, &b);
char *p3 = get_min_3 (&a, &b);
char *p4 = p2 < p0 ? p2 : p0;
char *p5 = p3 < p1 ? p3 : p1;
__builtin_printf ("%p %p %p %p\n", p2, p3, p4, p5);
if (i == 1)
return p4;
else
return p5;
}
int main ()
{
A (0 != test_max_2 ());
A (0 != test_max_3 ());
A (0 != test_min_2 ());
A (0 != test_min_3 ());
A (0 != test_min_3_phi (0));
}