From patchwork Wed Sep 20 07:17:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 142258 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:172:b0:3f2:4152:657d with SMTP id h50csp3937781vqi; Wed, 20 Sep 2023 00:18:10 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHGBB3nimicsSHQkZxt6ir+cxLie13a3hZ6wkSosffY9AcBpKesSFpskxhNDkj29ubObqPj X-Received: by 2002:a17:906:7696:b0:9ae:506f:391 with SMTP id o22-20020a170906769600b009ae506f0391mr297386ejm.23.1695194290327; Wed, 20 Sep 2023 00:18:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695194290; cv=none; d=google.com; s=arc-20160816; b=hcljyXSGVm7FicL9XQ/asvGYXm8/hmNkvC5yZ1HdPeu0kMQmuzPoCxRmVDJzlnErYg 6uESxIPepRMWMewwiwneNqLQ21MgiiZOiipzTA1v7sPnqeJ6nSpIvFfyec31yRn6zYR6 qi5BNNKTrmrJa5ghZRrN6rOpTevYUfyzbOmcykiE9J3Gk6nRPN1BbByJ4sBUl8tiFFVh A+3Vt+qqWlkowTHzDi9F/x3s6ptTXwhe4fB4d9C5tArVG4EiHewd0AOT33/wue7FLdWM t10SYuFjfbxODdt8Ik6sUBb3zW1Zd49Hrw+CjKw8Dv+5AlwQU5zJ/WrSHwseWkoZlVIT pbnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:reply-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-disposition:in-reply-to :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature:dmarc-filter:delivered-to; bh=WeMZpSsob7doTCMAQvd+apbrEyywrPLaNO3sGlMJLVA=; fh=Ey8LQmxBYWKCHXwTUssvYYzu6GuhSOQeCgYnneWJrpc=; b=k++nOUs39YkMWnQpkhHkF/oSHPns91i+GYeEHSb9KIxBSBNcvrlCuUF3hVPUBnae3r egVBpFpzt/iBOU7L8piCzq8L4xadZD7Iywk0nuwPGy1CEWZL4S0uTu2OTLA1Ovmuw6pd 5YflzKTXPrgAZbIWpBDi4cPRv3UamthL8B1jdcfa4I9QFqV0NTbmvzKkYSs0p4ecin5R O2Q0cgaL7EXYtSCvglVD64vlkvQzoLNhGxZnqTTZbZoXKS+l2fsZRNSf4iGE+J6lb4Iw cxJ3GIWL3AX3VXjJbcHXUdG1cXInfI84VXhuzeqDkTweE8stgFLXaBJqxksR4cOYElwB 05SQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@redhat.com header.s=mimecast20190719 header.b=QgsL5vnM; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id w8-20020a1709067c8800b0099c971ba282si11870129ejo.99.2023.09.20.00.18.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Sep 2023 00:18:10 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@redhat.com header.s=mimecast20190719 header.b=QgsL5vnM; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3FABF38582B7 for ; Wed, 20 Sep 2023 07:18:02 +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.133.124]) by sourceware.org (Postfix) with ESMTPS id A16EE3858D20 for ; Wed, 20 Sep 2023 07:17:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A16EE3858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695194256; 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=JYe7oPKF5IULyWpY2hl6lRKk+SOU69xda6o8HFVvTsg=; b=QgsL5vnMadxfngsPvUpP+EKEy804j43ZthEPYhyzmfh8CpfnfDo3IRWhDUD9TU3LJRqffE lsDawzXprKGRFIgGGQQlBTXlabmNVc4BMyCvClfxpxKx/BSWxmYQ9t8C2/43jgWZr310av CVPpCqsXcTyUn6iILfiBqJrcAIUarGs= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-168-Gwl1BKKENvKiXyik1w-Mlg-1; Wed, 20 Sep 2023 03:17:33 -0400 X-MC-Unique: Gwl1BKKENvKiXyik1w-Mlg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 149423C0CF0E; Wed, 20 Sep 2023 07:17:33 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.193.241]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AD68D140E962; Wed, 20 Sep 2023 07:17:32 +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 38K7HT4r1140987 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Wed, 20 Sep 2023 09:17:30 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 38K7HTwA1140986; Wed, 20 Sep 2023 09:17:29 +0200 Date: Wed, 20 Sep 2023 09:17:28 +0200 From: Jakub Jelinek To: Joseph Myers Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c, c++, v3: Accept __builtin_classify_type (typename) Message-ID: References: <3c117643-59c-8cd7-f6a6-3663fb524dde@codesourcery.com> MIME-Version: 1.0 In-Reply-To: <3c117643-59c-8cd7-f6a6-3663fb524dde@codesourcery.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, RCVD_IN_SBL_CSS, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=no 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+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1777540048479844268 X-GMAIL-MSGID: 1777540048479844268 On Mon, Sep 18, 2023 at 09:25:19PM +0000, Joseph Myers wrote: > > I'd like to ping this patch. > > The C++ FE part has been approved by Jason already with a minor change > > I've made in my copy. > > Are the remaining parts ok for trunk? > > In the C front-end changes, since you end up discarding any side effects > from the type, I'd expect use of in_alignof to be more appropriate than > in_typeof (and thus not needing to use pop_maybe_used). So like this? Bootstrapped/regtested again on x86_64-linux and i686-linux. 2023-09-20 Jakub Jelinek gcc/ * builtins.h (type_to_class): Declare. * builtins.cc (type_to_class): No longer static. Return int rather than enum. * doc/extend.texi (__builtin_classify_type): Document. gcc/c/ * c-parser.cc (c_parser_postfix_expression_after_primary): Parse __builtin_classify_type call with typename as argument. gcc/cp/ * parser.cc (cp_parser_postfix_expression): Parse __builtin_classify_type call with typename as argument. * pt.cc (tsubst_copy_and_build): Handle __builtin_classify_type with dependent typename as argument. gcc/testsuite/ * c-c++-common/builtin-classify-type-1.c: New test. * g++.dg/ext/builtin-classify-type-1.C: New test. * g++.dg/ext/builtin-classify-type-2.C: New test. * gcc.dg/builtin-classify-type-1.c: New test. Jakub --- gcc/builtins.h.jj 2023-01-03 00:20:34.856089856 +0100 +++ gcc/builtins.h 2023-06-12 09:35:20.841902572 +0200 @@ -156,5 +156,6 @@ extern internal_fn associated_internal_f extern internal_fn replacement_internal_fn (gcall *); extern bool builtin_with_linkage_p (tree); +extern int type_to_class (tree); #endif /* GCC_BUILTINS_H */ --- gcc/builtins.cc.jj 2023-05-20 15:31:09.066663352 +0200 +++ gcc/builtins.cc 2023-06-12 09:35:31.709751296 +0200 @@ -113,7 +113,6 @@ static rtx expand_builtin_apply_args (vo static rtx expand_builtin_apply_args_1 (void); static rtx expand_builtin_apply (rtx, rtx, rtx); static void expand_builtin_return (rtx); -static enum type_class type_to_class (tree); static rtx expand_builtin_classify_type (tree); static rtx expand_builtin_mathfn_3 (tree, rtx, rtx); static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx); @@ -1852,7 +1851,7 @@ expand_builtin_return (rtx result) /* Used by expand_builtin_classify_type and fold_builtin_classify_type. */ -static enum type_class +int type_to_class (tree type) { switch (TREE_CODE (type)) --- gcc/doc/extend.texi.jj 2023-06-10 19:58:26.197478291 +0200 +++ gcc/doc/extend.texi 2023-06-12 18:06:24.629413024 +0200 @@ -14354,6 +14354,30 @@ need not be a constant. @xref{Object Si description of the function. @enddefbuiltin +@defbuiltin{int __builtin_classify_type (@var{arg})} +@defbuiltinx{int __builtin_classify_type (@var{type})} +The @code{__builtin_classify_type} returns a small integer with a category +of @var{arg} argument's type, like void type, integer type, enumeral type, +boolean type, pointer type, reference type, offset type, real type, complex +type, function type, method type, record type, union type, array type, +string type, etc. When the argument is an expression, for +backwards compatibility reason the argument is promoted like arguments +passed to @code{...} in varargs function, so some classes are never returned +in certain languages. Alternatively, the argument of the built-in +function can be a typename, such as the @code{typeof} specifier. + +@smallexample +int a[2]; +__builtin_classify_type (a) == __builtin_classify_type (int[5]); +__builtin_classify_type (a) == __builtin_classify_type (void*); +__builtin_classify_type (typeof (a)) == __builtin_classify_type (int[5]); +@end smallexample + +The first comparison will never be true, as @var{a} is implicitly converted +to pointer. The last two comparisons will be true as they classify +pointers in the second case and arrays in the last case. +@enddefbuiltin + @defbuiltin{double __builtin_huge_val (void)} Returns a positive infinity, if supported by the floating-point format, else @code{DBL_MAX}. This function is suitable for implementing the --- gcc/c/c-parser.cc.jj 2023-06-10 19:22:15.577205685 +0200 +++ gcc/c/c-parser.cc 2023-06-12 17:32:31.007413019 +0200 @@ -11213,6 +11213,29 @@ c_parser_postfix_expression_after_primar literal_zero_mask = 0; if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) exprlist = NULL; + else if (TREE_CODE (expr.value) == FUNCTION_DECL + && fndecl_built_in_p (expr.value, BUILT_IN_CLASSIFY_TYPE) + && c_parser_next_tokens_start_typename (parser, + cla_prefer_id)) + { + /* __builtin_classify_type (type) */ + c_inhibit_evaluation_warnings++; + in_alignof++; + struct c_type_name *type = c_parser_type_name (parser); + c_inhibit_evaluation_warnings--; + in_alignof--; + struct c_typespec ret; + ret.expr = NULL_TREE; + ret.spec = error_mark_node; + ret.expr_const_operands = false; + if (type != NULL) + ret.spec = groktypename (type, &ret.expr, + &ret.expr_const_operands); + parens.skip_until_found_close (parser); + expr.value = build_int_cst (integer_type_node, + type_to_class (ret.spec)); + break; + } else exprlist = c_parser_expr_list (parser, true, false, &origtypes, sizeof_arg_loc, sizeof_arg, --- gcc/cp/parser.cc.jj 2023-06-06 20:02:35.631211230 +0200 +++ gcc/cp/parser.cc 2023-06-12 16:19:04.892202240 +0200 @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. #include "c-family/known-headers.h" #include "contracts.h" #include "bitmap.h" +#include "builtins.h" /* The lexer. */ @@ -7850,6 +7851,47 @@ cp_parser_postfix_expression (cp_parser = parser->non_integral_constant_expression_p; parser->integral_constant_expression_p = false; } + else if (TREE_CODE (stripped_expression) == FUNCTION_DECL + && fndecl_built_in_p (stripped_expression, + BUILT_IN_CLASSIFY_TYPE)) + { + /* __builtin_classify_type (type) */ + auto cl1 = make_temp_override + (parser->type_definition_forbidden_message, + G_("types may not be defined in " + "%<__builtin_classify_type%> calls")); + auto cl2 = make_temp_override + (parser->type_definition_forbidden_message_arg, + NULL); + auto cl3 = make_temp_override (parser->in_type_id_in_expr_p, + true); + cp_unevaluated uev; + cp_parser_parse_tentatively (parser); + matching_parens parens; + parens.consume_open (parser); + tree type = cp_parser_type_id (parser); + parens.require_close (parser); + if (cp_parser_parse_definitely (parser)) + { + if (dependent_type_p (type)) + { + postfix_expression = build_vl_exp (CALL_EXPR, 4); + CALL_EXPR_FN (postfix_expression) + = stripped_expression; + CALL_EXPR_STATIC_CHAIN (postfix_expression) = type; + CALL_EXPR_ARG (postfix_expression, 0) + = build_min (SIZEOF_EXPR, size_type_node, type); + TREE_TYPE (postfix_expression) = integer_type_node; + } + else + { + postfix_expression + = build_int_cst (integer_type_node, + type_to_class (type)); + } + break; + } + } args = (cp_parser_parenthesized_expression_list (parser, non_attr, /*cast_p=*/false, /*allow_expansion_p=*/true, --- gcc/cp/pt.cc.jj 2023-06-06 20:02:35.000000000 +0200 +++ gcc/cp/pt.cc 2023-06-12 16:19:06.495180108 +0200 @@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. #include "gcc-rich-location.h" #include "selftest.h" #include "target.h" +#include "builtins.h" /* The type of functions taking a tree, and some additional data, and returning an int. */ @@ -20963,6 +20964,25 @@ tsubst_copy_and_build (tree t, /*done=*/false, /*address_p=*/false); } + else if (CALL_EXPR_STATIC_CHAIN (t) + && TREE_CODE (function) == FUNCTION_DECL + && fndecl_built_in_p (function, BUILT_IN_CLASSIFY_TYPE)) + { + tree type = tsubst (CALL_EXPR_STATIC_CHAIN (t), args, complain, + in_decl); + if (dependent_type_p (type)) + { + ret = build_vl_exp (CALL_EXPR, 4); + CALL_EXPR_FN (ret) = function; + CALL_EXPR_STATIC_CHAIN (ret) = type; + CALL_EXPR_ARG (ret, 0) + = build_min (SIZEOF_EXPR, size_type_node, type); + TREE_TYPE (ret) = integer_type_node; + } + else + ret = build_int_cst (integer_type_node, type_to_class (type)); + RETURN (ret); + } else if (koenig_p && (identifier_p (function) || (TREE_CODE (function) == TEMPLATE_ID_EXPR --- gcc/testsuite/c-c++-common/builtin-classify-type-1.c.jj 2023-06-12 14:27:19.087986210 +0200 +++ gcc/testsuite/c-c++-common/builtin-classify-type-1.c 2023-06-12 16:23:07.029859079 +0200 @@ -0,0 +1,105 @@ +/* { dg-do run { target { c || c++11 } } } */ + +#if !defined(__cplusplus) && __STDC_VERSION__ <= 201710L +#define static_assert _Static_assert +#define bool _Bool +#define false ((_Bool) 0) +#endif +#ifdef __cplusplus +extern "C" void abort (); +#else +extern void abort (void); +#endif + +int +main () +{ + enum E { E1 } e = E1; + struct S { int s; } s = { 0 }; + union U { int u; } u = { 0 }; + int a[2] = { 0, 0 }; + bool b = false; + const char *p = (const char *) 0; + float f = 0.0; + _Complex double c = 0.0; +#ifdef __cplusplus + struct T { void foo (); }; + int &r = a[0]; + int S::*q = &S::s; +#endif + static_assert (__builtin_classify_type (void) == 0, ""); + static_assert (__builtin_classify_type (int) == 1, ""); + static_assert (__builtin_classify_type (enum E) == 3, ""); + static_assert (__builtin_classify_type (bool) == 4, ""); + static_assert (__builtin_classify_type (const char *) == 5, ""); +#ifdef __cplusplus + static_assert (__builtin_classify_type (int &) == 6, ""); + static_assert (__builtin_classify_type (int &&) == 6, ""); + static_assert (__builtin_classify_type (int S::*) == 7, ""); +#endif + static_assert (__builtin_classify_type (float) == 8, ""); + static_assert (__builtin_classify_type (_Complex double) == 9, ""); + static_assert (__builtin_classify_type (int (int, int)) == 10, ""); + static_assert (__builtin_classify_type (struct S) == 12, ""); + static_assert (__builtin_classify_type (union U) == 13, ""); + static_assert (__builtin_classify_type (int [2]) == 14, ""); + static_assert (__builtin_classify_type (__typeof__ (a[0])) == 1, ""); + static_assert (__builtin_classify_type (__typeof__ (e)) == 3, ""); + static_assert (__builtin_classify_type (__typeof__ (b)) == 4, ""); + static_assert (__builtin_classify_type (__typeof__ (p)) == 5, ""); +#ifdef __cplusplus + static_assert (__builtin_classify_type (decltype (r)) == 6, ""); + static_assert (__builtin_classify_type (__typeof__ (q)) == 7, ""); +#endif + static_assert (__builtin_classify_type (__typeof__ (f)) == 8, ""); + static_assert (__builtin_classify_type (__typeof__ (c)) == 9, ""); + static_assert (__builtin_classify_type (__typeof__ (main)) == 10, ""); + static_assert (__builtin_classify_type (__typeof__ (s)) == 12, ""); + static_assert (__builtin_classify_type (__typeof__ (u)) == 13, ""); + static_assert (__builtin_classify_type (__typeof__ (a)) == 14, ""); +#ifndef __cplusplus + static_assert (__builtin_classify_type (a[0]) == 1, ""); + static_assert (__builtin_classify_type (e) == 1, ""); + static_assert (__builtin_classify_type (b) == 1, ""); + static_assert (__builtin_classify_type (p) == 5, ""); + static_assert (__builtin_classify_type (f) == 8, ""); + static_assert (__builtin_classify_type (c) == 9, ""); + static_assert (__builtin_classify_type (main) == 5, ""); + static_assert (__builtin_classify_type (s) == 12, ""); + static_assert (__builtin_classify_type (u) == 13, ""); + static_assert (__builtin_classify_type (a) == 5, ""); +#endif + if (__builtin_classify_type (a[0]) != 1) + abort (); +#ifdef __cplusplus + if (__builtin_classify_type (e) != 3) + abort (); + if (__builtin_classify_type (b) != 4) + abort (); +#else + if (__builtin_classify_type (e) != 1) + abort (); + if (__builtin_classify_type (b) != 1) + abort (); +#endif + if (__builtin_classify_type (p) != 5) + abort (); +#ifdef __cplusplus + if (__builtin_classify_type (r) != 1) + abort (); + if (__builtin_classify_type (q) != 7) + abort (); +#endif + if (__builtin_classify_type (f) != 8) + abort (); + if (__builtin_classify_type (c) != 9) + abort (); + if (__builtin_classify_type (main) != 5) + abort (); + if (__builtin_classify_type (s) != 12) + abort (); + if (__builtin_classify_type (u) != 13) + abort (); + if (__builtin_classify_type (a) != 5) + abort (); +} --- gcc/testsuite/g++.dg/ext/builtin-classify-type-1.C.jj 2023-06-12 15:03:37.488813774 +0200 +++ gcc/testsuite/g++.dg/ext/builtin-classify-type-1.C 2023-06-12 16:24:17.787882132 +0200 @@ -0,0 +1,149 @@ +// { dg-do run { target c++11 } } + +extern "C" void abort (); + +template +void +foo () +{ + enum E { E1 } e = E1; + struct S { int s; } s = { 0 }; + union U { int u; } u = { 0 }; + int a[2] = { 0, 0 }; + bool b = false; + const char *p = (const char *) 0; + float f = 0.0; + _Complex double c = 0.0; + struct T { void foo (); }; + int &r = a[0]; + int S::*q = &S::s; + static_assert (__builtin_classify_type (void) == 0, ""); + static_assert (__builtin_classify_type (int) == 1, ""); + static_assert (__builtin_classify_type (enum E) == 3, ""); + static_assert (__builtin_classify_type (bool) == 4, ""); + static_assert (__builtin_classify_type (const char *) == 5, ""); + static_assert (__builtin_classify_type (int &) == 6, ""); + static_assert (__builtin_classify_type (int &&) == 6, ""); + static_assert (__builtin_classify_type (int S::*) == 7, ""); + static_assert (__builtin_classify_type (float) == 8, ""); + static_assert (__builtin_classify_type (_Complex double) == 9, ""); + static_assert (__builtin_classify_type (int (int, int)) == 10, ""); + static_assert (__builtin_classify_type (struct S) == 12, ""); + static_assert (__builtin_classify_type (union U) == 13, ""); + static_assert (__builtin_classify_type (int [2]) == 14, ""); + static_assert (__builtin_classify_type (__typeof__ (a[0])) == 1, ""); + static_assert (__builtin_classify_type (__typeof__ (e)) == 3, ""); + static_assert (__builtin_classify_type (__typeof__ (b)) == 4, ""); + static_assert (__builtin_classify_type (__typeof__ (p)) == 5, ""); + static_assert (__builtin_classify_type (decltype (r)) == 6, ""); + static_assert (__builtin_classify_type (__typeof__ (q)) == 7, ""); + static_assert (__builtin_classify_type (__typeof__ (f)) == 8, ""); + static_assert (__builtin_classify_type (__typeof__ (c)) == 9, ""); + static_assert (__builtin_classify_type (__typeof__ (abort)) == 10, ""); + static_assert (__builtin_classify_type (__typeof__ (s)) == 12, ""); + static_assert (__builtin_classify_type (__typeof__ (u)) == 13, ""); + static_assert (__builtin_classify_type (__typeof__ (a)) == 14, ""); + if (__builtin_classify_type (a[0]) != 1) + abort (); + if (__builtin_classify_type (e) != 3) + abort (); + if (__builtin_classify_type (b) != 4) + abort (); + if (__builtin_classify_type (p) != 5) + abort (); + if (__builtin_classify_type (r) != 1) + abort (); + if (__builtin_classify_type (q) != 7) + abort (); + if (__builtin_classify_type (f) != 8) + abort (); + if (__builtin_classify_type (c) != 9) + abort (); + if (__builtin_classify_type (abort) != 5) + abort (); + if (__builtin_classify_type (s) != 12) + abort (); + if (__builtin_classify_type (u) != 13) + abort (); + if (__builtin_classify_type (a) != 5) + abort (); +} + +template +void +bar () +{ + E e = (E) 0; + S s = { 0 }; + U u = { 0 }; + A a = { 0, 0 }; + B b = false; + P p = (P) 0; + F f = 0.0; + C c = 0.0; + R1 r = a[0]; + PM q = &S::s; + static_assert (__builtin_classify_type (V) == 0, ""); + static_assert (__builtin_classify_type (I) == 1, ""); + static_assert (__builtin_classify_type (E) == 3, ""); + static_assert (__builtin_classify_type (B) == 4, ""); + static_assert (__builtin_classify_type (P) == 5, ""); + static_assert (__builtin_classify_type (R1) == 6, ""); + static_assert (__builtin_classify_type (R2) == 6, ""); + static_assert (__builtin_classify_type (PM) == 7, ""); + static_assert (__builtin_classify_type (F) == 8, ""); + static_assert (__builtin_classify_type (C) == 9, ""); + static_assert (__builtin_classify_type (FN) == 10, ""); + static_assert (__builtin_classify_type (S) == 12, ""); + static_assert (__builtin_classify_type (U) == 13, ""); + static_assert (__builtin_classify_type (A) == 14, ""); + static_assert (__builtin_classify_type (__typeof__ (a[0])) == 1, ""); + static_assert (__builtin_classify_type (__typeof__ (e)) == 3, ""); + static_assert (__builtin_classify_type (__typeof__ (b)) == 4, ""); + static_assert (__builtin_classify_type (__typeof__ (p)) == 5, ""); + static_assert (__builtin_classify_type (decltype (r)) == 6, ""); + static_assert (__builtin_classify_type (__typeof__ (q)) == 7, ""); + static_assert (__builtin_classify_type (__typeof__ (f)) == 8, ""); + static_assert (__builtin_classify_type (__typeof__ (c)) == 9, ""); + static_assert (__builtin_classify_type (__typeof__ (abort)) == 10, ""); + static_assert (__builtin_classify_type (__typeof__ (s)) == 12, ""); + static_assert (__builtin_classify_type (__typeof__ (u)) == 13, ""); + static_assert (__builtin_classify_type (__typeof__ (a)) == 14, ""); + if (__builtin_classify_type (a[0]) != 1) + abort (); + if (__builtin_classify_type (e) != 3) + abort (); + if (__builtin_classify_type (b) != 4) + abort (); + if (__builtin_classify_type (p) != 5) + abort (); + if (__builtin_classify_type (r) != 1) + abort (); + if (__builtin_classify_type (q) != 7) + abort (); + if (__builtin_classify_type (f) != 8) + abort (); + if (__builtin_classify_type (c) != 9) + abort (); + if (__builtin_classify_type (abort) != 5) + abort (); + if (__builtin_classify_type (s) != 12) + abort (); + if (__builtin_classify_type (u) != 13) + abort (); + if (__builtin_classify_type (a) != 5) + abort (); +} + +int +main () +{ + enum E { E1 }; + struct S { int s; }; + union U { int u; }; + foo <0> (); + bar (); +} --- gcc/testsuite/g++.dg/ext/builtin-classify-type-2.C.jj 2023-06-12 16:28:17.120577700 +0200 +++ gcc/testsuite/g++.dg/ext/builtin-classify-type-2.C 2023-06-12 16:29:57.860186807 +0200 @@ -0,0 +1,11 @@ +// { dg-do compile { target c++11 } } +// { dg-options "" } + +void +foo (int n) +{ + __builtin_classify_type (enum E { E1, E2 }); // { dg-error "types may not be defined in '__builtin_classify_type' calls" } + __builtin_classify_type (struct S { int s; });// { dg-error "types may not be defined in '__builtin_classify_type' calls" } + __builtin_classify_type (union U { int u; }); // { dg-error "types may not be defined in '__builtin_classify_type' calls" } + __builtin_classify_type (int [2 * n + 36]); +} --- gcc/testsuite/gcc.dg/builtin-classify-type-1.c.jj 2023-06-12 17:28:47.118495177 +0200 +++ gcc/testsuite/gcc.dg/builtin-classify-type-1.c 2023-06-12 17:43:46.420114514 +0200 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (int n) +{ + _Static_assert (__builtin_classify_type (enum E { E1, E2 }) == 3, ""); + _Static_assert (__builtin_classify_type (struct S { int s; }) == 12, ""); + _Static_assert (__builtin_classify_type (union U { int u; }) == 13, ""); + _Static_assert (__builtin_classify_type (int [2 * n + 36]) == 14, ""); +}