blob: e922888a4bfb1bc5594d869883f47fed69857769 [file] [log] [blame]
/* PR c/71924 - missing -Wreturn-local-addr returning alloca result
{ dg-do compile }
{ dg-options "-O2 -Wall" }
{ dg-require-effective-target alloca } */
#define ATTR(...) __attribute__ ((__VA_ARGS__))
typedef __INTPTR_TYPE__ intptr_t;
struct A { int a, b, c; };
struct B { int a, b, c[]; };
extern int g1[5], g2[5], g3[5], g4[5], g5[5];
void sink (void*, ...);
/* Verify that a pointer difference expression is handled correctly
even when converted to a pointer. */
ATTR (noipa) void*
return_local_diff_cst (void)
{
int a[5];
void *p = (void*)(&a[4] - &a[1]);
return p;
}
ATTR (noipa) void*
return_local_diff_var (int i, int j)
{
int a[5];
void *p = (void*)(&a[j] - &a[i]);
return p;
}
ATTR (noipa) void*
return_2_locals (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
void *p = i < 0 ? a : b;
return p; /* { dg-warning "function returns address of local" } */
}
/* Verify that returning the address of a local converted to intptr_t
is not diagnosed (see bug 90737 for a case the front-end gets wrong). */
ATTR (noipa) intptr_t
return_int_2_locals (int i)
{
int a[1];
int b[2];
void *p = i < 0 ? a : b;
return (intptr_t)p;
}
/* Verify that a conditional expression with a pointer first operand
is handled correctly. */
ATTR (noipa) void*
return_2_locals_ptrcond (void *q)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
void *p = q ? a : b;
return p; /* { dg-warning "function returns address of local" } */
}
/* Verify that a preincrement expression with a pointer operand is
handled correctly. */
ATTR (noipa) void*
return_2_locals_ptrinc (void *q)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int *p = q ? a : b;
return ++p; /* { dg-warning "function returns address of local" } */
}
ATTR (noipa) void*
return_3_locals (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int c[3]; /* { dg-message "declared here" } */
void *p = i < 0 ? a : 0 < i ? c : b;
return p; /* { dg-warning "function returns address of local" } */
}
/* Verify that a conditional expression with a pointer first operand
is handled correctly. */
ATTR (noipa) void*
return_3_locals_ptrcond (void *p, void *q)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int c[3]; /* { dg-message "declared here" } */
void *r = q ? r ? a : b : c;
return r; /* { dg-warning "function returns address of local" } */
}
ATTR (noipa) void*
return_5_locals (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int c[3]; /* { dg-message "declared here" } */
int d[4]; /* { dg-message "declared here" } */
int e[5]; /* { dg-message "declared here" } */
void *p = i < -1 ? a : i < 0 ? b : 1 < i ? e : 0 < i ? d : c;
return p; /* { dg-warning "function returns address of local" } */
}
ATTR (noipa) void*
return_1_global_4_locals (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int c[3]; /* { dg-message "declared here" } */
int d[4]; /* { dg-message "declared here" } */
void *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? d : c;
return p; /* { dg-warning "function may return address of local" } */
}
ATTR (noipa) void*
return_2_globals_3_locals (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int c[3]; /* { dg-message "declared here" } */
void *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : c;
return p; /* { dg-warning "function may return address of local" } */
}
ATTR (noipa) void*
return_3_globals_2_locals (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
void *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : g3;
return p; /* { dg-warning "function may return address of local" } */
}
ATTR (noipa) void*
return_4_globals_1_local (int i)
{
int a[1]; /* { dg-message "declared here" } */
void *p = i < -1 ? a : i < 0 ? g1 : 1 < i ? g2 : 0 < i ? g4 : g3;
return p; /* { dg-warning "function may return address of local" } */
}
ATTR (noipa) void*
return_all_globals (int i)
{
void *p = i < -1 ? g1 : i < 0 ? g2 : 1 < i ? g3 : 0 < i ? g5 : g4;
return p;
}
ATTR (noipa) void*
return_2_alloca_local_cstoff (int n, int i)
{
int *a = __builtin_alloca (n); /* { dg-message "declared here" } */
int *b = __builtin_alloca (n); /* { dg-message "declared here" } */
int *p = i < 0 ? a : b;
p += 1;
sink (p);
return p; /* { dg-warning "function returns address of local" } */
}
ATTR (noipa) void*
return_alloca_local_cstoff (int n, int i)
{
int *a = __builtin_alloca (n); /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int *p = i < 0 ? a : b;
p += 1;
sink (p);
return p; /* { dg-warning "function returns address of local" } */
}
ATTR (noipa) void*
return_local_alloca_cstoff (int n, int i)
{
int a[2]; /* { dg-message "declared here" } */
int *b = __builtin_alloca (n); /* { dg-message "declared here" } */
int *p = i < 0 ? a : b;
p += 1;
sink (p);
return p; /* { dg-warning "function returns address of local" } */
}
ATTR (noipa) void*
return_2_locals_cstoff (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int *p = i < 0 ? a : b;
p += 1;
sink (p);
return p; /* { dg-warning "function returns address of local" } */
}
ATTR (noipa) void*
return_2_globals_3_locals_cstoff (int i)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int c[3]; /* { dg-message "declared here" } */
int *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : c;
p += 1;
sink (p);
return p; /* { dg-warning "function may return address of local" } */
}
ATTR (noipa) void*
return_3_globals_alloca_local_varoff (int n, int i, int j)
{
int *a = __builtin_alloca (n); /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : g3;
p += j;
sink (p);
return p; /* { dg-warning "function may return address of local" } */
}
ATTR (noipa) void*
return_3_globals_2_locals_varoff (int i, int j)
{
int a[1]; /* { dg-message "declared here" } */
int b[2]; /* { dg-message "declared here" } */
int *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : g3;
p += j;
sink (p);
return p; /* { dg-warning "function may return address of local" } */
}