c: Diagnose char argument to __builtin_stdc_*

Message ID ZyHfRNs7umUtZb99@tucnak
State New
Headers
Series c: Diagnose char argument to __builtin_stdc_* |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Jakub Jelinek Oct. 30, 2024, 7:24 a.m. UTC
  Hi!

When working on __builtin_stdc_rotate_*, I've noticed that while the
second argument to those is explicitly allowed to have char type,
the first argument to all the stdc_* type-generic functions is
- standard unsigned integer type, excluding bool;
- extended unsigned integer type;
- or, bit-precise unsigned integer type whose width matches a standard
  or extended integer type, excluding bool.
but the __builtin_stdc_* lowering code was diagnosing just
!INTEGRAL_TYPE_P
ENUMERAL_TYPE
BOOLEAN_TYPE
!TYPE_UNSIGNED
Now, with -funsigned-char plain char type is TYPE_UNSIGNED, yet it isn't
allowed because it isn't standard unsigned integer type, nor
extended unsigned integer type, nor bit-precise unsigned integer type.

The following patch diagnoses char arguments and adds testsuite coverage
for that.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Or should I make it a pedwarn instead?

2024-10-30  Jakub Jelinek  <jakub@redhat.com>

gcc/c/
	* c-parser.cc (c_parser_postfix_expression): Diagnose if
	first __builtin_stdc_* argument has char type even when
	-funsigned-char.
gcc/testsuite/
	* gcc.dg/builtin-stdc-bit-3.c: New test.
	* gcc.dg/builtin-stdc-rotate-3.c: New test.


	Jakub
  

Comments

Joseph Myers Oct. 30, 2024, 1:07 p.m. UTC | #1
On Wed, 30 Oct 2024, Jakub Jelinek wrote:

> 2024-10-30  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/c/
> 	* c-parser.cc (c_parser_postfix_expression): Diagnose if
> 	first __builtin_stdc_* argument has char type even when
> 	-funsigned-char.
> gcc/testsuite/
> 	* gcc.dg/builtin-stdc-bit-3.c: New test.
> 	* gcc.dg/builtin-stdc-rotate-3.c: New test.

OK.
  

Patch

--- gcc/c/c-parser.cc.jj	2024-10-29 09:06:12.976008357 +0100
+++ gcc/c/c-parser.cc	2024-10-29 16:45:45.770813360 +0100
@@ -12382,6 +12382,14 @@  c_parser_postfix_expression (c_parser *p
 		expr.set_error ();
 		break;
 	      }
+	    if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value))
+		== char_type_node)
+	      {
+		error_at (loc, "argument 1 in call to function "
+			  "%qs has %<char%> type", name);
+		expr.set_error ();
+		break;
+	      }
 	    tree arg = arg_p->value;
 	    tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
 	    /* Expand:
--- gcc/testsuite/gcc.dg/builtin-stdc-bit-3.c.jj	2024-10-29 16:48:59.186127709 +0100
+++ gcc/testsuite/gcc.dg/builtin-stdc-bit-3.c	2024-10-29 16:49:56.188336214 +0100
@@ -0,0 +1,21 @@ 
+/* { dg-do compile } */
+/* { dg-options "-funsigned-char" } */
+
+void
+foo (void)
+{
+  __builtin_stdc_leading_zeros ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_leading_zeros' has 'char' type" } */
+  __builtin_stdc_leading_ones ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_leading_ones' has 'char' type" } */
+  __builtin_stdc_trailing_zeros ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_trailing_zeros' has 'char' type" } */
+  __builtin_stdc_trailing_ones ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_trailing_ones' has 'char' type" } */
+  __builtin_stdc_first_leading_zero ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_first_leading_zero' has 'char' type" } */
+  __builtin_stdc_first_leading_one ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_first_leading_one' has 'char' type" } */
+  __builtin_stdc_first_trailing_zero ((char) 0);	/* { dg-error "argument 1 in call to function '__builtin_stdc_first_trailing_zero' has 'char' type" } */
+  __builtin_stdc_first_trailing_one ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_first_trailing_one' has 'char' type" } */
+  __builtin_stdc_count_zeros ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_count_zeros' has 'char' type" } */
+  __builtin_stdc_count_ones ((char) 0);			/* { dg-error "argument 1 in call to function '__builtin_stdc_count_ones' has 'char' type" } */
+  __builtin_stdc_has_single_bit ((char) 0);		/* { dg-error "argument 1 in call to function '__builtin_stdc_has_single_bit' has 'char' type" } */
+  __builtin_stdc_bit_width ((char) 0);			/* { dg-error "argument 1 in call to function '__builtin_stdc_bit_width' has 'char' type" } */
+  __builtin_stdc_bit_floor ((char) 0);			/* { dg-error "argument 1 in call to function '__builtin_stdc_bit_floor' has 'char' type" } */
+  __builtin_stdc_bit_ceil ((char) 0);			/* { dg-error "argument 1 in call to function '__builtin_stdc_bit_ceil' has 'char' type" } */
+}
--- gcc/testsuite/gcc.dg/builtin-stdc-rotate-3.c.jj	2024-10-29 16:48:55.506178811 +0100
+++ gcc/testsuite/gcc.dg/builtin-stdc-rotate-3.c	2024-10-29 16:50:15.338070312 +0100
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } */
+/* { dg-options "-funsigned-char" } */
+
+void
+foo (void)
+{
+  __builtin_stdc_rotate_left ((char) 0, 0);			/* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_left' has 'char' type" } */
+  __builtin_stdc_rotate_right ((char) 0, 0);			/* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_right' has 'char' type" } */
+}