c++: Fix up ICE on __builtin_shufflevector constexpr evaluation [PR105871]

As the following testcase shows, BIT_FIELD_REF result doesn't have to have
just integral type, it can also have vector type.  And in that case
cxx_eval_bit_field_ref just ICEs on it because it is unprepared for that
case, creates the initial value with build_int_cst (sure, that one could be
easily replaced with build_zero_cst) and then expects it can through shifts,
ands and ors come up with the final value, but that doesn't work for
vectors.

We already call fold_ternary if whole is a VECTOR_CST, this patch does the
same if the result doesn't have integral type.  And, there is no guarantee
fold_ternary will succeed and the callers certainly don't expect NULL
being returned, so it also diagnoses those as non-constant and returns
original t in that case.

2022-06-09  Jakub Jelinek  <jakub@redhat.com>

	PR c++/105871
	* constexpr.cc (cxx_eval_bit_field_ref): For BIT_FIELD_REF with
	non-integral result type use fold_ternary too like for BIT_FIELD_REFs
	from VECTOR_CST.  If fold_ternary returns NULL, diagnose non-constant
	expression, set *non_constant_p and return t, instead of returning
	NULL.

	* g++.dg/pr105871.C: New test.
This commit is contained in:
Jakub Jelinek 2022-06-09 17:42:31 +02:00
parent 702a11ade2
commit 4c334e0e4f
2 changed files with 22 additions and 3 deletions

View File

@ -4198,9 +4198,16 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t,
if (*non_constant_p)
return t;
if (TREE_CODE (whole) == VECTOR_CST)
return fold_ternary (BIT_FIELD_REF, TREE_TYPE (t), whole,
TREE_OPERAND (t, 1), TREE_OPERAND (t, 2));
if (TREE_CODE (whole) == VECTOR_CST || !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
if (tree r = fold_ternary (BIT_FIELD_REF, TREE_TYPE (t), whole,
TREE_OPERAND (t, 1), TREE_OPERAND (t, 2)))
return r;
if (!ctx->quiet)
error ("%qE is not a constant expression", orig_whole);
*non_constant_p = true;
return t;
}
start = TREE_OPERAND (t, 2);
istart = tree_to_shwi (start);

View File

@ -0,0 +1,12 @@
// PR c++/105871
// { dg-do compile }
// { dg-options "-Wno-psabi" }
typedef __attribute__((__vector_size__ ( 1))) unsigned char U;
typedef __attribute__((__vector_size__ (16))) unsigned char V;
U
foo (void)
{
return __builtin_shufflevector ((U){}, (V){}, 0);
}