From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 03DDC3858D1E for ; Fri, 30 Sep 2022 19:51:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 03DDC3858D1E 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=1664567515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=S5E3mVsIgx6z7PCx9hciU+lnHUJeh4ww0ib2+b5QeAk=; b=QBETSosHfApTK6pE6uXAVmFN8MRM24WVaKp2Z2wpEReZf6u3jofvS0A9PGxXK+zyaAEP2W 9OF47QO8emT95pH3V143iYv6N9zSoPcWxT8FuGFHbZ+RXz8glKT1jnLT29BZQbZI2aRiXN 3afdj9RXDn9uF/VKoRv3qVAab2YY+yQ= Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-541-6eS0HTdGPJS3UPd5zo9gBw-1; Fri, 30 Sep 2022 15:51:51 -0400 X-MC-Unique: 6eS0HTdGPJS3UPd5zo9gBw-1 Received: by mail-qk1-f198.google.com with SMTP id bl17-20020a05620a1a9100b006cdf19243acso4474749qkb.4 for ; Fri, 30 Sep 2022 12:51:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date; bh=S5E3mVsIgx6z7PCx9hciU+lnHUJeh4ww0ib2+b5QeAk=; b=Y0tAw2/s0nLpsGOs+a0EIhz59zBY/ZLyVPSKyvPQ3rfztg1rm7z5ZSh28Dht/QZwNc MpRJbZkNQbkcyBwqHQNLNs4qRQ34cuEL6RYElshEIl1ySN8nIpuM++iW+9Rnjr7hSZMm FI0z1PqPlRWQU3OtC64KppkCMDLnPtzkjc1xW7xlkBtsIFEEPAeNSeaUYkflbDNmRPA7 xxMlbxjfigBW0yznR92hsAQidXQTxmU9r/Y2CNKikm7o9JdrYgQwa4i0Zi/Brv5Hp5Lv 402o3WP4fAUqX9VA5RZfN89uoS0s/n520qyFQRlOHwPxQBkNOThIznEb74KjR+JC4drK 04ow== X-Gm-Message-State: ACrzQf3ejZbWGcT4DBP2qu33NkzbW0HOlM+EwuLaWl+YEbtJ4B68lJAV VbFrz6h5PI+2pi/KgvVBbJTBSztiRPboDIDD5qQtmyM6BF/ze0DHxi1OOxhY+CGM7XnfX81h4wn tM4P6eFrpmRGSOtIN7w== X-Received: by 2002:a05:622a:3cc:b0:35d:4df0:2ed4 with SMTP id k12-20020a05622a03cc00b0035d4df02ed4mr8191911qtx.204.1664567510393; Fri, 30 Sep 2022 12:51:50 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5GiKVe75dh9jf9z6DlsPvz0/beFb004hHI8izoEOb5WmTvqx0bhcF8XpgAWlvnhWsWUAQpag== X-Received: by 2002:a05:622a:3cc:b0:35d:4df0:2ed4 with SMTP id k12-20020a05622a03cc00b0035d4df02ed4mr8191893qtx.204.1664567509961; Fri, 30 Sep 2022 12:51:49 -0700 (PDT) Received: from [192.168.1.101] (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id cx4-20020a05620a51c400b006bc56c063fcsm3072591qkb.62.2022.09.30.12.51.49 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 30 Sep 2022 12:51:49 -0700 (PDT) Message-ID: <4d2b9810-0093-ca32-0c76-c6bf1619a10b@redhat.com> Date: Fri, 30 Sep 2022 15:51:48 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.1 Subject: Re: [PATCH RFC] c++: streamline process for adding new builtin trait To: Patrick Palka Cc: gcc-patches@gcc.gnu.org, jwakely@redhat.com References: <20220929150504.829703-1-ppalka@redhat.com> <5b78716b-3056-e3f1-2e38-5f7eab29094c@idea> From: Jason Merrill In-Reply-To: <5b78716b-3056-e3f1-2e38-5f7eab29094c@idea> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-13.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,NICE_REPLY_A,RCVD_IN_DNSWL_LOW,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 List-Id: On 9/30/22 11:14, Patrick Palka wrote: > On Thu, 29 Sep 2022, Jason Merrill wrote: > >> On 9/29/22 11:05, Patrick Palka wrote: >>> Adding a new builtin trait currently involves some boilerplate (as can >>> be seen in r13-2956-g9ca147154074a0) of defining corresponding RID_ and >>> CPTK_ enumerators and adding them to various switch statements across >>> many files. The exact switch statements we need to change is determined >>> by whether the proposed trait yields a type or an expression. >>> >>> This RFC patch attempts to streamline this process via a centralized >>> cp-trait.def file for declaring the important parts about a builtin trait >>> (whether it yields a type or an expression, its code, its spelling and >>> its arity) and using this file to automate away the switch statement >>> addition boilerplate. It also converts 9 traits to use this approach >>> by way of example (we can convert all the traits once the design is >>> settled). >>> >>> After this change, the process of adding a new builtin trait is just >>> (modulo tests): declare it in cp-trait.def, define its behavior in >>> finish_trait_type/expr, and handle it in diagnose_trait_expr if it's >>> an expression-yielding trait (this last step is unfortunate but since >>> the switch has no default case, we'll at least get a diagnostic if we >>> forget to do it). >>> >>> Does this look like a good approach? >> >> OK. > > Thanks a lot, I committed the following (which migrates all the > C++-specific traits to the new approach): > > -- >8 -- > > Subject: [PATCH] c++: streamline built-in trait addition process > > Adding a new built-in trait currently involves manual boilerplate > consisting of defining an rid enumerator for the identifier as well as a > corresponding cp_trait_kind enumerator and handling them in various switch > statements, the exact set of which depends on whether the proposed trait > yields (and thus is recognized as) a type or an expression. > > To streamline the process, this patch adds a central cp-trait.def file > that tabulates the essential details about each built-in trait (whether > it yields a type or an expression, its code, its spelling and its arity) > and uses this file to automate away the manual boilerplate. It also > migrates all the existing C++-specific built-in traits to use this > approach. > > After this change, adding a new built-in trait just entails declaring > it in cp-trait.def and defining its behavior in finish_trait_expr/type > (and handling it in diagnose_trait_expr, if it's an expression-yielding > trait). > > gcc/c-family/ChangeLog: > > * c-common.cc (c_common_reswords): Use cp/cp-trait.def to handle > C++ traits. > * c-common.h (enum rid): Likewise. > > gcc/cp/ChangeLog: > > * constraint.cc (diagnose_trait_expr): Likewise. > * cp-objcp-common.cc (names_builtin_p): Likewise. > * cp-tree.h (enum cp_trait_kind): Likewise. > * cxx-pretty-print.cc (pp_cxx_trait): Likewise. > * parser.cc (cp_keyword_starts_decl_specifier_p): Likewise. > (cp_parser_primary_expression): Likewise. > (cp_parser_trait): Likewise. > (cp_parser_simple_type_specifier): Likewise. > * cp-trait.def: New file. > --- > gcc/c-family/c-common.cc | 54 ++------- > gcc/c-family/c-common.h | 33 ++---- > gcc/cp/constraint.cc | 12 +- > gcc/cp/cp-objcp-common.cc | 44 +------- > gcc/cp/cp-trait.def | 106 ++++++++++++++++++ > gcc/cp/cp-tree.h | 46 +------- > gcc/cp/cxx-pretty-print.cc | 126 +-------------------- > gcc/cp/parser.cc | 217 ++++--------------------------------- > 8 files changed, 161 insertions(+), 477 deletions(-) > create mode 100644 gcc/cp/cp-trait.def > > diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc > index 6e0af863a49..3c60a89bfe2 100644 > --- a/gcc/c-family/c-common.cc > +++ b/gcc/c-family/c-common.cc > @@ -378,7 +378,6 @@ const struct c_common_resword c_common_reswords[] = > { "__attribute", RID_ATTRIBUTE, 0 }, > { "__attribute__", RID_ATTRIBUTE, 0 }, > { "__auto_type", RID_AUTO_TYPE, D_CONLY }, > - { "__bases", RID_BASES, D_CXXONLY }, > { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY }, > { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY }, > { "__builtin_call_with_static_chain", > @@ -401,44 +400,12 @@ const struct c_common_resword c_common_reswords[] = > { "__const__", RID_CONST, 0 }, > { "__constinit", RID_CONSTINIT, D_CXXONLY }, > { "__decltype", RID_DECLTYPE, D_CXXONLY }, > - { "__direct_bases", RID_DIRECT_BASES, D_CXXONLY }, > { "__extension__", RID_EXTENSION, 0 }, > { "__func__", RID_C99_FUNCTION_NAME, 0 }, > - { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY }, > - { "__has_nothrow_constructor", RID_HAS_NOTHROW_CONSTRUCTOR, D_CXXONLY }, > - { "__has_nothrow_copy", RID_HAS_NOTHROW_COPY, D_CXXONLY }, > - { "__has_trivial_assign", RID_HAS_TRIVIAL_ASSIGN, D_CXXONLY }, > - { "__has_trivial_constructor", RID_HAS_TRIVIAL_CONSTRUCTOR, D_CXXONLY }, > - { "__has_trivial_copy", RID_HAS_TRIVIAL_COPY, D_CXXONLY }, > - { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY }, > - { "__has_unique_object_representations", RID_HAS_UNIQUE_OBJ_REPRESENTATIONS, > - D_CXXONLY }, > - { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY }, > { "__imag", RID_IMAGPART, 0 }, > { "__imag__", RID_IMAGPART, 0 }, > { "__inline", RID_INLINE, 0 }, > { "__inline__", RID_INLINE, 0 }, > - { "__is_abstract", RID_IS_ABSTRACT, D_CXXONLY }, > - { "__is_aggregate", RID_IS_AGGREGATE, D_CXXONLY }, > - { "__is_base_of", RID_IS_BASE_OF, D_CXXONLY }, > - { "__is_class", RID_IS_CLASS, D_CXXONLY }, > - { "__is_empty", RID_IS_EMPTY, D_CXXONLY }, > - { "__is_enum", RID_IS_ENUM, D_CXXONLY }, > - { "__is_final", RID_IS_FINAL, D_CXXONLY }, > - { "__is_layout_compatible", RID_IS_LAYOUT_COMPATIBLE, D_CXXONLY }, > - { "__is_literal_type", RID_IS_LITERAL_TYPE, D_CXXONLY }, > - { "__is_pointer_interconvertible_base_of", > - RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF, D_CXXONLY }, > - { "__is_pod", RID_IS_POD, D_CXXONLY }, > - { "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY }, > - { "__is_same", RID_IS_SAME_AS, D_CXXONLY }, > - { "__is_same_as", RID_IS_SAME_AS, D_CXXONLY }, > - { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY }, > - { "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY }, > - { "__is_trivially_assignable", RID_IS_TRIVIALLY_ASSIGNABLE, D_CXXONLY }, > - { "__is_trivially_constructible", RID_IS_TRIVIALLY_CONSTRUCTIBLE, D_CXXONLY }, > - { "__is_trivially_copyable", RID_IS_TRIVIALLY_COPYABLE, D_CXXONLY }, > - { "__is_union", RID_IS_UNION, D_CXXONLY }, > { "__label__", RID_LABEL, 0 }, > { "__null", RID_NULL, 0 }, > { "__real", RID_REALPART, 0 }, > @@ -453,7 +420,6 @@ const struct c_common_resword c_common_reswords[] = > { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 }, > { "__typeof", RID_TYPEOF, 0 }, > { "__typeof__", RID_TYPEOF, 0 }, > - { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY }, > { "__volatile", RID_VOLATILE, 0 }, > { "__volatile__", RID_VOLATILE, 0 }, > { "__GIMPLE", RID_GIMPLE, D_CONLY }, > @@ -537,19 +503,13 @@ const struct c_common_resword c_common_reswords[] = > { "volatile", RID_VOLATILE, 0 }, > { "wchar_t", RID_WCHAR, D_CXXONLY }, > { "while", RID_WHILE, 0 }, > - { "__is_assignable", RID_IS_ASSIGNABLE, D_CXXONLY }, > - { "__is_constructible", RID_IS_CONSTRUCTIBLE, D_CXXONLY }, > - { "__is_nothrow_assignable", RID_IS_NOTHROW_ASSIGNABLE, D_CXXONLY }, > - { "__is_nothrow_constructible", RID_IS_NOTHROW_CONSTRUCTIBLE, D_CXXONLY }, > - { "__is_convertible", RID_IS_CONVERTIBLE, D_CXXONLY }, > - { "__is_nothrow_convertible", RID_IS_NOTHROW_CONVERTIBLE, D_CXXONLY }, > - { "__reference_constructs_from_temporary", RID_REF_CONSTRUCTS_FROM_TEMPORARY, > - D_CXXONLY }, > - { "__reference_converts_from_temporary", RID_REF_CONVERTS_FROM_TEMPORARY, > - D_CXXONLY }, > - { "__remove_cv", RID_REMOVE_CV, D_CXXONLY }, > - { "__remove_reference", RID_REMOVE_REFERENCE, D_CXXONLY }, > - { "__remove_cvref", RID_REMOVE_CVREF, D_CXXONLY }, > + > +#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > + { NAME, RID_##CODE, D_CXXONLY }, > +#include "cp/cp-trait.def" > +#undef DEFTRAIT > + /* An alias for __is_same. */ > + { "__is_same_as", RID_IS_SAME_AS, D_CXXONLY }, > > /* C++ transactional memory. */ > { "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM }, > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h > index d5c98d306ce..5f470d94f4a 100644 > --- a/gcc/c-family/c-common.h > +++ b/gcc/c-family/c-common.h > @@ -163,31 +163,14 @@ enum rid > RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST, > > /* C++ extensions */ > - RID_ADDRESSOF, RID_BASES, > - RID_BUILTIN_LAUNDER, RID_DIRECT_BASES, > - RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR, > - RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN, > - RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY, > - RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_UNIQUE_OBJ_REPRESENTATIONS, > - RID_HAS_VIRTUAL_DESTRUCTOR, RID_BUILTIN_BIT_CAST, > - RID_IS_ABSTRACT, RID_IS_AGGREGATE, > - RID_IS_BASE_OF, RID_IS_CLASS, > - RID_IS_EMPTY, RID_IS_ENUM, > - RID_IS_FINAL, RID_IS_LAYOUT_COMPATIBLE, > - RID_IS_LITERAL_TYPE, > - RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF, > - RID_IS_POD, RID_IS_POLYMORPHIC, > - RID_IS_SAME_AS, > - RID_IS_STD_LAYOUT, RID_IS_TRIVIAL, > - RID_IS_TRIVIALLY_ASSIGNABLE, RID_IS_TRIVIALLY_CONSTRUCTIBLE, > - RID_IS_TRIVIALLY_COPYABLE, > - RID_IS_UNION, RID_UNDERLYING_TYPE, > - RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE, > - RID_IS_NOTHROW_ASSIGNABLE, RID_IS_NOTHROW_CONSTRUCTIBLE, > - RID_IS_CONVERTIBLE, RID_IS_NOTHROW_CONVERTIBLE, > - RID_REF_CONSTRUCTS_FROM_TEMPORARY, > - RID_REF_CONVERTS_FROM_TEMPORARY, > - RID_REMOVE_CV, RID_REMOVE_REFERENCE, RID_REMOVE_CVREF, > + RID_ADDRESSOF, > + RID_BUILTIN_LAUNDER, > + RID_BUILTIN_BIT_CAST, > + > +#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > + RID_##CODE, > +#include "cp/cp-trait.def" > +#undef DEFTRAIT > > /* C++11 */ > RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT, > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > index ca73aff3f38..f4145571d92 100644 > --- a/gcc/cp/constraint.cc > +++ b/gcc/cp/constraint.cc > @@ -3711,13 +3711,11 @@ diagnose_trait_expr (tree expr, tree args) > inform (loc, " %qT is not a reference that binds to a temporary " > "object of type %qT (copy-initialization)", t1, t2); > break; > - case CPTK_BASES: > - case CPTK_DIRECT_BASES: > - case CPTK_UNDERLYING_TYPE: > - case CPTK_REMOVE_CV: > - case CPTK_REMOVE_REFERENCE: > - case CPTK_REMOVE_CVREF: > - /* We shouldn't see these non-expression traits. */ > +#define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ > + case CPTK_##CODE: > +#include "cp-trait.def" > +#undef DEFTRAIT_TYPE > + /* Type-yielding traits aren't expressions. */ > gcc_unreachable (); > /* We deliberately omit the default case so that when adding a new > trait we'll get reminded (by way of a warning) to handle it here. */ > diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc > index 2d3f206b530..e4df30d9720 100644 > --- a/gcc/cp/cp-objcp-common.cc > +++ b/gcc/cp/cp-objcp-common.cc > @@ -430,46 +430,10 @@ names_builtin_p (const char *name) > case RID_BUILTIN_ASSOC_BARRIER: > case RID_BUILTIN_BIT_CAST: > case RID_OFFSETOF: > - case RID_HAS_NOTHROW_ASSIGN: > - case RID_HAS_NOTHROW_CONSTRUCTOR: > - case RID_HAS_NOTHROW_COPY: > - case RID_HAS_TRIVIAL_ASSIGN: > - case RID_HAS_TRIVIAL_CONSTRUCTOR: > - case RID_HAS_TRIVIAL_COPY: > - case RID_HAS_TRIVIAL_DESTRUCTOR: > - case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS: > - case RID_HAS_VIRTUAL_DESTRUCTOR: > - case RID_IS_ABSTRACT: > - case RID_IS_AGGREGATE: > - case RID_IS_BASE_OF: > - case RID_IS_CLASS: > - case RID_IS_EMPTY: > - case RID_IS_ENUM: > - case RID_IS_FINAL: > - case RID_IS_LAYOUT_COMPATIBLE: > - case RID_IS_LITERAL_TYPE: > - case RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF: > - case RID_IS_POD: > - case RID_IS_POLYMORPHIC: > - case RID_IS_SAME_AS: > - case RID_IS_STD_LAYOUT: > - case RID_IS_TRIVIAL: > - case RID_IS_TRIVIALLY_ASSIGNABLE: > - case RID_IS_TRIVIALLY_CONSTRUCTIBLE: > - case RID_IS_TRIVIALLY_COPYABLE: > - case RID_IS_UNION: > - case RID_IS_ASSIGNABLE: > - case RID_IS_CONSTRUCTIBLE: > - case RID_IS_NOTHROW_ASSIGNABLE: > - case RID_IS_NOTHROW_CONSTRUCTIBLE: > - case RID_UNDERLYING_TYPE: > - case RID_IS_CONVERTIBLE: > - case RID_IS_NOTHROW_CONVERTIBLE: > - case RID_REF_CONSTRUCTS_FROM_TEMPORARY: > - case RID_REF_CONVERTS_FROM_TEMPORARY: > - case RID_REMOVE_CV: > - case RID_REMOVE_REFERENCE: > - case RID_REMOVE_CVREF: > +#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > + case RID_##CODE: > +#include "cp-trait.def" > +#undef DEFTRAIT > return true; > default: > break; > diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def > new file mode 100644 > index 00000000000..922348a1659 > --- /dev/null > +++ b/gcc/cp/cp-trait.def > @@ -0,0 +1,106 @@ > +/* This file contains the definitions for C++-specific built-in traits. > + > + Copyright The GNU Toolchain Authors. > + > + This file is part of GCC. > + > + GCC is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3, or (at your option) > + any later version. > + > + GCC is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with GCC; see the file COPYING3. If not see > + . */ > + > +/* Add a DEFTRAIT_EXPR (CODE, NAME, N) line to this file to define an > + expression-yielding built-in trait that has internal code name CODE, is > + spelled as NAME and takes N type arguments (where N is either 1, 2, or > + the special value -1 which denotes that it takes at least one argument). > + Such traits are represented as TRAIT_EXPR tree whose TRAIT_EXPR_KIND is > + CPTK_CODE. Define the behavior of the trait in finish_trait_expr. */ > + > +/* Add a DEFTRAIT_TYPE (CODE, NAME, N) line to this file to define a > + type-yielding built-in trait as described above. Such traits are > + generally represented as a TRAIT_TYPE tree whose TRAIT_TYPE_KIND is > + CPTK_CODE (exceptions are BASES and DIRECT_BASES below). Define the > + behavior of the trait in finish_trait_type. */ > + > +#ifdef DEFTRAIT > +#define DEFTRAIT_EXPR(CODE, NAME, ARITY) DEFTRAIT(tcc_expression, CODE, NAME, ARITY) > +#define DEFTRAIT_TYPE(CODE, NAME, ARITY) DEFTRAIT(tcc_type, CODE, NAME, ARITY) > +#define DEFTRAIT_EXPR_DEFAULTED > +#define DEFTRAIT_TYPE_DEFAULTED > +#endif > + > +#ifndef DEFTRAIT_EXPR > +#define DEFTRAIT_EXPR(CODE, NAME, ARITY) > +#define DEFTRAIT_EXPR_DEFAULTED > +#endif > + > +#ifndef DEFTRAIT_TYPE > +#define DEFTRAIT_TYPE(CODE, NAME, ARITY) > +#define DEFTRAIT_TYPE_DEFAULTED > +#endif > + > +DEFTRAIT_EXPR (HAS_NOTHROW_ASSIGN, "__has_nothrow_assign", 1) > +DEFTRAIT_EXPR (HAS_NOTHROW_CONSTRUCTOR, "__has_nothrow_constructor", 1) > +DEFTRAIT_EXPR (HAS_NOTHROW_COPY, "__has_nothrow_copy", 1) > +DEFTRAIT_EXPR (HAS_TRIVIAL_ASSIGN, "__has_trivial_assign", 1) > +DEFTRAIT_EXPR (HAS_TRIVIAL_CONSTRUCTOR, "__has_trivial_constructor", 1) > +DEFTRAIT_EXPR (HAS_TRIVIAL_COPY, "__has_trivial_copy", 1) > +DEFTRAIT_EXPR (HAS_TRIVIAL_DESTRUCTOR, "__has_trivial_destructor", 1) > +DEFTRAIT_EXPR (HAS_UNIQUE_OBJ_REPRESENTATIONS, "__has_unique_object_representations", 1) > +DEFTRAIT_EXPR (HAS_VIRTUAL_DESTRUCTOR, "__has_virtual_destructor", 1) > +DEFTRAIT_EXPR (IS_ABSTRACT, "__is_abstract", 1) > +DEFTRAIT_EXPR (IS_AGGREGATE, "__is_aggregate", 1) > +DEFTRAIT_EXPR (IS_ASSIGNABLE, "__is_assignable", 2) > +DEFTRAIT_EXPR (IS_BASE_OF, "__is_base_of", 2) > +DEFTRAIT_EXPR (IS_CLASS, "__is_class", 1) > +DEFTRAIT_EXPR (IS_CONSTRUCTIBLE, "__is_constructible", -1) > +DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2) > +DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1) > +DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1) > +DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1) > +DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2) > +DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1) > +DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2) > +DEFTRAIT_EXPR (IS_NOTHROW_CONSTRUCTIBLE, "__is_nothrow_constructible", -1) > +DEFTRAIT_EXPR (IS_NOTHROW_CONVERTIBLE, "__is_nothrow_convertible", 2) > +DEFTRAIT_EXPR (IS_POINTER_INTERCONVERTIBLE_BASE_OF, "__is_pointer_interconvertible_base_of", 2) > +DEFTRAIT_EXPR (IS_POD, "__is_pod", 1) > +DEFTRAIT_EXPR (IS_POLYMORPHIC, "__is_polymorphic", 1) > +DEFTRAIT_EXPR (IS_SAME_AS, "__is_same", 2) Can we make the code and name agree? I don't feel strongly about which way. > +DEFTRAIT_EXPR (IS_STD_LAYOUT, "__is_standard_layout", 1) > +DEFTRAIT_EXPR (IS_TRIVIAL, "__is_trivial", 1) > +DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2) > +DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1) > +DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1) > +DEFTRAIT_EXPR (IS_UNION, "__is_union", 1) > +DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2) > +DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2) > + > +DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1) > +DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1) > +DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1) > +DEFTRAIT_TYPE (UNDERLYING_TYPE, "__underlying_type", 1) > + > +/* These traits yield a type pack, not a type, and are represented by > + cp_parser_trait as a special BASES tree instead of a TRAIT_TYPE tree. */ > +DEFTRAIT_TYPE (BASES, "__bases", 1) > +DEFTRAIT_TYPE (DIRECT_BASES, "__direct_bases", 1) > + > +#ifdef DEFTRAIT_EXPR_DEFAULTED > +#undef DEFTRAIT_EXPR > +#undef DEFTRAIT_EXPR_DEFAULTED > +#endif > + > +#ifdef DEFTRAIT_TYPE_DEFAULTED > +#undef DEFTRAIT_TYPE > +#undef DEFTRAIT_TYPE_DEFAULTED > +#endif > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > index d696fd54a7a..67aea9653e3 100644 > --- a/gcc/cp/cp-tree.h > +++ b/gcc/cp/cp-tree.h > @@ -1374,48 +1374,10 @@ struct GTY (()) tree_argument_pack_select { > > enum cp_trait_kind > { > - CPTK_BASES, > - CPTK_DIRECT_BASES, > - CPTK_HAS_NOTHROW_ASSIGN, > - CPTK_HAS_NOTHROW_CONSTRUCTOR, > - CPTK_HAS_NOTHROW_COPY, > - CPTK_HAS_TRIVIAL_ASSIGN, > - CPTK_HAS_TRIVIAL_CONSTRUCTOR, > - CPTK_HAS_TRIVIAL_COPY, > - CPTK_HAS_TRIVIAL_DESTRUCTOR, > - CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS, > - CPTK_HAS_VIRTUAL_DESTRUCTOR, > - CPTK_IS_ABSTRACT, > - CPTK_IS_AGGREGATE, > - CPTK_IS_BASE_OF, > - CPTK_IS_CLASS, > - CPTK_IS_EMPTY, > - CPTK_IS_ENUM, > - CPTK_IS_FINAL, > - CPTK_IS_LAYOUT_COMPATIBLE, > - CPTK_IS_LITERAL_TYPE, > - CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF, > - CPTK_IS_POD, > - CPTK_IS_POLYMORPHIC, > - CPTK_IS_SAME_AS, > - CPTK_IS_STD_LAYOUT, > - CPTK_IS_TRIVIAL, > - CPTK_IS_TRIVIALLY_ASSIGNABLE, > - CPTK_IS_TRIVIALLY_CONSTRUCTIBLE, > - CPTK_IS_TRIVIALLY_COPYABLE, > - CPTK_IS_UNION, > - CPTK_UNDERLYING_TYPE, > - CPTK_IS_ASSIGNABLE, > - CPTK_IS_CONSTRUCTIBLE, > - CPTK_IS_NOTHROW_ASSIGNABLE, > - CPTK_IS_NOTHROW_CONSTRUCTIBLE, > - CPTK_IS_CONVERTIBLE, > - CPTK_IS_NOTHROW_CONVERTIBLE, > - CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, > - CPTK_REF_CONVERTS_FROM_TEMPORARY, > - CPTK_REMOVE_CV, > - CPTK_REMOVE_REFERENCE, > - CPTK_REMOVE_CVREF, > +#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > + CPTK_##CODE, > +#include "cp-trait.def" > +#undef DEFTRAIT > }; > > /* The types that we are processing. */ > diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc > index b91615439e4..8ca1b8f234a 100644 > --- a/gcc/cp/cxx-pretty-print.cc > +++ b/gcc/cp/cxx-pretty-print.cc > @@ -2617,128 +2617,12 @@ pp_cxx_trait (cxx_pretty_printer *pp, tree t) > > switch (kind) > { > - case CPTK_HAS_NOTHROW_ASSIGN: > - pp_cxx_ws_string (pp, "__has_nothrow_assign"); > +#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > + case CPTK_##CODE: \ > + pp_cxx_ws_string (pp, NAME); \ > break; > - case CPTK_HAS_TRIVIAL_ASSIGN: > - pp_cxx_ws_string (pp, "__has_trivial_assign"); > - break; > - case CPTK_HAS_NOTHROW_CONSTRUCTOR: > - pp_cxx_ws_string (pp, "__has_nothrow_constructor"); > - break; > - case CPTK_HAS_TRIVIAL_CONSTRUCTOR: > - pp_cxx_ws_string (pp, "__has_trivial_constructor"); > - break; > - case CPTK_HAS_NOTHROW_COPY: > - pp_cxx_ws_string (pp, "__has_nothrow_copy"); > - break; > - case CPTK_HAS_TRIVIAL_COPY: > - pp_cxx_ws_string (pp, "__has_trivial_copy"); > - break; > - case CPTK_HAS_TRIVIAL_DESTRUCTOR: > - pp_cxx_ws_string (pp, "__has_trivial_destructor"); > - break; > - case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS: > - pp_cxx_ws_string (pp, "__has_unique_object_representations"); > - break; > - case CPTK_HAS_VIRTUAL_DESTRUCTOR: > - pp_cxx_ws_string (pp, "__has_virtual_destructor"); > - break; > - case CPTK_IS_ABSTRACT: > - pp_cxx_ws_string (pp, "__is_abstract"); > - break; > - case CPTK_IS_AGGREGATE: > - pp_cxx_ws_string (pp, "__is_aggregate"); > - break; > - case CPTK_IS_BASE_OF: > - pp_cxx_ws_string (pp, "__is_base_of"); > - break; > - case CPTK_IS_CLASS: > - pp_cxx_ws_string (pp, "__is_class"); > - break; > - case CPTK_IS_EMPTY: > - pp_cxx_ws_string (pp, "__is_empty"); > - break; > - case CPTK_IS_ENUM: > - pp_cxx_ws_string (pp, "__is_enum"); > - break; > - case CPTK_IS_FINAL: > - pp_cxx_ws_string (pp, "__is_final"); > - break; > - case CPTK_IS_LAYOUT_COMPATIBLE: > - pp_cxx_ws_string (pp, "__is_layout_compatible"); > - break; > - case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF: > - pp_cxx_ws_string (pp, "__is_pointer_interconvertible_base_of"); > - break; > - case CPTK_IS_POD: > - pp_cxx_ws_string (pp, "__is_pod"); > - break; > - case CPTK_IS_POLYMORPHIC: > - pp_cxx_ws_string (pp, "__is_polymorphic"); > - break; > - case CPTK_IS_SAME_AS: > - pp_cxx_ws_string (pp, "__is_same"); > - break; > - case CPTK_IS_STD_LAYOUT: > - pp_cxx_ws_string (pp, "__is_std_layout"); > - break; > - case CPTK_IS_TRIVIAL: > - pp_cxx_ws_string (pp, "__is_trivial"); > - break; > - case CPTK_IS_TRIVIALLY_ASSIGNABLE: > - pp_cxx_ws_string (pp, "__is_trivially_assignable"); > - break; > - case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE: > - pp_cxx_ws_string (pp, "__is_trivially_constructible"); > - break; > - case CPTK_IS_TRIVIALLY_COPYABLE: > - pp_cxx_ws_string (pp, "__is_trivially_copyable"); > - break; > - case CPTK_IS_UNION: > - pp_cxx_ws_string (pp, "__is_union"); > - break; > - case CPTK_IS_LITERAL_TYPE: > - pp_cxx_ws_string (pp, "__is_literal_type"); > - break; > - case CPTK_IS_ASSIGNABLE: > - pp_cxx_ws_string (pp, "__is_assignable"); > - break; > - case CPTK_IS_CONSTRUCTIBLE: > - pp_cxx_ws_string (pp, "__is_constructible"); > - break; > - case CPTK_IS_NOTHROW_ASSIGNABLE: > - pp_cxx_ws_string (pp, "__is_nothrow_assignable"); > - break; > - case CPTK_IS_NOTHROW_CONSTRUCTIBLE: > - pp_cxx_ws_string (pp, "__is_nothrow_constructible"); > - break; > - case CPTK_IS_CONVERTIBLE: > - pp_cxx_ws_string (pp, "__is_convertible"); > - break; > - case CPTK_IS_NOTHROW_CONVERTIBLE: > - pp_cxx_ws_string (pp, "__is_nothrow_convertible"); > - break; > - case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY: > - pp_cxx_ws_string (pp, "__reference_constructs_from_temporary"); > - break; > - case CPTK_REF_CONVERTS_FROM_TEMPORARY: > - pp_cxx_ws_string (pp, "__reference_converts_from_temporary"); > - break; > - case CPTK_UNDERLYING_TYPE: > - pp_cxx_ws_string (pp, "__underlying_type"); > - break; > - case CPTK_REMOVE_CV: > - pp_cxx_ws_string (pp, "__remove_cv"); > - break; > - case CPTK_REMOVE_REFERENCE: > - pp_cxx_ws_string (pp, "__remove_reference"); > - break; > - case CPTK_REMOVE_CVREF: > - pp_cxx_ws_string (pp, "__remove_cvref"); > - break; > - default: > - gcc_unreachable (); > +#include "cp-trait.def" > +#undef DEFTRAIT > } > > pp_cxx_left_paren (pp); > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index d592d783250..8d0e0fa1b87 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -1146,16 +1146,18 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword) > case RID_TYPEOF: > /* C++11 extensions. */ > case RID_DECLTYPE: > - case RID_UNDERLYING_TYPE: > - case RID_REMOVE_CV: > - case RID_REMOVE_REFERENCE: > - case RID_REMOVE_CVREF: > case RID_CONSTEXPR: > /* C++20 extensions. */ > case RID_CONSTINIT: > case RID_CONSTEVAL: > return true; > > +#define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ > + case RID_##CODE: > +#include "cp-trait.def" > +#undef DEFTRAIT_TYPE > + return true; > + > default: > if (keyword >= RID_FIRST_INT_N > && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS > @@ -5895,42 +5897,10 @@ cp_parser_primary_expression (cp_parser *parser, > case RID_OFFSETOF: > return cp_parser_builtin_offsetof (parser); > > - case RID_HAS_NOTHROW_ASSIGN: > - case RID_HAS_NOTHROW_CONSTRUCTOR: > - case RID_HAS_NOTHROW_COPY: > - case RID_HAS_TRIVIAL_ASSIGN: > - case RID_HAS_TRIVIAL_CONSTRUCTOR: > - case RID_HAS_TRIVIAL_COPY: > - case RID_HAS_TRIVIAL_DESTRUCTOR: > - case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS: > - case RID_HAS_VIRTUAL_DESTRUCTOR: > - case RID_IS_ABSTRACT: > - case RID_IS_AGGREGATE: > - case RID_IS_BASE_OF: > - case RID_IS_CLASS: > - case RID_IS_EMPTY: > - case RID_IS_ENUM: > - case RID_IS_FINAL: > - case RID_IS_LAYOUT_COMPATIBLE: > - case RID_IS_LITERAL_TYPE: > - case RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF: > - case RID_IS_POD: > - case RID_IS_POLYMORPHIC: > - case RID_IS_SAME_AS: > - case RID_IS_STD_LAYOUT: > - case RID_IS_TRIVIAL: > - case RID_IS_TRIVIALLY_ASSIGNABLE: > - case RID_IS_TRIVIALLY_CONSTRUCTIBLE: > - case RID_IS_TRIVIALLY_COPYABLE: > - case RID_IS_UNION: > - case RID_IS_ASSIGNABLE: > - case RID_IS_CONSTRUCTIBLE: > - case RID_IS_NOTHROW_ASSIGNABLE: > - case RID_IS_NOTHROW_CONSTRUCTIBLE: > - case RID_IS_CONVERTIBLE: > - case RID_IS_NOTHROW_CONVERTIBLE: > - case RID_REF_CONSTRUCTS_FROM_TEMPORARY: > - case RID_REF_CONVERTS_FROM_TEMPORARY: > +#define DEFTRAIT_EXPR(CODE, NAME, ARITY) \ > + case RID_##CODE: > +#include "cp-trait.def" > +#undef DEFTRAIT_EXPR > return cp_parser_trait (parser, token->keyword); > > // C++ concepts > @@ -10898,150 +10868,15 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > > switch (keyword) > { > - case RID_HAS_NOTHROW_ASSIGN: > - kind = CPTK_HAS_NOTHROW_ASSIGN; > - break; > - case RID_HAS_NOTHROW_CONSTRUCTOR: > - kind = CPTK_HAS_NOTHROW_CONSTRUCTOR; > - break; > - case RID_HAS_NOTHROW_COPY: > - kind = CPTK_HAS_NOTHROW_COPY; > - break; > - case RID_HAS_TRIVIAL_ASSIGN: > - kind = CPTK_HAS_TRIVIAL_ASSIGN; > - break; > - case RID_HAS_TRIVIAL_CONSTRUCTOR: > - kind = CPTK_HAS_TRIVIAL_CONSTRUCTOR; > - break; > - case RID_HAS_TRIVIAL_COPY: > - kind = CPTK_HAS_TRIVIAL_COPY; > - break; > - case RID_HAS_TRIVIAL_DESTRUCTOR: > - kind = CPTK_HAS_TRIVIAL_DESTRUCTOR; > - break; > - case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS: > - kind = CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS; > - break; > - case RID_HAS_VIRTUAL_DESTRUCTOR: > - kind = CPTK_HAS_VIRTUAL_DESTRUCTOR; > - break; > - case RID_IS_ABSTRACT: > - kind = CPTK_IS_ABSTRACT; > - break; > - case RID_IS_AGGREGATE: > - kind = CPTK_IS_AGGREGATE; > - break; > - case RID_IS_BASE_OF: > - kind = CPTK_IS_BASE_OF; > - binary = true; > - break; > - case RID_IS_CLASS: > - kind = CPTK_IS_CLASS; > - break; > - case RID_IS_EMPTY: > - kind = CPTK_IS_EMPTY; > - break; > - case RID_IS_ENUM: > - kind = CPTK_IS_ENUM; > - break; > - case RID_IS_FINAL: > - kind = CPTK_IS_FINAL; > - break; > - case RID_IS_LAYOUT_COMPATIBLE: > - kind = CPTK_IS_LAYOUT_COMPATIBLE; > - binary = true; > - break; > - case RID_IS_LITERAL_TYPE: > - kind = CPTK_IS_LITERAL_TYPE; > - break; > - case RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF: > - kind = CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF; > - binary = true; > - break; > - case RID_IS_POD: > - kind = CPTK_IS_POD; > - break; > - case RID_IS_POLYMORPHIC: > - kind = CPTK_IS_POLYMORPHIC; > - break; > - case RID_IS_SAME_AS: > - kind = CPTK_IS_SAME_AS; > - binary = true; > - break; > - case RID_IS_STD_LAYOUT: > - kind = CPTK_IS_STD_LAYOUT; > - break; > - case RID_IS_TRIVIAL: > - kind = CPTK_IS_TRIVIAL; > - break; > - case RID_IS_TRIVIALLY_ASSIGNABLE: > - kind = CPTK_IS_TRIVIALLY_ASSIGNABLE; > - binary = true; > - break; > - case RID_IS_TRIVIALLY_CONSTRUCTIBLE: > - kind = CPTK_IS_TRIVIALLY_CONSTRUCTIBLE; > - variadic = true; > - break; > - case RID_IS_TRIVIALLY_COPYABLE: > - kind = CPTK_IS_TRIVIALLY_COPYABLE; > - break; > - case RID_IS_UNION: > - kind = CPTK_IS_UNION; > - break; > - case RID_UNDERLYING_TYPE: > - kind = CPTK_UNDERLYING_TYPE; > - type = true; > - break; > - case RID_BASES: > - kind = CPTK_BASES; > - break; > - case RID_DIRECT_BASES: > - kind = CPTK_DIRECT_BASES; > - break; > - case RID_IS_ASSIGNABLE: > - kind = CPTK_IS_ASSIGNABLE; > - binary = true; > - break; > - case RID_IS_CONSTRUCTIBLE: > - kind = CPTK_IS_CONSTRUCTIBLE; > - variadic = true; > - break; > - case RID_IS_NOTHROW_ASSIGNABLE: > - kind = CPTK_IS_NOTHROW_ASSIGNABLE; > - binary = true; > - break; > - case RID_IS_NOTHROW_CONSTRUCTIBLE: > - kind = CPTK_IS_NOTHROW_CONSTRUCTIBLE; > - variadic = true; > - break; > - case RID_IS_CONVERTIBLE: > - kind = CPTK_IS_CONVERTIBLE; > - binary = true; > - break; > - case RID_IS_NOTHROW_CONVERTIBLE: > - kind = CPTK_IS_NOTHROW_CONVERTIBLE; > - binary = true; > - break; > - case RID_REF_CONSTRUCTS_FROM_TEMPORARY: > - kind = CPTK_REF_CONSTRUCTS_FROM_TEMPORARY; > - binary = true; > - break; > - case RID_REF_CONVERTS_FROM_TEMPORARY: > - kind = CPTK_REF_CONVERTS_FROM_TEMPORARY; > - binary = true; > - break; > - case RID_REMOVE_CV: > - kind = CPTK_REMOVE_CV; > - type = true; > - break; > - case RID_REMOVE_REFERENCE: > - kind = CPTK_REMOVE_REFERENCE; > - type = true; > - break; > - case RID_REMOVE_CVREF: > - kind = CPTK_REMOVE_CVREF; > - type = true; > +#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > + case RID_##CODE: \ > + kind = CPTK_##CODE; \ > + binary = (ARITY == 2); \ > + variadic = (ARITY == -1); \ > + type = (TCC == tcc_type); \ > break; > +#include "cp-trait.def" > +#undef DEFTRAIT > default: > gcc_unreachable (); > } > @@ -19881,10 +19716,10 @@ cp_parser_simple_type_specifier (cp_parser* parser, > > return type; > > - case RID_UNDERLYING_TYPE: > - case RID_REMOVE_CV: > - case RID_REMOVE_REFERENCE: > - case RID_REMOVE_CVREF: > +#define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ > + case RID_##CODE: > +#include "cp-trait.def" > +#undef DEFTRAIT_TYPE > type = cp_parser_trait (parser, token->keyword); > if (decl_specs) > cp_parser_set_decl_spec_type (decl_specs, type, > @@ -19893,14 +19728,6 @@ cp_parser_simple_type_specifier (cp_parser* parser, > > return type; > > - case RID_BASES: > - case RID_DIRECT_BASES: > - type = cp_parser_trait (parser, token->keyword); > - if (decl_specs) > - cp_parser_set_decl_spec_type (decl_specs, type, > - token, > - /*type_definition_p=*/false); > - return type; > default: > break; > }