From patchwork Mon Oct 28 07:53:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 2003141 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=UQwYs9iO; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XcQd34Pc3z1xxV for ; Mon, 28 Oct 2024 18:53:56 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F278C3858D20 for ; Mon, 28 Oct 2024 07:53:54 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 3E63E3858D20 for ; Mon, 28 Oct 2024 07:53:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3E63E3858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3E63E3858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730102016; cv=none; b=alrSlS9b8WCYGAxzorre8Q/RnuCzvy1oVJMt0Qhwux3z9D15yvxZRrffGsVmxQz27jY6jLsjVg6a5WTkVxDs+rQAGJUriQsBnICxhgddXMUvIfxFHyemWWPU+gzQJ6CkdU3KIAGpdIunjihIQxvWlSSSv/g6ZDAT3PbvZ7tQcWM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730102016; c=relaxed/simple; bh=7XbEJ/K5Z7xe5BITZE5PKVR7RLf8R/wspDOt9HcvP5I=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=sG6YSbhxa112R/MIUacyUrtVwP5fRXLpxL6p3bMprMH47WlNkz3C2LzlFM23zGUi9+1iJVmOJ+tBqeRmTdg4tk2W20NYN69MpPZhajn1rhom7wiEKcZ+rmQENPtKGhbEHOzH2bd0O2CeQAZJSakQxIikXeZ7PUTEtwsXCLwIWyM= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730102011; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references; bh=7wfxF/SxXx/1a5Z9x/PD2zhW3IJVz/9brxw5yz4uRC0=; b=UQwYs9iOPfI8RCNIXISK+bQnZL6UxxOMhT1IPgn7M2+0Tq2DGIIXAUktcTls8PnoNYV0SY kdwQHlZiWBkydQZ2a56eDp6xAlMSmG/D4OhnpucVWabW0O1Uji7b2dUoJ9V060uO7EJi4D 2M2l6C+I5YBDwzVA8DzWIYJU6kckP3U= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-77-J0aa_8TmMjGFI736tL0jfA-1; Mon, 28 Oct 2024 03:53:28 -0400 X-MC-Unique: J0aa_8TmMjGFI736tL0jfA-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0DDA019560B0 for ; Mon, 28 Oct 2024 07:53:27 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 919AA1956086; Mon, 28 Oct 2024 07:53:25 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 49S7rMR8163096 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 28 Oct 2024 08:53:22 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 49S7rMK5163095; Mon, 28 Oct 2024 08:53:22 +0100 Date: Mon, 28 Oct 2024 08:53:22 +0100 From: Jakub Jelinek To: Joseph Myers Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c, v3: Add __builtin_stdc_rotate_{left,right} builtins [PR117030] Message-ID: References: <95354a1e-3987-e2e3-9718-370012237294@redhat.com> MIME-Version: 1.0 In-Reply-To: <95354a1e-3987-e2e3-9718-370012237294@redhat.com> X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org On Fri, Oct 25, 2024 at 08:06:36PM +0000, Joseph Myers wrote: > If sanitizing makes sense for these built-in functions, surely it should > check for all negative shifts, including those that are multiples of the > width (and there should be tests for it in the testsuite). So sanitizing > would require more complicated logic to avoid reducing a negative shift > modulo the width at all. Or in the absence of support for sanitizing > these functions, the logic for modulo reduction shouldn't need to depend > on whether sanitizing. > > > @@ -409,7 +416,9 @@ c_fully_fold_internal (tree expr, bool i > > warning_at (loc, OPT_Wshift_count_overflow, > > (code == LSHIFT_EXPR > > ? G_("left shift count >= width of type") > > - : G_("right shift count >= width of type"))); > > + : code == RSHIFT_EXPR > > + ? G_("right shift count >= width of type") > > + : G_("rotate count >= width of type"))); > > This shouldn't be reachable, since larger rotate counts are valid and > should have been reduced modulo the width. Ok, here is an updated patch, which for ubsan checks just for negative count and nothing else, does that check before using TRUNC_MOD_EXPR on the argument and uses it on unsigned types in all cases. The c_fully_fold_internal new wording is removed in both cases, as the argument will be modulo shift count and so it can't be negative or too large anymore. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2024-10-28 Jakub Jelinek PR c/117030 gcc/ * doc/extend.texi (__builtin_stdc_rotate_left, __builtin_stdc_rotate_right): Document. gcc/c-family/ * c-common.cc (c_common_reswords): Add __builtin_stdc_rotate_left and __builtin_stdc_rotate_right. * c-ubsan.cc (ubsan_instrument_shift): For {L,R}ROTATE_EXPR just check if op1 is negative. gcc/c/ * c-parser.cc: Include asan.h and c-family/c-ubsan.h. (c_parser_postfix_expression): Handle __builtin_stdc_rotate_left and __builtin_stdc_rotate_right. * c-fold.cc (c_fully_fold_internal): Handle LROTATE_EXPR and RROTATE_EXPR. gcc/testsuite/ * gcc.dg/builtin-stdc-rotate-1.c: New test. * gcc.dg/builtin-stdc-rotate-2.c: New test. * gcc.dg/ubsan/builtin-stdc-rotate-1.c: New test. * gcc.dg/ubsan/builtin-stdc-rotate-2.c: New test. Jakub --- gcc/c-family/c-common.cc.jj 2024-10-25 10:00:29.314770060 +0200 +++ gcc/c-family/c-common.cc 2024-10-26 11:52:52.332892683 +0200 @@ -448,6 +448,8 @@ const struct c_common_resword c_common_r { "__builtin_stdc_has_single_bit", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_ones", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_rotate_left", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_rotate_right", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_ones", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_zeros", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, --- gcc/c-family/c-ubsan.cc.jj 2024-10-25 10:00:29.317770017 +0200 +++ gcc/c-family/c-ubsan.cc 2024-10-26 11:57:29.199977994 +0200 @@ -176,8 +176,19 @@ ubsan_instrument_shift (location_t loc, op0 = unshare_expr (op0); op1 = unshare_expr (op1); - t = fold_convert_loc (loc, op1_utype, op1); - t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1); + if (code == LROTATE_EXPR || code == RROTATE_EXPR) + { + /* For rotates just check for negative op1. */ + if (TYPE_UNSIGNED (type1)) + return NULL_TREE; + t = fold_build2 (LT_EXPR, boolean_type_node, op1, + build_int_cst (type1, 0)); + } + else + { + t = fold_convert_loc (loc, op1_utype, op1); + t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1); + } /* If this is not a signed operation, don't perform overflow checks. Also punt on bit-fields. */ --- gcc/c/c-parser.cc.jj 2024-10-25 10:00:29.322769946 +0200 +++ gcc/c/c-parser.cc 2024-10-26 12:05:40.900026757 +0200 @@ -74,6 +74,8 @@ along with GCC; see the file COPYING3. #include "bitmap.h" #include "analyzer/analyzer-language.h" #include "toplev.h" +#include "asan.h" +#include "c-family/c-ubsan.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -12262,12 +12264,15 @@ c_parser_postfix_expression (c_parser *p C_BUILTIN_STDC_HAS_SINGLE_BIT, C_BUILTIN_STDC_LEADING_ONES, C_BUILTIN_STDC_LEADING_ZEROS, + C_BUILTIN_STDC_ROTATE_LEFT, + C_BUILTIN_STDC_ROTATE_RIGHT, C_BUILTIN_STDC_TRAILING_ONES, C_BUILTIN_STDC_TRAILING_ZEROS, C_BUILTIN_STDC_MAX } stdc_rid = C_BUILTIN_STDC_MAX; const char *name = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + unsigned num_args = 1; switch (name[sizeof ("__builtin_stdc_") - 1]) { case 'b': @@ -12316,6 +12321,13 @@ c_parser_postfix_expression (c_parser *p else stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS; break; + case 'r': + if (name[sizeof ("__builtin_stdc_rotate_") - 1] == 'l') + stdc_rid = C_BUILTIN_STDC_ROTATE_LEFT; + else + stdc_rid = C_BUILTIN_STDC_ROTATE_RIGHT; + num_args = 2; + break; case 't': if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o') stdc_rid = C_BUILTIN_STDC_TRAILING_ONES; @@ -12334,7 +12346,7 @@ c_parser_postfix_expression (c_parser *p break; } - if (vec_safe_length (cexpr_list) != 1) + if (vec_safe_length (cexpr_list) != num_args) { error_at (loc, "wrong number of arguments to %qs", name); expr.set_error (); @@ -12406,6 +12418,77 @@ c_parser_postfix_expression (c_parser *p without evaluating arg multiple times, type being __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */ int prec = TYPE_PRECISION (type); + if (num_args == 2) + { + /* Expand: + __builtin_stdc_rotate_left (arg1, arg2) as + arg1 r<< (arg2 % prec) + __builtin_stdc_rotate_right (arg1, arg2) as + arg1 r>> (arg2 % prec). */ + arg_p = &(*cexpr_list)[1]; + *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true); + if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value))) + { + error_at (loc, "%qs operand not an integral type", name); + expr.set_error (); + break; + } + if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE) + { + error_at (loc, "argument %u in call to function " + "%qs has enumerated type", 2, name); + expr.set_error (); + break; + } + tree arg1 = save_expr (arg); + tree arg2 = save_expr (arg_p->value); + tree_code code; + if (stdc_rid == C_BUILTIN_STDC_ROTATE_LEFT) + code = LROTATE_EXPR; + else + code = RROTATE_EXPR; + + if (TREE_CODE (arg2) == INTEGER_CST + && tree_int_cst_sgn (arg2) < 0) + warning_at (loc, OPT_Wshift_count_negative, + "rotate count is negative"); + + tree instrument_expr = NULL_TREE; + if (sanitize_flags_p (SANITIZE_SHIFT)) + instrument_expr = ubsan_instrument_shift (loc, code, + arg1, arg2); + + /* Promote arg2 to unsigned just so that we don't + need to deal with arg2 type not being able to represent + prec. In the end gimplification uses unsigned int + for all shifts/rotates anyway. */ + if (TYPE_PRECISION (TREE_TYPE (arg2)) + < TYPE_PRECISION (integer_type_node)) + arg2 = fold_convert (unsigned_type_node, arg2); + + if (TYPE_UNSIGNED (TREE_TYPE (arg2))) + arg2 = build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg2), + arg2, build_int_cst (TREE_TYPE (arg2), + prec)); + else + { + /* When second argument is signed, just do the modulo in + unsigned type, that results in better generated code + (for power of 2 precisions bitwise AND). */ + tree utype = c_common_unsigned_type (TREE_TYPE (arg2)); + arg2 = build2_loc (loc, TRUNC_MOD_EXPR, utype, + fold_convert (utype, arg2), + build_int_cst (utype, prec)); + } + + expr.value = build2_loc (loc, code, TREE_TYPE (arg1), arg1, + arg2); + if (instrument_expr) + expr.value = build2_loc (loc, COMPOUND_EXPR, + TREE_TYPE (expr.value), + instrument_expr, expr.value); + break; + } tree barg1 = arg; switch (stdc_rid) { --- gcc/c/c-fold.cc.jj 2024-10-25 09:35:28.145154965 +0200 +++ gcc/c/c-fold.cc 2024-10-26 11:54:10.859782375 +0200 @@ -328,6 +328,8 @@ c_fully_fold_internal (tree expr, bool i case EXACT_DIV_EXPR: case LSHIFT_EXPR: case RSHIFT_EXPR: + case LROTATE_EXPR: + case RROTATE_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: case BIT_AND_EXPR: @@ -389,7 +391,10 @@ c_fully_fold_internal (tree expr, bool i && tree_int_cst_sgn (op0) < 0) warning_at (loc, OPT_Wshift_negative_value, "left shift of negative value"); - if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR) + if ((code == LSHIFT_EXPR + || code == RSHIFT_EXPR + || code == LROTATE_EXPR + || code == RROTATE_EXPR) && TREE_CODE (orig_op1) != INTEGER_CST && TREE_CODE (op1) == INTEGER_CST && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE --- gcc/doc/extend.texi.jj 2024-10-25 09:35:28.474150291 +0200 +++ gcc/doc/extend.texi 2024-10-26 11:52:52.340892570 +0200 @@ -16129,6 +16129,32 @@ performed on the argument. It is equiva @code{(unsigned int) __builtin_ctzg (@var{arg}, @var{prec})} @enddefbuiltin +@defbuiltin{@var{type1} __builtin_stdc_rotate_left (@var{type1} @var{arg1}, @var{type2} @var{arg2})} +The @code{__builtin_stdc_rotate_left} function is available only +in C. It is type-generic, the first argument can be any unsigned integer +(standard, extended or bit-precise) and second argument any signed or +unsigned integer or @code{char}. No integral argument promotions are +performed on the arguments. It is equivalent to +@code{(@var{type1}) ((@var{arg1} << (@var{arg2} % @var{prec})) +| (@var{arg1} >> ((-(unsigned @var{type2}) @var{arg2}) % @var{prec})))} +where @var{prec} is bit width of @var{type1}, except that side-effects +in @var{arg1} and @var{arg2} are evaluated just once. The behavior is +undefined if @var{arg2} is negative. +@enddefbuiltin + +@defbuiltin{@var{type1} __builtin_stdc_rotate_right (@var{type1} @var{arg1}, @var{type2} @var{arg2})} +The @code{__builtin_stdc_rotate_right} function is available only +in C. It is type-generic, the first argument can be any unsigned integer +(standard, extended or bit-precise) and second argument any signed or +unsigned integer or @code{char}. No integral argument promotions are +performed on the arguments. It is equivalent to +@code{(@var{type1}) ((@var{arg1} >> (@var{arg2} % @var{prec})) +| (@var{arg1} << ((-(unsigned @var{type2}) @var{arg2}) % @var{prec})))} +where @var{prec} is bit width of @var{type1}, except that side-effects +in @var{arg1} and @var{arg2} are evaluated just once. The behavior is +undefined if @var{arg2} is negative. +@enddefbuiltin + @defbuiltin{double __builtin_powi (double, int)} @defbuiltinx{float __builtin_powif (float, int)} @defbuiltinx{{long double} __builtin_powil (long double, int)} --- gcc/testsuite/gcc.dg/builtin-stdc-rotate-1.c.jj 2024-10-26 11:52:52.341892555 +0200 +++ gcc/testsuite/gcc.dg/builtin-stdc-rotate-1.c 2024-10-26 11:52:52.341892555 +0200 @@ -0,0 +1,235 @@ +/* { dg-do run } */ +/* { dg-options "-std=c11" } */ + +unsigned long long +rotate_left (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e, int n) +{ + return (__builtin_stdc_rotate_left (a, n) + + __builtin_stdc_rotate_left (b, n) + + __builtin_stdc_rotate_left (c, n) + + __builtin_stdc_rotate_left (d, n) + + __builtin_stdc_rotate_left (e, n)); +} + +unsigned long long +rotate_right (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e, int n) +{ + return (__builtin_stdc_rotate_right (a, n) + + __builtin_stdc_rotate_right (b, n) + + __builtin_stdc_rotate_right (c, n) + + __builtin_stdc_rotate_right (d, n) + + __builtin_stdc_rotate_right (e, n)); +} + +#define expr_has_type(e, t) _Generic (e, default : 0, t : 1) + +int +main () +{ + if (__builtin_stdc_rotate_left ((unsigned char) 0, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned char) 0xdcU, (char) 0) != 0xdcU + || __builtin_stdc_rotate_left ((unsigned char) 0xdcU, __CHAR_BIT__) != 0xdcU + || __builtin_stdc_rotate_left ((unsigned char) 0xdcU, 2 * __CHAR_BIT__) != 0xdcU + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned char) 0, 0), unsigned char) + || __builtin_stdc_rotate_left ((unsigned char) 1, (_Bool) 1) != 2 + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned char) 1, (unsigned char) 1), unsigned char) + || __builtin_stdc_rotate_left ((unsigned char) ~1U, 3) != (unsigned char) ~8U + || __builtin_stdc_rotate_left ((unsigned char) (2U + __SCHAR_MAX__), 1) != 3 + || __builtin_stdc_rotate_left ((unsigned char) (2U + __SCHAR_MAX__), __CHAR_BIT__ + 1) != 3 + || __builtin_stdc_rotate_left ((unsigned short) 0, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned short) 0xdcabU, 0) != 0xdcabU + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned short) 0, (signed char) 0), unsigned short) + || __builtin_stdc_rotate_left ((unsigned short) 1, 13) != (1U << 13) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned short) 1, 13), unsigned short) + || __builtin_stdc_rotate_left ((unsigned short) ~1U, 7) != (unsigned short) ~0x80U + || __builtin_stdc_rotate_left ((unsigned short) (2U + __SHRT_MAX__), 1) != 3 + || __builtin_stdc_rotate_left (0U, 0) != 0 + || __builtin_stdc_rotate_left (0xcdbaU, (short int) 0) != 0xcdbaU + || !expr_has_type (__builtin_stdc_rotate_left (0U, 0), unsigned int) + || __builtin_stdc_rotate_left (1U, (char) 15) != (1U << 15) + || !expr_has_type (__builtin_stdc_rotate_left (1U, 15), unsigned int) + || __builtin_stdc_rotate_left (~1U, 9) != ~0x200U + || __builtin_stdc_rotate_left (2U + __INT_MAX__, 1) != 3 + || __builtin_stdc_rotate_left (0UL, 0) != 0 + || __builtin_stdc_rotate_left (0xdc8971baUL, 0) != 0xdc8971baUL + || !expr_has_type (__builtin_stdc_rotate_left (0UL, 0LL), unsigned long) + || __builtin_stdc_rotate_left (1UL, 30) != (1UL << 30) + || !expr_has_type (__builtin_stdc_rotate_left (1UL, 30), unsigned long) + || __builtin_stdc_rotate_left (~1UL, 22) != ~0x400000UL + || __builtin_stdc_rotate_left (2UL + __LONG_MAX__, 1) != 3 + || __builtin_stdc_rotate_left (2UL + __LONG_MAX__, (int) (sizeof (unsigned long) * __CHAR_BIT__) + 1) != 3 + || __builtin_stdc_rotate_left (0ULL, (_Bool) 0) != 0 + || __builtin_stdc_rotate_left (0xdc897143985734baULL, 0) != 0xdc897143985734baULL + || __builtin_stdc_rotate_left (0xdc897143985734baULL, 4 * (int) (sizeof (unsigned long long) * __CHAR_BIT__)) != 0xdc897143985734baULL + || !expr_has_type (__builtin_stdc_rotate_left (0ULL, 0), unsigned long long) + || __builtin_stdc_rotate_left (1ULL, 62) != (1ULL << 62) + || !expr_has_type (__builtin_stdc_rotate_left (1ULL, 62ULL), unsigned long long) + || __builtin_stdc_rotate_left (~1ULL, 53) != ~0x20000000000000ULL + || __builtin_stdc_rotate_left (2ULL + __LONG_LONG_MAX__, 1) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right ((unsigned char) 0, 0) != 0 + || __builtin_stdc_rotate_right ((unsigned char) 0xdcU, 0) != 0xdcU + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned char) 0, 0), unsigned char) + || __builtin_stdc_rotate_right ((unsigned char) 1, 1) != (1U + __SCHAR_MAX__) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned char) 1, 1), unsigned char) + || __builtin_stdc_rotate_right ((unsigned char) ~1U, (char) 3) != (unsigned char) ~((1U + __SCHAR_MAX__) >> 2) + || __builtin_stdc_rotate_right ((unsigned char) 3, 1) != (2U + __SCHAR_MAX__) + || __builtin_stdc_rotate_right ((unsigned short) 0, 0) != 0 + || __builtin_stdc_rotate_right ((unsigned short) 0xdcabU, 0) != 0xdcabU + || __builtin_stdc_rotate_right ((unsigned short) 0xdcabU, sizeof (unsigned short) * __CHAR_BIT__) != 0xdcabU + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned short) 0, 0), unsigned short) + || __builtin_stdc_rotate_right ((unsigned short) (1U << 13), 12) != 2 + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned short) (1U << 13), 2), unsigned short) + || __builtin_stdc_rotate_right ((unsigned short) ~1U, 7) != (unsigned short) ~((1U + __SHRT_MAX__) >> 6) + || __builtin_stdc_rotate_right ((unsigned short) 3, 1) != (2U + __SHRT_MAX__) + || __builtin_stdc_rotate_right (0U, 0) != 0 + || __builtin_stdc_rotate_right (0xcdbaU, 0) != 0xcdbaU + || !expr_has_type (__builtin_stdc_rotate_right (0U, 0), unsigned int) + || __builtin_stdc_rotate_right (1U << 15, 13) != 4U + || !expr_has_type (__builtin_stdc_rotate_right (1U << 15, 13), unsigned int) + || __builtin_stdc_rotate_right (~1U, 9) != ~((1U + __INT_MAX__) >> 8) + || __builtin_stdc_rotate_right (3U, (_Bool) 1) != (2U + __INT_MAX__) + || __builtin_stdc_rotate_right (3U, (int) (sizeof (unsigned) * __CHAR_BIT__) + 1) != (2U + __INT_MAX__) + || __builtin_stdc_rotate_right (0UL, (_Bool) 0) != 0 + || __builtin_stdc_rotate_right (0xdc8971baUL, 0) != 0xdc8971baUL + || !expr_has_type (__builtin_stdc_rotate_right (0UL, 0), unsigned long) + || __builtin_stdc_rotate_right (1UL << 30, 27) != 8UL + || !expr_has_type (__builtin_stdc_rotate_right (1UL << 30, 27), unsigned long) + || __builtin_stdc_rotate_right (~1UL, 22) != ~((1UL + __LONG_MAX__) >> 21) + || __builtin_stdc_rotate_right (3UL, 1) != (2UL + __LONG_MAX__) + || __builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right (0xdc897143985734baULL, 0) != 0xdc897143985734baULL + || !expr_has_type (__builtin_stdc_rotate_right (0ULL, 0), unsigned long long) + || __builtin_stdc_rotate_right (1ULL << 62, 60) != 4ULL + || !expr_has_type (__builtin_stdc_rotate_right (1ULL << 62, 60), unsigned long long) + || __builtin_stdc_rotate_right (~1ULL, 53) != ~((1ULL + __LONG_LONG_MAX__) >> 52) + || __builtin_stdc_rotate_right (3ULL, 1) != (2ULL + __LONG_LONG_MAX__)) + __builtin_abort (); +#ifdef __SIZEOF_INT128__ + if (__builtin_stdc_rotate_left ((unsigned __int128) 0U, 0) != 0 + || __builtin_stdc_rotate_left (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned __int128) 0U, 0), unsigned __int128) + || __builtin_stdc_rotate_left ((unsigned __int128) 1U, 115) != ((unsigned __int128) 1U << 115) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned __int128) 1U, 115), unsigned __int128) + || __builtin_stdc_rotate_left (~(unsigned __int128) 1ULL, 53) != ~(unsigned __int128) 0x20000000000000ULL + || __builtin_stdc_rotate_left (1ULL + ((unsigned __int128) 1U << 127), 1) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned __int128) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned __int128) 0U, 0), unsigned __int128) + || __builtin_stdc_rotate_right ((unsigned __int128) 1ULL << 115, 110) != 32U + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned __int128) 1ULL << 115, 110), unsigned __int128) + || __builtin_stdc_rotate_right (~(unsigned __int128) 1ULL, 53) != ~((unsigned __int128) 1 << 75) + || __builtin_stdc_rotate_right ((unsigned __int128) 3ULL, 1) != 1U + ((unsigned __int128) 1U << 127)) + __builtin_abort (); +#endif +#if __has_builtin (__builtin_stdc_rotate_left) != 1 +#error __builtin_stdc_rotate_left not implemented +#endif +#if __has_builtin (__builtin_stdc_rotate_right) != 1 +#error __builtin_stdc_rotate_right not implemented +#endif + unsigned char a = 1; + unsigned short b = 1; + unsigned int c = 1; + unsigned long d = 1; + unsigned long long e = 1; + int f = 1; + if (__builtin_stdc_rotate_left (a++, f++) != 2 || a != 2 || f != 2) + __builtin_abort (); + if (__builtin_stdc_rotate_left (b++, f++) != 4 || b != 2 || f != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_left (c++, f++) != 8 || c != 2 || f != 4) + __builtin_abort (); + if (__builtin_stdc_rotate_left (d++, f++) != 16 || d != 2 || f != 5) + __builtin_abort (); + if (__builtin_stdc_rotate_left (e++, f++) != 32 || e != 2 || f != 6) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (a++, f++) != 1 || a != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (b++, f++) != 1 || b != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (c++, f++) != 1 || c != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (d++, f++) != 1 || d != 3 || f != 2) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (e++, f++) != 1 || e != 3 || f != 2) + __builtin_abort (); +#ifdef __SIZEOF_INT128__ + unsigned __int128 g = 1; + if (__builtin_stdc_rotate_left (g++, f++) != 4 || g != 2 || f != 3) + __builtin_abort (); + f = 1; + if (__builtin_stdc_rotate_right (g++, f++) != 1 || g != 3 || f != 2) + __builtin_abort (); +#endif +#if __BITINT_MAXWIDTH__ >= 64 + if (__builtin_stdc_rotate_left (0uwb, 0) != 0 + || __builtin_stdc_rotate_left (1uwb, 0) != 1uwb + || !expr_has_type (__builtin_stdc_rotate_left (0uwb, 0), unsigned _BitInt(1))) + __builtin_abort (); + if (__builtin_stdc_rotate_left ((unsigned _BitInt(2)) 0, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 1, (_BitInt(27)) 1) != 2uwb + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(2)) 0, 0), unsigned _BitInt(2)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 1, 1) != 2 + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(2)) 1, (unsigned _BitInt(2)) 1), unsigned _BitInt(2)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 2, 1) != 1) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0uwb, 0) != 0 + || __builtin_stdc_rotate_right (1uwb, 0) != 1uwb + || !expr_has_type (__builtin_stdc_rotate_right (0uwb, 0), unsigned _BitInt(1))) + __builtin_abort (); + if (__builtin_stdc_rotate_right ((unsigned _BitInt(2)) 0, (_BitInt(3)) 0) != 0 + || __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 1, 1) != 2uwb + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(2)) 0, 0), unsigned _BitInt(2)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 1, 1) != 2 + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(2)) 1, 1), unsigned _BitInt(2)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 2, 1) != 1) + __builtin_abort (); + if (__builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0U, 0) != 0 + || __builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0x43256567547ULL, 0) != ((unsigned _BitInt(59)) 0x43256567547ULL) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0U, 0), unsigned _BitInt(59)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(59)) 1U, 57) != ((unsigned _BitInt(59)) 1U << 57) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(59)) 1U, 57), unsigned _BitInt(59)) + || __builtin_stdc_rotate_left (~(unsigned _BitInt(59)) 1ULL, 53) != ~(unsigned _BitInt(59)) 0x20000000000000ULL + || __builtin_stdc_rotate_left (1uwb + ((unsigned _BitInt(59)) 1U << 58), 1) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 0x43256567547ULL, 0) != ((unsigned _BitInt(59)) 0x43256567547ULL) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(59)) 0U, 0), unsigned _BitInt(59)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 1ULL << 57, 55) != 4U + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(59)) 1U << 57, 55), unsigned _BitInt(59)) + || __builtin_stdc_rotate_right (~(unsigned _BitInt(59)) 1ULL, 53) != ~((unsigned _BitInt(59)) 1 << 6) + || __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 3ULL, 1) != 1uwb + ((unsigned _BitInt(59)) 1U << 58)) + __builtin_abort (); +#endif +#if __BITINT_MAXWIDTH__ >= 512 + if (__builtin_stdc_rotate_left ((unsigned _BitInt(510)) 0U, (_BitInt(503)) 0) != 0 + || __builtin_stdc_rotate_left (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || __builtin_stdc_rotate_left (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 510) != (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(510)) 0U, 0), unsigned _BitInt(510)) + || __builtin_stdc_rotate_left ((unsigned _BitInt(510)) 1U, 508) != ((unsigned _BitInt(510)) 1U << 508) + || !expr_has_type (__builtin_stdc_rotate_left ((unsigned _BitInt(510)) 1U, (unsigned _BitInt(505)) 508), unsigned _BitInt(510)) + || __builtin_stdc_rotate_left (~(unsigned _BitInt(510)) 1ULL, 53) != ~(unsigned _BitInt(510)) 0x20000000000000ULL + || __builtin_stdc_rotate_left (1uwb + ((unsigned _BitInt(510)) 1U << 509), 1) != 3 + || __builtin_stdc_rotate_left (1uwb + ((unsigned _BitInt(510)) 1U << 509), 511U) != 3) + __builtin_abort (); + if (__builtin_stdc_rotate_right (0ULL, 0) != 0 + || __builtin_stdc_rotate_right (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 0) != (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || __builtin_stdc_rotate_right (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL, 510U * 2) != (((unsigned _BitInt(510)) 0x43256567547ULL) << 64 | 0xdc897143985734baULL) + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(510)) 0U, 0), unsigned _BitInt(510)) + || __builtin_stdc_rotate_right ((unsigned _BitInt(510)) 1ULL << 508, 503) != 32U + || !expr_has_type (__builtin_stdc_rotate_right ((unsigned _BitInt(510)) 1ULL << 508, 503), unsigned _BitInt(510)) + || __builtin_stdc_rotate_right (~(unsigned _BitInt(510)) 1ULL, 499) != ~((unsigned _BitInt(510)) 1 << 11) + || __builtin_stdc_rotate_right ((unsigned _BitInt(510)) 3ULL, 1) != 1uwb + ((unsigned _BitInt(510)) 1U << 509) + || __builtin_stdc_rotate_right ((unsigned _BitInt(510)) 3ULL, 511) != 1uwb + ((unsigned _BitInt(510)) 1U << 509)) + __builtin_abort (); +#endif +} --- gcc/testsuite/gcc.dg/builtin-stdc-rotate-2.c.jj 2024-10-26 11:52:52.341892555 +0200 +++ gcc/testsuite/gcc.dg/builtin-stdc-rotate-2.c 2024-10-26 11:52:52.341892555 +0200 @@ -0,0 +1,70 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (void) +{ + typedef int V __attribute__ ((vector_size (4 * sizeof (int)))); + struct S { int s; }; + enum E { E0, E1 }; + __builtin_stdc_rotate_left (0.0f, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0.0, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0.0L, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left ((V) {}, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left ((struct S) { 0 }, 0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_left'" } */ + __builtin_stdc_rotate_left (0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_left'" } */ + __builtin_stdc_rotate_left (0U, 0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_left'" } */ + __builtin_stdc_rotate_left ((_Bool) 0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_left' has boolean type" } */ + __builtin_stdc_rotate_left ((enum E) E0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_left' has enumerated type" } */ + __builtin_stdc_rotate_left (0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_left' has signed type" } */ + __builtin_stdc_rotate_left (0U, 0.0f); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, 0.0); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, 0.0L); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, (V) {}); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, (struct S) { 0 }); /* { dg-error "'__builtin_stdc_rotate_left' operand not an integral type" } */ + __builtin_stdc_rotate_left (0U, (enum E) E0); /* { dg-error "argument 2 in call to function '__builtin_stdc_rotate_left' has enumerated type" } */ + __builtin_stdc_rotate_right (0.0f, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0.0, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0.0L, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right ((V) {}, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right ((struct S) { 0 }, 0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_right'" } */ + __builtin_stdc_rotate_right (0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_right'" } */ + __builtin_stdc_rotate_right (0U, 0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_rotate_right'" } */ + __builtin_stdc_rotate_right ((_Bool) 0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_right' has boolean type" } */ + __builtin_stdc_rotate_right ((enum E) E0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_right' has enumerated type" } */ + __builtin_stdc_rotate_right (0, 0); /* { dg-error "argument 1 in call to function '__builtin_stdc_rotate_right' has signed type" } */ + __builtin_stdc_rotate_right (0U, 0.0f); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, 0.0); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, 0.0L); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, (V) {}); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, (struct S) { 0 }); /* { dg-error "'__builtin_stdc_rotate_right' operand not an integral type" } */ + __builtin_stdc_rotate_right (0U, (enum E) E0); /* { dg-error "argument 2 in call to function '__builtin_stdc_rotate_right' has enumerated type" } */ + __builtin_stdc_rotate_left ((unsigned char) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right ((unsigned char) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left ((unsigned short) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right ((unsigned short) 0, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left (0U, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right (0U, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left (0UL, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right (0UL, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_left (0ULL, -1); /* { dg-warning "rotate count is negative" } */ + __builtin_stdc_rotate_right (0ULL, -1); /* { dg-warning "rotate count is negative" } */ +#ifdef __SIZEOF_INT128__ + __builtin_stdc_rotate_left ((unsigned __int128) 0, -1); /* { dg-warning "rotate count is negative" "" { target int128 } } */ + __builtin_stdc_rotate_right ((unsigned __int128) 0, -1); /* { dg-warning "rotate count is negative" "" { target int128 } } */ +#endif +#if __BITINT_MAXWIDTH__ >= 64 + __builtin_stdc_rotate_left (0uwb, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_right (0uwb, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_left ((unsigned _BitInt(2)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(2)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_left ((unsigned _BitInt(59)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(59)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint } } */ +#endif +#if __BITINT_MAXWIDTH__ >= 575 + __builtin_stdc_rotate_left ((unsigned _BitInt(525)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint575 } } */ + __builtin_stdc_rotate_right ((unsigned _BitInt(525)) 0, -1); /* { dg-warning "rotate count is negative" "" { target bitint575 } } */ +#endif +} --- gcc/testsuite/gcc.dg/ubsan/builtin-stdc-rotate-1.c.jj 2024-10-26 12:08:49.361362620 +0200 +++ gcc/testsuite/gcc.dg/ubsan/builtin-stdc-rotate-1.c 2024-10-26 12:12:16.435435374 +0200 @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=shift -std=c2y" } */ + +int +main () +{ + int a = -42; + unsigned b = 42; + unsigned c = __builtin_stdc_rotate_left (b, a); + unsigned d = __builtin_stdc_rotate_right (b, a - 1); + volatile int e = c + d; +} +/* { dg-output "shift exponent -42 is negative\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*shift exponent -43 is negative" } */ --- gcc/testsuite/gcc.dg/ubsan/builtin-stdc-rotate-2.c.jj 2024-10-26 12:12:24.586320150 +0200 +++ gcc/testsuite/gcc.dg/ubsan/builtin-stdc-rotate-2.c 2024-10-26 12:14:52.270232462 +0200 @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=shift -fno-sanitize-recover=shift -std=c2y" } */ + +int +main () +{ + int a = sizeof (unsigned) * __CHAR_BIT__ + 1; + unsigned b = 42; + unsigned c = __builtin_stdc_rotate_left (b, a); + unsigned d = __builtin_stdc_rotate_right (b, a); + volatile int e = c + d; + if (c != 84 || d != 21) + __builtin_abort (); +}