c++: Fix up __builtin_{bit_cast,convertvector} parsing

Jonathan reported on IRC that we don't parse
__builtin_bit_cast (type, val).field
etc.
The problem is that for these 2 builtins we return from
cp_parser_postfix_expression instead of setting postfix_expression
to the cp_build_* value and falling through into the postfix regression
suffix handling loop.

2022-03-26  Jakub Jelinek  <jakub@redhat.com>

	* parser.cc (cp_parser_postfix_expression)
	<case RID_BILTIN_CONVERTVECTOR, case RID_BUILTIN_BIT_CAST>: Don't
	return cp_build_{vec,convert,bit_cast} result right away, instead
	set postfix_expression to it and break.

	* c-c++-common/builtin-convertvector-3.c: New test.
	* g++.dg/cpp2a/bit-cast15.C: New test.
This commit is contained in:
Jakub Jelinek 2022-03-26 08:11:58 +01:00
parent 75d1c8fea9
commit 1806829e08
3 changed files with 38 additions and 4 deletions

View file

@ -7525,8 +7525,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
}
/* Look for the closing `)'. */
parens.require_close (parser);
return cp_build_vec_convert (expression, type_location, type,
tf_warning_or_error);
postfix_expression
= cp_build_vec_convert (expression, type_location, type,
tf_warning_or_error);
break;
}
case RID_BUILTIN_BIT_CAST:
@ -7551,8 +7553,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
expression = cp_parser_assignment_expression (parser);
/* Look for the closing `)'. */
parens.require_close (parser);
return cp_build_bit_cast (type_location, type, expression,
tf_warning_or_error);
postfix_expression
= cp_build_bit_cast (type_location, type, expression,
tf_warning_or_error);
break;
}
default:

View file

@ -0,0 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
typedef int v4si __attribute__((vector_size (4 * sizeof (int))));
typedef double v4df __attribute__((vector_size (4 * sizeof (double))));
double
foo (void)
{
v4si a = { 1, 2, 3, 4 };
return __builtin_convertvector (a, v4df)[1];
}

View file

@ -0,0 +1,19 @@
// { dg-do compile }
struct S { short a, b; };
struct T { float a[4]; };
struct U { int b[4]; };
#if __SIZEOF_FLOAT__ == __SIZEOF_INT__
int
f1 (T &x)
{
return __builtin_bit_cast (U, x).b[1];
}
float
f2 (int (&x)[4])
{
return __builtin_bit_cast (T, x).a[2];
}
#endif