blob: e857502685a76c2316c9f869cc4724e63d6a914c [file] [log] [blame]
// PR middle-end/69780 - [4.9/5/6 Regression] ICE on
// __builtin_alloca_with_align with small alignment
// { dg-do compile }
// { dg-require-effective-target alloca }
#define CHAR_BIT __CHAR_BIT__
#define SIZE_MAX __SIZE_MAX__
#define UINT_MAX (__INT_MAX__ + 1U)
/* The largest valid alignment is undocumented and subject to change
but for the purposes of white box testing we rely on knowing that
it happens to be defined to (UINT_MAX >> 1) + 1. */
#define ALIGN_MAX ((UINT_MAX >> 1) + 1)
#if UINT_MAX < SIZE_MAX
/* Define a constant to exercise an alignment that is valid a power
of 2 in excess of the maximum. */
# define MAX_X_2 (ALIGN_MAX << 1)
#else
/* For targets where UINT_MAX is the same as SIZE_MAX, use an invalid
alignment that's less than the maximum to elicit the same errors. */
# define MAX_X_2 (ALIGN_MAX + 1)
#endif
static void* p;
// Verify that valid __builtin_alloca_with_align expressions are accepted.
void test_valid (int n)
{
enum {
A1 = CHAR_BIT * 1,
A2 = CHAR_BIT * 2,
A4 = CHAR_BIT * 4,
A8 = CHAR_BIT * 8,
A16 = CHAR_BIT * 16,
A32 = CHAR_BIT * 32
};
const int a1 = A1;
const int a2 = A2;
const int a4 = A4;
const int a8 = A8;
const int a16 = A16;
const int a32 = A32;
// Valid alignments are power of 2 positive multiples of CHAR_BIT.
p = __builtin_alloca_with_align (n, CHAR_BIT * 1);
p = __builtin_alloca_with_align (n, CHAR_BIT * 2);
p = __builtin_alloca_with_align (n, CHAR_BIT * 4);
p = __builtin_alloca_with_align (n, CHAR_BIT * 8);
p = __builtin_alloca_with_align (n, CHAR_BIT * 16);
p = __builtin_alloca_with_align (n, CHAR_BIT * 32);
p = __builtin_alloca_with_align (n, A1);
p = __builtin_alloca_with_align (n, A2);
p = __builtin_alloca_with_align (n, A4);
p = __builtin_alloca_with_align (n, A8);
p = __builtin_alloca_with_align (n, A16);
p = __builtin_alloca_with_align (n, A32);
p = __builtin_alloca_with_align (n, a1);
p = __builtin_alloca_with_align (n, a2);
p = __builtin_alloca_with_align (n, a4);
p = __builtin_alloca_with_align (n, a8);
p = __builtin_alloca_with_align (n, a16);
p = __builtin_alloca_with_align (n, a32);
}
template <int A> struct X { enum { Align = A }; };
template <int A>
void test_valid_template (int n)
{
// Valid alignments are power of 2 positive multiples of CHAR_BIT.
p = __builtin_alloca_with_align (n, A);
}
template void test_valid_template<CHAR_BIT>(int);
template void test_valid_template<CHAR_BIT * 2>(int);
template void test_valid_template<CHAR_BIT * 4>(int);
template void test_valid_template<CHAR_BIT * 8>(int);
template void test_valid_template<CHAR_BIT * 16>(int);
template void test_valid_template<CHAR_BIT * 32>(int);
// Exercise the alignment in a dependent context.
template <int A>
void test_valid_template_dep (int n)
{
// Valid alignments are power of 2 positive multiples of CHAR_BIT.
p = __builtin_alloca_with_align (n, X<A>::Align);
}
template void test_valid_template_dep<CHAR_BIT>(int);
template void test_valid_template_dep<CHAR_BIT * 2>(int);
template void test_valid_template_dep<CHAR_BIT * 4>(int);
template void test_valid_template_dep<CHAR_BIT * 8>(int);
template void test_valid_template_dep<CHAR_BIT * 16>(int);
template void test_valid_template_dep<CHAR_BIT * 32>(int);
// Invalid size must be rejected (and not cause an ICE).
void test_arg1_non_int (int n)
{
extern void f ();
p = __builtin_alloca_with_align ((void*)0, 32); // { dg-error "invalid conversion" }
p = __builtin_alloca_with_align ("", 32); // { dg-error "invalid conversion" }
p = __builtin_alloca_with_align (L"", 32); // { dg-error "invalid conversion" }
p = __builtin_alloca_with_align (f, 32); // { dg-error "invalid conversion" }
}
// Non-integer alignment must be rejected.
void test_arg2_non_int (int n)
{
// Verify the full text of the diagnostic just once.
p = __builtin_alloca_with_align (n, 0.0); // { dg-error "second argument to function .__builtin_alloca_with_align. must be a constant integer power of 2 between .8. and " }
p = __builtin_alloca_with_align (n, (void*)0); // { dg-error "invalid conversion|must be a constant integer" }
p = __builtin_alloca_with_align (n, ""); // { dg-error "invalid conversion|must be a constant integer" }
p = __builtin_alloca_with_align (n, L""); // { dg-error "invalid conversion|must be a constant integer" }
}
// Integer alignment that's not a constant expression must be rejected.
void test_arg2_non_const (int n, int a1)
{
extern const int a2;
static volatile const int a3 = CHAR_BIT;
p = __builtin_alloca_with_align (n, a1); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, a2); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, a3); // { dg-error "must be a constant integer" }
}
// Constant integer alignment that's not a power of 2 positive multiple
// of CHAR_BIT must be rejected.
void test_arg2_non_pow2 (int n)
{
p = __builtin_alloca_with_align (n, 0); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 1); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 2); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 3); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 4); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 5); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 6); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 7); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 9); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 10); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 11); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 12); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 13); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 14); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 15); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 17); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 31); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 33); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 63); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, 65); // { dg-error "must be a constant integer" }
p = __builtin_alloca_with_align (n, SIZE_MAX); /* { dg-error "must be a constant integer" } */
p = __builtin_alloca_with_align (n, MAX_X_2); /* { dg-error "must be a constant integer" } */
}
// Exercise invalid alignment specified by a template argument.
template <int A>
void test_invalid_template_1 (int n)
{
// Valid alignments are power of 2 positive multiples of CHAR_BIT.
p = __builtin_alloca_with_align (n, A); // { dg-error "must be a constant integer" }
}
template void test_invalid_template_1<1>(int);
template <int A>
void test_invalid_template_7 (int n)
{
p = __builtin_alloca_with_align (n, A); // { dg-error "must be a constant integer" }
}
template void test_invalid_template_7<7>(int);
template <int A>
void test_invalid_template_9 (int n)
{
p = __builtin_alloca_with_align (n, A); // { dg-error "must be a constant integer" }
}
template void test_invalid_template_9<9>(int);
// Exercise invalid alignment specified by a template dependent argument.
template <int A>
void test_invalid_template_dep_1 (int n)
{
p = __builtin_alloca_with_align (n, X<A>::Align); // { dg-error "must be a constant integer" }
}
template void test_invalid_template_dep_1<1>(int);