From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-vk1-xa2d.google.com (mail-vk1-xa2d.google.com [IPv6:2607:f8b0:4864:20::a2d]) by sourceware.org (Postfix) with ESMTPS id B6E213857004 for ; Sun, 15 Oct 2023 21:53:03 +0000 (GMT) ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B6E213857004 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::a2d ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1697406788; cv=none; b=merxrMbV/z8LvdDD4WwDtoW62Yq010H5xBAMP/fqtCWefwqoT1tnbOlPfJx8axRKk1zm1qG0DXa61lqNTPahsU6W+RWipN/+4xIe6SEMTUOdII0WWfNF+pUYNRiRleRRW+fDXxvN3o7Bf50PswEP+ut+GoAU9ieMbzoFgZ4MQ1Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1697406788; c=relaxed/simple; bh=SYpY7wi92BBXwDILxXmiGENfJX6Hthy6HK4fFEUww90=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=opcWeYUCumXXkzsGXL/l1ILEN/hnyOQ7RsKHVX0h7EJwNOrKdCAhG6j41D3jDD8lUGyFC8ivxlhzsWgcuSDU4gu1GQN8d/jiDZ93fIIAN3mz6Cl94BjBPvFyto5MIIrJiSa6adK+HscgllRPvQFUWRuaVNSqsJKK/xQbyvoQVxo= ARC-Authentication-Results: i=1; server2.sourceware.org DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B6E213857004 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=cs.washington.edu Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cs.washington.edu Received: by mail-vk1-xa2d.google.com with SMTP id 71dfb90a1353d-49ab6c1869dso3407210e0c.0 for ; Sun, 15 Oct 2023 14:53:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cs.washington.edu; s=goo201206; t=1697406783; x=1698011583; darn=gcc.gnu.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=xTMBB+1CJPnm+mKh7d0RvqJA5S1s0cDhCdZ2QubBtlI=; b=Actx7gsS6nrv4j2tNBKxjVctQr/xuyfjmMaXl/EmqLqTBRnqk7gTvhy8vXV+gCmWsj Vs4RZBdD88O6g69skzXtV3ORqyH5kE5Q07CsfREDMCV6bsCRW7oqZIblCtDiTSQFvZAW jtuucgaYnkyOBFlc6b91WOBg3QJyx8oDzUj2A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697406783; x=1698011583; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xTMBB+1CJPnm+mKh7d0RvqJA5S1s0cDhCdZ2QubBtlI=; b=MoOrXCgt9CFkwFDu7jsOkMU1OKcdE82clRb01F9erfumRJtesVSYjosUooyADx5/QW TpyJIbdNomJpoYoOApbUTQn7PPMrVaX7srceBeO//i3uLDVU7NyN6rHNeCLFNgOz3Vmw etVWbc97AKims8dP8zVjbwhg16fGmH1DulQdzqLbUX4haq9R7xIcqT82HoEprp1ejuV7 +TR1dMiA7O3lDEVEcIc+W3XVpTb8WbwFXILr658/853YByb30c7VCyC559lgNXFgxoQS ZYI5WHUCMXt/YVUE4gg8ErrhZX5zxQ4/q5mOy/Zo/XAItvUrnz4l3t1QLE7XYpIQoNix ZBXg== X-Gm-Message-State: AOJu0YzQWKWQ6+sQ00exxqBnQFKI9pGAw9IZEcqXufKgEazOMeUHEkHY h3roCu39jY27MVjYGC0Que001STMIzADoWUKW/0Adg== X-Google-Smtp-Source: AGHT+IEEVZmweESaHmcCO3NL6LNleS7j5GPEMdlJ3cy8QaXM7ok/yRGmzTh4NmZrAku4U9/7+Aignc/dXpcG04I9U/k= X-Received: by 2002:a05:6122:2513:b0:49a:b9ed:8c19 with SMTP id cl19-20020a056122251300b0049ab9ed8c19mr3208224vkb.7.1697406782769; Sun, 15 Oct 2023 14:53:02 -0700 (PDT) MIME-Version: 1.0 References: <20231013211206.1215663-1-kmatsui@gcc.gnu.org> <20231013223957.1634024-1-kmatsui@gcc.gnu.org> <20231013223957.1634024-3-kmatsui@gcc.gnu.org> <1b2b9b34-3647-8f29-4a07-81cf3c8adb19@idea> <9268edce-f2c9-e839-4deb-c05d247b52b8@idea> In-Reply-To: <9268edce-f2c9-e839-4deb-c05d247b52b8@idea> From: Ken Matsui Date: Sun, 15 Oct 2023 14:52:26 -0700 Message-ID: Subject: Re: [PATCH v19 02/40] c-family, c++: Look up built-in traits through gperf To: Patrick Palka Cc: Ken Matsui , gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org, jason@redhat.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SCC_5_SHORT_WORD_LINES,SPF_HELO_NONE,SPF_PASS,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 Sun, Oct 15, 2023 at 2:50=E2=80=AFPM Patrick Palka w= rote: > > On Sun, 15 Oct 2023, Ken Matsui wrote: > > > On Sun, Oct 15, 2023 at 1:43=E2=80=AFPM Patrick Palka wrote: > > > > > > On Fri, 13 Oct 2023, Ken Matsui wrote: > > > > > > > Since RID_MAX soon reaches 255 and all built-in traits are used app= roximately > > > > once in a C++ translation unit, this patch removes all RID values f= or built-in > > > > traits and uses gperf to look up the specific trait. Rather than h= olding > > > > traits as keywords, we set all trait identifiers as cik_trait, whic= h is a new > > > > cp_identifier_kind. As cik_reserved_for_udlit was unused and > > > > cp_identifier_kind is 3 bits, we replaced the unused field with the= new > > > > cik_trait. Also, the later patch handles a subsequent token to the= built-in > > > > identifier so that we accept the use of non-function-like built-in = trait > > > > identifiers. > > > > > > Awesome! It's great we won't have to rename any existing identifiers= in > > > libstdc++ with this approach. > > > > > > I think this patch looks perfect, assuming we want to stick with the = gperf > > > approach, but I just noticed that IDENTIFIER nodes have an IDENTIFIER= _CP_INDEX > > > field which is currently only used for operator name identifiers to > > > optimize looking up operator information. Could we reuse this field = for > > > IDENTIFIER_TRAIT_P identifiers as well in order to store their > > > corresponding cp_trait_kind? If so then I think we wouldn't need to = use > > > gperf for the built-in traits at all, since the mapping from identifi= er > > > to cp_trait_kind would be implicit in each IDENTIFIER node, which wou= ld > > > perhaps be a nice simplification (and just as fast if not faster than= gperf)? > > > > > > > Thank you! I think this way decreases the size of the compiler even if > > we do not see speed improvements. Since IDENTIFIER_CP_INDEX > > (base.u.bits.address_space) is an unsigned char (addr_space_t), we can > > have only up to 255 traits. Is this acceptable? > > Good points. Given there's so far around 150 standard library traits, a > limit of 255 should last us quite a while so IMHO it's acceptable :) > Sounds great! I will update the patch in this way. Thank you! > > > > > > > > > > gcc/c-family/ChangeLog: > > > > > > > > * c-common.cc (c_common_reswords): Remove all mappings of > > > > built-in traits. > > > > * c-common.h (enum rid): Remove all RID values for built-in t= raits. > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > * Make-lang.in: Add targets to generate cp-trait.gperf and > > > > cp-trait.h. > > > > * cp-objcp-common.cc (names_builtin_p): Remove all RID value > > > > cases for built-in traits. Check for built-in traits via > > > > the new cik_trait identifier. > > > > * cp-tree.h (cik_reserved_for_udlit): Rename to ... > > > > (cik_trait): ... this. > > > > (IDENTIFIER_ANY_OP_P): Exclude cik_trait. > > > > (IDENTIFIER_TRAIT_P): New macro to detect cik_trait. > > > > * lex.cc (init_cp_traits): New function to set cik_trait for = all > > > > built-in trait identifiers. > > > > (cxx_init): Call init_cp_traits function. > > > > * parser.cc (cp_lexer_lookup_trait): New function to look up = a > > > > built-in trait from a token by gperf. > > > > (cp_lexer_lookup_trait_expr): Likewise, look up an > > > > expression-yielding built-in trait. > > > > (cp_lexer_lookup_trait_type): Likewise, look up a type-yieldi= ng > > > > built-in trait. > > > > (cp_keyword_starts_decl_specifier_p): Remove all RID value ca= ses > > > > for built-in traits. > > > > (cp_lexer_next_token_is_decl_specifier_keyword): Handle > > > > type-yielding built-in traits. > > > > (cp_parser_primary_expression): Remove all RID value cases fo= r > > > > built-in traits. Handle expression-yielding built-in traits. > > > > (cp_parser_trait): Handle cp_trait instead of enum rid. > > > > (cp_parser_simple_type_specifier): Remove all RID value cases > > > > for built-in traits. Handle type-yielding built-in traits. > > > > * cp-trait-head.in: New file. > > > > * cp-trait.gperf: New file. > > > > * cp-trait.h: New file. > > > > > > > > Co-authored-by: Patrick Palka > > > > Signed-off-by: Ken Matsui > > > > --- > > > > gcc/c-family/c-common.cc | 7 -- > > > > gcc/c-family/c-common.h | 5 - > > > > gcc/cp/Make-lang.in | 26 ++++ > > > > gcc/cp/cp-objcp-common.cc | 8 +- > > > > gcc/cp/cp-trait-head.in | 30 +++++ > > > > gcc/cp/cp-trait.gperf | 74 ++++++++++++ > > > > gcc/cp/cp-trait.h | 247 ++++++++++++++++++++++++++++++++++= ++++ > > > > gcc/cp/cp-tree.h | 14 ++- > > > > gcc/cp/lex.cc | 19 +++ > > > > gcc/cp/parser.cc | 132 ++++++++++++-------- > > > > 10 files changed, 492 insertions(+), 70 deletions(-) > > > > create mode 100644 gcc/cp/cp-trait-head.in > > > > create mode 100644 gcc/cp/cp-trait.gperf > > > > create mode 100644 gcc/cp/cp-trait.h > > > > > > > > diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc > > > > index f044db5b797..21fd333ef57 100644 > > > > --- a/gcc/c-family/c-common.cc > > > > +++ b/gcc/c-family/c-common.cc > > > > @@ -508,13 +508,6 @@ const struct c_common_resword c_common_resword= s[] =3D > > > > { "wchar_t", RID_WCHAR, D_CXXONLY }, > > > > { "while", RID_WHILE, 0 }, > > > > > > > > -#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, D_CXXONLY }, > > > > - > > > > /* C++ transactional memory. */ > > > > { "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM }, > > > > { "atomic_noexcept", RID_ATOMIC_NOEXCEPT, D_CXXONLY | D_TR= ANSMEM }, > > > > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h > > > > index 1fdba7ef3ea..051a442e0f4 100644 > > > > --- a/gcc/c-family/c-common.h > > > > +++ b/gcc/c-family/c-common.h > > > > @@ -168,11 +168,6 @@ enum rid > > > > 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_STAT= IC_ASSERT, > > > > > > > > diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in > > > > index 2727fb7f8cc..a67d1c3e9f3 100644 > > > > --- a/gcc/cp/Make-lang.in > > > > +++ b/gcc/cp/Make-lang.in > > > > @@ -34,6 +34,8 @@ > > > > # - the compiler proper (eg: cc1plus) > > > > # - define the names for selecting the language in LANGUAGES. > > > > > > > > +AWK =3D @AWK@ > > > > + > > > > # Actual names to use when installing a native compiler. > > > > CXX_INSTALL_NAME :=3D $(shell echo c++|sed '$(program_transform_na= me)') > > > > GXX_INSTALL_NAME :=3D $(shell echo g++|sed '$(program_transform_na= me)') > > > > @@ -186,6 +188,30 @@ endif > > > > # This is the file that depends on the generated header file. > > > > cp/name-lookup.o: $(srcdir)/cp/std-name-hint.h > > > > > > > > +# We always need the dependency on the .gperf file > > > > +# because it itself is generated. > > > > +ifeq ($(ENABLE_MAINTAINER_RULES), true) > > > > +$(srcdir)/cp/cp-trait.h: $(srcdir)/cp/cp-trait.gperf > > > > +else > > > > +$(srcdir)/cp/cp-trait.h: | $(srcdir)/cp/cp-trait.gperf > > > > +endif > > > > + gperf -o -C -E -k '8' -D -N 'find' -L C++ \ > > > > + $(srcdir)/cp/cp-trait.gperf --output-file $(srcdir)/c= p/cp-trait.h > > > > + > > > > +# The cp-trait.gperf file itself is generated from > > > > +# cp-trait-head.in and cp-trait.def files. > > > > +$(srcdir)/cp/cp-trait.gperf: $(srcdir)/cp/cp-trait-head.in $(srcdi= r)/cp/cp-trait.def > > > > + cat $< > $@ > > > > + $(AWK) -F', *' '/^DEFTRAIT_/ { \ > > > > + type =3D (index($$1, "DEFTRAIT_TYPE") !=3D 0 ? "true"= : "false"); \ > > > > + gsub(/DEFTRAIT_(EXPR|TYPE) \(/, "", $$1); \ > > > > + gsub(/\)/, "", $$3); \ > > > > + print $$2", CPTK_" $$1", "$$3", "type; \ > > > > + }' $(srcdir)/cp/cp-trait.def >> $@ > > > > + > > > > +# This is the file that depends on the generated header file. > > > > +cp/parser.o: $(srcdir)/cp/cp-trait.h > > > > + > > > > components_in_prev =3D "bfd opcodes binutils fixincludes gas gcc g= mp mpfr mpc isl gold intl ld libbacktrace libcpp libcody libdecnumber libib= erty libiberty-linker-plugin libiconv zlib lto-plugin libctf libsframe" > > > > components_in_prev_target =3D "libstdc++-v3 libsanitizer libvtv li= bgcc libbacktrace libphobos zlib libgomp libatomic" > > > > > > > > diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc > > > > index 93b027b80ce..b1adacfec07 100644 > > > > --- a/gcc/cp/cp-objcp-common.cc > > > > +++ b/gcc/cp/cp-objcp-common.cc > > > > @@ -421,6 +421,10 @@ names_builtin_p (const char *name) > > > > } > > > > } > > > > > > > > + /* Check for built-in traits. */ > > > > + if (IDENTIFIER_TRAIT_P (id)) > > > > + return true; > > > > + > > > > /* Also detect common reserved C++ words that aren't strictly bu= ilt-in > > > > functions. */ > > > > switch (C_RID_CODE (id)) > > > > @@ -434,10 +438,6 @@ names_builtin_p (const char *name) > > > > case RID_BUILTIN_ASSOC_BARRIER: > > > > case RID_BUILTIN_BIT_CAST: > > > > case RID_OFFSETOF: > > > > -#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-head.in b/gcc/cp/cp-trait-head.in > > > > new file mode 100644 > > > > index 00000000000..9357eea1238 > > > > --- /dev/null > > > > +++ b/gcc/cp/cp-trait-head.in > > > > @@ -0,0 +1,30 @@ > > > > +%language=3DC++ > > > > +%define class-name cp_trait_lookup > > > > +%struct-type > > > > +%{ > > > > +/* Copyright (C) 2023 Free Software Foundation, Inc. > > > > + > > > > +This file is part of GCC. > > > > + > > > > +GCC is free software; you can redistribute it and/or modify it und= er > > > > +the terms of the GNU General Public License as published by the Fr= ee > > > > +Software Foundation; either version 3, or (at your option) any lat= er > > > > +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 Lice= nse > > > > +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 > > > > +. */ > > > > +%} > > > > +struct cp_trait { > > > > + const char *name; > > > > + enum cp_trait_kind kind; > > > > + short arity; > > > > + bool type; > > > > +}; > > > > +%% > > > > +"__is_same_as", CPTK_IS_SAME, 2, false > > > > diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf > > > > new file mode 100644 > > > > index 00000000000..47e3c1af499 > > > > --- /dev/null > > > > +++ b/gcc/cp/cp-trait.gperf > > > > @@ -0,0 +1,74 @@ > > > > +%language=3DC++ > > > > +%define class-name cp_trait_lookup > > > > +%struct-type > > > > +%{ > > > > +/* Copyright (C) 2023 Free Software Foundation, Inc. > > > > + > > > > +This file is part of GCC. > > > > + > > > > +GCC is free software; you can redistribute it and/or modify it und= er > > > > +the terms of the GNU General Public License as published by the Fr= ee > > > > +Software Foundation; either version 3, or (at your option) any lat= er > > > > +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 Lice= nse > > > > +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 > > > > +. */ > > > > +%} > > > > +struct cp_trait { > > > > + const char *name; > > > > + enum cp_trait_kind kind; > > > > + short arity; > > > > + bool type; > > > > +}; > > > > +%% > > > > +"__is_same_as", CPTK_IS_SAME, 2, false > > > > +"__has_nothrow_assign", CPTK_HAS_NOTHROW_ASSIGN, 1, false > > > > +"__has_nothrow_constructor", CPTK_HAS_NOTHROW_CONSTRUCTOR, 1, fals= e > > > > +"__has_nothrow_copy", CPTK_HAS_NOTHROW_COPY, 1, false > > > > +"__has_trivial_assign", CPTK_HAS_TRIVIAL_ASSIGN, 1, false > > > > +"__has_trivial_constructor", CPTK_HAS_TRIVIAL_CONSTRUCTOR, 1, fals= e > > > > +"__has_trivial_copy", CPTK_HAS_TRIVIAL_COPY, 1, false > > > > +"__has_trivial_destructor", CPTK_HAS_TRIVIAL_DESTRUCTOR, 1, false > > > > +"__has_unique_object_representations", CPTK_HAS_UNIQUE_OBJ_REPRESE= NTATIONS, 1, false > > > > +"__has_virtual_destructor", CPTK_HAS_VIRTUAL_DESTRUCTOR, 1, false > > > > +"__is_abstract", CPTK_IS_ABSTRACT, 1, false > > > > +"__is_aggregate", CPTK_IS_AGGREGATE, 1, false > > > > +"__is_assignable", CPTK_IS_ASSIGNABLE, 2, false > > > > +"__is_base_of", CPTK_IS_BASE_OF, 2, false > > > > +"__is_class", CPTK_IS_CLASS, 1, false > > > > +"__is_constructible", CPTK_IS_CONSTRUCTIBLE, -1, false > > > > +"__is_convertible", CPTK_IS_CONVERTIBLE, 2, false > > > > +"__is_empty", CPTK_IS_EMPTY, 1, false > > > > +"__is_enum", CPTK_IS_ENUM, 1, false > > > > +"__is_final", CPTK_IS_FINAL, 1, false > > > > +"__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, 2, false > > > > +"__is_literal_type", CPTK_IS_LITERAL_TYPE, 1, false > > > > +"__is_nothrow_assignable", CPTK_IS_NOTHROW_ASSIGNABLE, 2, false > > > > +"__is_nothrow_constructible", CPTK_IS_NOTHROW_CONSTRUCTIBLE, -1, f= alse > > > > +"__is_nothrow_convertible", CPTK_IS_NOTHROW_CONVERTIBLE, 2, false > > > > +"__is_pointer_interconvertible_base_of", CPTK_IS_POINTER_INTERCONV= ERTIBLE_BASE_OF, 2, false > > > > +"__is_pod", CPTK_IS_POD, 1, false > > > > +"__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false > > > > +"__is_same", CPTK_IS_SAME, 2, false > > > > +"__is_standard_layout", CPTK_IS_STD_LAYOUT, 1, false > > > > +"__is_trivial", CPTK_IS_TRIVIAL, 1, false > > > > +"__is_trivially_assignable", CPTK_IS_TRIVIALLY_ASSIGNABLE, 2, fals= e > > > > +"__is_trivially_constructible", CPTK_IS_TRIVIALLY_CONSTRUCTIBLE, -= 1, false > > > > +"__is_trivially_copyable", CPTK_IS_TRIVIALLY_COPYABLE, 1, false > > > > +"__is_union", CPTK_IS_UNION, 1, false > > > > +"__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_FROM_= TEMPORARY, 2, false > > > > +"__reference_converts_from_temporary", CPTK_REF_CONVERTS_FROM_TEMP= ORARY, 2, false > > > > +"__remove_cv", CPTK_REMOVE_CV, 1, true > > > > +"__remove_cvref", CPTK_REMOVE_CVREF, 1, true > > > > +"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true > > > > +"__type_pack_element", CPTK_TYPE_PACK_ELEMENT, -1, true > > > > +"__underlying_type", CPTK_UNDERLYING_TYPE, 1, true > > > > +"__is_deducible ", CPTK_IS_DEDUCIBLE, 2, false > > > > +"__bases", CPTK_BASES, 1, true > > > > +"__direct_bases", CPTK_DIRECT_BASES, 1, true > > > > diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h > > > > new file mode 100644 > > > > index 00000000000..97ba8492d15 > > > > --- /dev/null > > > > +++ b/gcc/cp/cp-trait.h > > > > @@ -0,0 +1,247 @@ > > > > +/* C++ code produced by gperf version 3.1 */ > > > > +/* Command-line: gperf -o -C -E -k 8 -D -N find -L C++ --output-fi= le ../../gcc/cp/cp-trait.h ../../gcc/cp/cp-trait.gperf */ > > > > + > > > > +#if !((' ' =3D=3D 32) && ('!' =3D=3D 33) && ('"' =3D=3D 34) && ('#= ' =3D=3D 35) \ > > > > + && ('%' =3D=3D 37) && ('&' =3D=3D 38) && ('\'' =3D=3D 39) &&= ('(' =3D=3D 40) \ > > > > + && (')' =3D=3D 41) && ('*' =3D=3D 42) && ('+' =3D=3D 43) && = (',' =3D=3D 44) \ > > > > + && ('-' =3D=3D 45) && ('.' =3D=3D 46) && ('/' =3D=3D 47) && = ('0' =3D=3D 48) \ > > > > + && ('1' =3D=3D 49) && ('2' =3D=3D 50) && ('3' =3D=3D 51) && = ('4' =3D=3D 52) \ > > > > + && ('5' =3D=3D 53) && ('6' =3D=3D 54) && ('7' =3D=3D 55) && = ('8' =3D=3D 56) \ > > > > + && ('9' =3D=3D 57) && (':' =3D=3D 58) && (';' =3D=3D 59) && = ('<' =3D=3D 60) \ > > > > + && ('=3D' =3D=3D 61) && ('>' =3D=3D 62) && ('?' =3D=3D 63) &= & ('A' =3D=3D 65) \ > > > > + && ('B' =3D=3D 66) && ('C' =3D=3D 67) && ('D' =3D=3D 68) && = ('E' =3D=3D 69) \ > > > > + && ('F' =3D=3D 70) && ('G' =3D=3D 71) && ('H' =3D=3D 72) && = ('I' =3D=3D 73) \ > > > > + && ('J' =3D=3D 74) && ('K' =3D=3D 75) && ('L' =3D=3D 76) && = ('M' =3D=3D 77) \ > > > > + && ('N' =3D=3D 78) && ('O' =3D=3D 79) && ('P' =3D=3D 80) && = ('Q' =3D=3D 81) \ > > > > + && ('R' =3D=3D 82) && ('S' =3D=3D 83) && ('T' =3D=3D 84) && = ('U' =3D=3D 85) \ > > > > + && ('V' =3D=3D 86) && ('W' =3D=3D 87) && ('X' =3D=3D 88) && = ('Y' =3D=3D 89) \ > > > > + && ('Z' =3D=3D 90) && ('[' =3D=3D 91) && ('\\' =3D=3D 92) &&= (']' =3D=3D 93) \ > > > > + && ('^' =3D=3D 94) && ('_' =3D=3D 95) && ('a' =3D=3D 97) && = ('b' =3D=3D 98) \ > > > > + && ('c' =3D=3D 99) && ('d' =3D=3D 100) && ('e' =3D=3D 101) &= & ('f' =3D=3D 102) \ > > > > + && ('g' =3D=3D 103) && ('h' =3D=3D 104) && ('i' =3D=3D 105) = && ('j' =3D=3D 106) \ > > > > + && ('k' =3D=3D 107) && ('l' =3D=3D 108) && ('m' =3D=3D 109) = && ('n' =3D=3D 110) \ > > > > + && ('o' =3D=3D 111) && ('p' =3D=3D 112) && ('q' =3D=3D 113) = && ('r' =3D=3D 114) \ > > > > + && ('s' =3D=3D 115) && ('t' =3D=3D 116) && ('u' =3D=3D 117) = && ('v' =3D=3D 118) \ > > > > + && ('w' =3D=3D 119) && ('x' =3D=3D 120) && ('y' =3D=3D 121) = && ('z' =3D=3D 122) \ > > > > + && ('{' =3D=3D 123) && ('|' =3D=3D 124) && ('}' =3D=3D 125) = && ('~' =3D=3D 126)) > > > > +/* The character set is not based on ISO-646. */ > > > > +#error "gperf generated tables don't work with this execution char= acter set. Please report a bug to ." > > > > +#endif > > > > + > > > > +#line 4 "../../gcc/cp/cp-trait.gperf" > > > > + > > > > +/* Copyright (C) 2023 Free Software Foundation, Inc. > > > > + > > > > +This file is part of GCC. > > > > + > > > > +GCC is free software; you can redistribute it and/or modify it und= er > > > > +the terms of the GNU General Public License as published by the Fr= ee > > > > +Software Foundation; either version 3, or (at your option) any lat= er > > > > +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 Lice= nse > > > > +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 > > > > +. */ > > > > +#line 23 "../../gcc/cp/cp-trait.gperf" > > > > +struct cp_trait { > > > > + const char *name; > > > > + enum cp_trait_kind kind; > > > > + short arity; > > > > + bool type; > > > > +}; > > > > +/* maximum key range =3D 79, duplicates =3D 0 */ > > > > + > > > > +class cp_trait_lookup > > > > +{ > > > > +private: > > > > + static inline unsigned int hash (const char *str, size_t len); > > > > +public: > > > > + static const struct cp_trait *find (const char *str, size_t len)= ; > > > > +}; > > > > + > > > > +inline unsigned int > > > > +cp_trait_lookup::hash (const char *str, size_t len) > > > > +{ > > > > + static const unsigned char asso_values[] =3D > > > > + { > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 1, 86, 86, > > > > + 0, 35, 86, 0, 86, 0, 86, 86, 10, 10, > > > > + 50, 15, 55, 86, 30, 5, 15, 0, 86, 86, > > > > + 86, 20, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, > > > > + 86, 86, 86, 86, 86, 86 > > > > + }; > > > > + unsigned int hval =3D len; > > > > + > > > > + switch (hval) > > > > + { > > > > + default: > > > > + hval +=3D asso_values[static_cast(str[7])]; > > > > + /*FALLTHROUGH*/ > > > > + case 7: > > > > + break; > > > > + } > > > > + return hval; > > > > +} > > > > + > > > > +const struct cp_trait * > > > > +cp_trait_lookup::find (const char *str, size_t len) > > > > +{ > > > > + enum > > > > + { > > > > + TOTAL_KEYWORDS =3D 45, > > > > + MIN_WORD_LENGTH =3D 7, > > > > + MAX_WORD_LENGTH =3D 37, > > > > + MIN_HASH_VALUE =3D 7, > > > > + MAX_HASH_VALUE =3D 85 > > > > + }; > > > > + > > > > + static const struct cp_trait wordlist[] =3D > > > > + { > > > > +#line 73 "../../gcc/cp/cp-trait.gperf" > > > > + {"__bases", CPTK_BASES, 1, true}, > > > > +#line 56 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_pod", CPTK_IS_POD, 1, false}, > > > > +#line 48 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_enum", CPTK_IS_ENUM, 1, false}, > > > > +#line 64 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_union", CPTK_IS_UNION, 1, false}, > > > > +#line 44 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_class", CPTK_IS_CLASS, 1, false}, > > > > +#line 60 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_trivial", CPTK_IS_TRIVIAL, 1, false}, > > > > +#line 41 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_aggregate", CPTK_IS_AGGREGATE, 1, false}, > > > > +#line 72 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_deducible ", CPTK_IS_DEDUCIBLE, 2, false}, > > > > +#line 43 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_base_of", CPTK_IS_BASE_OF, 2, false}, > > > > +#line 40 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_abstract", CPTK_IS_ABSTRACT, 1, false}, > > > > +#line 58 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_same", CPTK_IS_SAME, 2, false}, > > > > +#line 42 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_assignable", CPTK_IS_ASSIGNABLE, 2, false}, > > > > +#line 59 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_standard_layout", CPTK_IS_STD_LAYOUT, 1, false}, > > > > +#line 30 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_same_as", CPTK_IS_SAME, 2, false}, > > > > +#line 63 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_trivially_copyable", CPTK_IS_TRIVIALLY_COPYABLE, 1, f= alse}, > > > > +#line 39 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_virtual_destructor", CPTK_HAS_VIRTUAL_DESTRUCTOR, 1,= false}, > > > > +#line 61 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_trivially_assignable", CPTK_IS_TRIVIALLY_ASSIGNABLE, = 2, false}, > > > > +#line 57 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false}, > > > > +#line 71 "../../gcc/cp/cp-trait.gperf" > > > > + {"__underlying_type", CPTK_UNDERLYING_TYPE, 1, true}, > > > > +#line 62 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_trivially_constructible", CPTK_IS_TRIVIALLY_CONSTRUCT= IBLE, -1, false}, > > > > +#line 74 "../../gcc/cp/cp-trait.gperf" > > > > + {"__direct_bases", CPTK_DIRECT_BASES, 1, true}, > > > > +#line 51 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_literal_type", CPTK_IS_LITERAL_TYPE, 1, false}, > > > > +#line 33 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_nothrow_copy", CPTK_HAS_NOTHROW_COPY, 1, false}, > > > > +#line 31 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_nothrow_assign", CPTK_HAS_NOTHROW_ASSIGN, 1, false}, > > > > +#line 55 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_pointer_interconvertible_base_of", CPTK_IS_POINTER_IN= TERCONVERTIBLE_BASE_OF, 2, false}, > > > > +#line 52 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_nothrow_assignable", CPTK_IS_NOTHROW_ASSIGNABLE, 2, f= alse}, > > > > +#line 54 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_nothrow_convertible", CPTK_IS_NOTHROW_CONVERTIBLE, 2,= false}, > > > > +#line 32 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_nothrow_constructor", CPTK_HAS_NOTHROW_CONSTRUCTOR, = 1, false}, > > > > +#line 53 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_nothrow_constructible", CPTK_IS_NOTHROW_CONSTRUCTIBLE= , -1, false}, > > > > +#line 50 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, 2, fal= se}, > > > > +#line 67 "../../gcc/cp/cp-trait.gperf" > > > > + {"__remove_cv", CPTK_REMOVE_CV, 1, true}, > > > > +#line 36 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_trivial_copy", CPTK_HAS_TRIVIAL_COPY, 1, false}, > > > > +#line 68 "../../gcc/cp/cp-trait.gperf" > > > > + {"__remove_cvref", CPTK_REMOVE_CVREF, 1, true}, > > > > +#line 34 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_trivial_assign", CPTK_HAS_TRIVIAL_ASSIGN, 1, false}, > > > > +#line 69 "../../gcc/cp/cp-trait.gperf" > > > > + {"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true}, > > > > +#line 37 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_trivial_destructor", CPTK_HAS_TRIVIAL_DESTRUCTOR, 1,= false}, > > > > +#line 35 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_trivial_constructor", CPTK_HAS_TRIVIAL_CONSTRUCTOR, = 1, false}, > > > > +#line 49 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_final", CPTK_IS_FINAL, 1, false}, > > > > +#line 47 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_empty", CPTK_IS_EMPTY, 1, false}, > > > > +#line 46 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_convertible", CPTK_IS_CONVERTIBLE, 2, false}, > > > > +#line 45 "../../gcc/cp/cp-trait.gperf" > > > > + {"__is_constructible", CPTK_IS_CONSTRUCTIBLE, -1, false}, > > > > +#line 66 "../../gcc/cp/cp-trait.gperf" > > > > + {"__reference_converts_from_temporary", CPTK_REF_CONVERTS_FR= OM_TEMPORARY, 2, false}, > > > > +#line 65 "../../gcc/cp/cp-trait.gperf" > > > > + {"__reference_constructs_from_temporary", CPTK_REF_CONSTRUCT= S_FROM_TEMPORARY, 2, false}, > > > > +#line 70 "../../gcc/cp/cp-trait.gperf" > > > > + {"__type_pack_element", CPTK_TYPE_PACK_ELEMENT, -1, true}, > > > > +#line 38 "../../gcc/cp/cp-trait.gperf" > > > > + {"__has_unique_object_representations", CPTK_HAS_UNIQUE_OBJ_= REPRESENTATIONS, 1, false} > > > > + }; > > > > + > > > > + static const signed char lookup[] =3D > > > > + { > > > > + -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, -1, > > > > + 6, 7, -1, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, > > > > + 19, 20, -1, -1, 21, 22, -1, 23, -1, 24, 25, 26, 27, 28, > > > > + 29, -1, -1, -1, 30, -1, 31, 32, 33, -1, -1, 34, 35, 36, > > > > + -1, -1, -1, -1, 37, -1, -1, -1, -1, 38, 39, -1, 40, -1, > > > > + 41, -1, 42, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, > > > > + -1, 44 > > > > + }; > > > > + > > > > + if (len <=3D MAX_WORD_LENGTH && len >=3D MIN_WORD_LENGTH) > > > > + { > > > > + unsigned int key =3D hash (str, len); > > > > + > > > > + if (key <=3D MAX_HASH_VALUE) > > > > + { > > > > + int index =3D lookup[key]; > > > > + > > > > + if (index >=3D 0) > > > > + { > > > > + const char *s =3D wordlist[index].name; > > > > + > > > > + if (*str =3D=3D *s && !strcmp (str + 1, s + 1)) > > > > + return &wordlist[index]; > > > > + } > > > > + } > > > > + } > > > > + return 0; > > > > +} > > > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > > > > index 6e34952da99..62e134886fb 100644 > > > > --- a/gcc/cp/cp-tree.h > > > > +++ b/gcc/cp/cp-tree.h > > > > @@ -1226,7 +1226,7 @@ enum cp_identifier_kind { > > > > cik_simple_op =3D 4, /* Non-assignment operator name. */ > > > > cik_assign_op =3D 5, /* An assignment operator name. */ > > > > cik_conv_op =3D 6, /* Conversion operator name. */ > > > > - cik_reserved_for_udlit =3D 7, /* Not yet in use */ > > > > + cik_trait =3D 7, /* Built-in trait name. */ > > > > cik_max > > > > }; > > > > > > > > @@ -1271,9 +1271,9 @@ enum cp_identifier_kind { > > > > & IDENTIFIER_KIND_BIT_0 (NODE)) > > > > > > > > /* True if this identifier is for any operator name (including > > > > - conversions). Value 4, 5, 6 or 7. */ > > > > + conversions). Value 4, 5, or 6. */ > > > > #define IDENTIFIER_ANY_OP_P(NODE) \ > > > > - (IDENTIFIER_KIND_BIT_2 (NODE)) > > > > + (IDENTIFIER_KIND_BIT_2 (NODE) && !IDENTIFIER_TRAIT_P (NODE)) > > > > > > > > /* True if this identifier is for an overloaded operator. Values 4= , 5. */ > > > > #define IDENTIFIER_OVL_OP_P(NODE) \ > > > > @@ -1286,12 +1286,18 @@ enum cp_identifier_kind { > > > > & IDENTIFIER_KIND_BIT_0 (NODE)) > > > > > > > > /* True if this identifier is the name of a type-conversion > > > > - operator. Value 7. */ > > > > + operator. Value 6. */ > > > > #define IDENTIFIER_CONV_OP_P(NODE) \ > > > > (IDENTIFIER_ANY_OP_P (NODE) \ > > > > & IDENTIFIER_KIND_BIT_1 (NODE) \ > > > > & (!IDENTIFIER_KIND_BIT_0 (NODE))) > > > > > > > > +/* True if this identifier is the name of a built-in trait. */ > > > > +#define IDENTIFIER_TRAIT_P(NODE) \ > > > > + (IDENTIFIER_KIND_BIT_0 (NODE) \ > > > > + && IDENTIFIER_KIND_BIT_1 (NODE) \ > > > > + && IDENTIFIER_KIND_BIT_2 (NODE)) > > > > + > > > > /* True if this identifier is a new or delete operator. */ > > > > #define IDENTIFIER_NEWDEL_OP_P(NODE) \ > > > > (IDENTIFIER_OVL_OP_P (NODE) \ > > > > diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc > > > > index 64bcfb18196..f6e1f6a4075 100644 > > > > --- a/gcc/cp/lex.cc > > > > +++ b/gcc/cp/lex.cc > > > > @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not se= e > > > > #include "langhooks.h" > > > > > > > > static int interface_strcmp (const char *); > > > > +static void init_cp_traits (void); > > > > static void init_cp_pragma (void); > > > > > > > > static tree parse_strconst_pragma (const char *, int); > > > > @@ -283,6 +284,23 @@ init_reswords (void) > > > > } > > > > } > > > > > > > > +/* Initialize the C++ traits. */ > > > > +static void > > > > +init_cp_traits (void) > > > > +{ > > > > + tree id; > > > > + > > > > +#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > > > > + id =3D get_identifier (NAME); \ > > > > + set_identifier_kind (id, cik_trait); > > > > +#include "cp/cp-trait.def" > > > > +#undef DEFTRAIT > > > > + > > > > + /* An alias for __is_same. */ > > > > + id =3D get_identifier ("__is_same_as"); > > > > + set_identifier_kind (id, cik_trait); > > > > +} > > > > + > > > > static void > > > > init_cp_pragma (void) > > > > { > > > > @@ -324,6 +342,7 @@ cxx_init (void) > > > > input_location =3D BUILTINS_LOCATION; > > > > > > > > init_reswords (); > > > > + init_cp_traits (); > > > > init_tree (); > > > > init_cp_semantics (); > > > > init_operators (); > > > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > > > > index f3abae716fe..39952893ffa 100644 > > > > --- a/gcc/cp/parser.cc > > > > +++ b/gcc/cp/parser.cc > > > > @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not se= e > > > > #include "contracts.h" > > > > #include "bitmap.h" > > > > #include "builtins.h" > > > > +#include "cp-trait.h" > > > > > > > > > > > > /* The lexer. */ > > > > @@ -246,6 +247,12 @@ static void cp_lexer_start_debugging > > > > (cp_lexer *) ATTRIBUTE_UNUSED; > > > > static void cp_lexer_stop_debugging > > > > (cp_lexer *) ATTRIBUTE_UNUSED; > > > > +static const cp_trait *cp_lexer_lookup_trait > > > > + (const cp_token *); > > > > +static const cp_trait *cp_lexer_lookup_trait_expr > > > > + (const cp_token *); > > > > +static const cp_trait *cp_lexer_lookup_trait_type > > > > + (const cp_token *); > > > > > > > > static cp_token_cache *cp_token_cache_new > > > > (cp_token *, cp_token *); > > > > @@ -1167,12 +1174,6 @@ cp_keyword_starts_decl_specifier_p (enum rid= keyword) > > > > 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 >=3D RID_FIRST_INT_N > > > > && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS > > > > @@ -1182,6 +1183,51 @@ cp_keyword_starts_decl_specifier_p (enum rid= keyword) > > > > } > > > > } > > > > > > > > +/* Look ups the corresponding built-in trait if a given token is > > > > + a built-in trait. Otherwise, returns nullptr. */ > > > > + > > > > +static const cp_trait * > > > > +cp_lexer_lookup_trait (const cp_token *token) > > > > +{ > > > > + tree id =3D token->u.value; > > > > + > > > > + if (token->type =3D=3D CPP_NAME > > > > + && TREE_CODE (id) =3D=3D IDENTIFIER_NODE > > > > + && IDENTIFIER_TRAIT_P (id)) > > > > + { > > > > + const char *id_str =3D IDENTIFIER_POINTER (id); > > > > + const int id_len =3D IDENTIFIER_LENGTH (id); > > > > + return cp_trait_lookup::find (id_str, id_len); > > > > + } > > > > + return nullptr; > > > > +} > > > > + > > > > +/* Similarly, but only if the token is an expression-yielding > > > > + built-in trait. */ > > > > + > > > > +static const cp_trait * > > > > +cp_lexer_lookup_trait_expr (const cp_token *token) > > > > +{ > > > > + const cp_trait *trait =3D cp_lexer_lookup_trait (token); > > > > + if (trait && !trait->type) > > > > + return trait; > > > > + > > > > + return nullptr; > > > > +} > > > > + > > > > +/* Similarly, but only if the token is a type-yielding > > > > + built-in trait. */ > > > > + > > > > +static const cp_trait * > > > > +cp_lexer_lookup_trait_type (const cp_token *token) > > > > +{ > > > > + const cp_trait *trait =3D cp_lexer_lookup_trait (token); > > > > + if (trait && trait->type) > > > > + return trait; > > > > + > > > > + return nullptr; > > > > +} > > > > + > > > > /* Return true if the next token is a keyword for a decl-specifier= . */ > > > > > > > > static bool > > > > @@ -1190,6 +1236,8 @@ cp_lexer_next_token_is_decl_specifier_keyword= (cp_lexer *lexer) > > > > cp_token *token; > > > > > > > > token =3D cp_lexer_peek_token (lexer); > > > > + if (cp_lexer_lookup_trait_type (token)) > > > > + return true; > > > > return cp_keyword_starts_decl_specifier_p (token->keyword); > > > > } > > > > > > > > @@ -2854,7 +2902,7 @@ static void cp_parser_late_parsing_default_ar= gs > > > > static tree cp_parser_sizeof_operand > > > > (cp_parser *, enum rid); > > > > static cp_expr cp_parser_trait > > > > - (cp_parser *, enum rid); > > > > + (cp_parser *, const cp_trait *); > > > > static bool cp_parser_declares_only_class_p > > > > (cp_parser *); > > > > static void cp_parser_set_storage_class > > > > @@ -6021,12 +6069,6 @@ cp_parser_primary_expression (cp_parser *par= ser, > > > > case RID_OFFSETOF: > > > > return cp_parser_builtin_offsetof (parser); > > > > > > > > -#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 > > > > case RID_REQUIRES: > > > > return cp_parser_requires_expression (parser); > > > > @@ -6065,6 +6107,12 @@ cp_parser_primary_expression (cp_parser *par= ser, > > > > `::' as the beginning of a qualified-id, or the "operator" > > > > keyword. */ > > > > case CPP_NAME: > > > > + { > > > > + const cp_trait* trait =3D cp_lexer_lookup_trait_expr (token); > > > > + if (trait) > > > > + return cp_parser_trait (parser, trait); > > > > + } > > > > + /* FALLTHRU */ > > > > case CPP_SCOPE: > > > > case CPP_TEMPLATE_ID: > > > > case CPP_NESTED_NAME_SPECIFIER: > > > > @@ -11033,28 +11081,11 @@ cp_parser_builtin_offsetof (cp_parser *pa= rser) > > > > /* Parse a builtin trait expression or type. */ > > > > > > > > static cp_expr > > > > -cp_parser_trait (cp_parser* parser, enum rid keyword) > > > > +cp_parser_trait (cp_parser* parser, const cp_trait* trait) > > > > { > > > > - cp_trait_kind kind; > > > > tree type1, type2 =3D NULL_TREE; > > > > - bool binary =3D false; > > > > - bool variadic =3D false; > > > > - bool type =3D false; > > > > - > > > > - switch (keyword) > > > > - { > > > > -#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > > > > - case RID_##CODE: \ > > > > - kind =3D CPTK_##CODE; \ > > > > - binary =3D (ARITY =3D=3D 2); \ > > > > - variadic =3D (ARITY =3D=3D -1); \ > > > > - type =3D (TCC =3D=3D tcc_type); \ > > > > - break; > > > > -#include "cp-trait.def" > > > > -#undef DEFTRAIT > > > > - default: > > > > - gcc_unreachable (); > > > > - } > > > > + const bool binary =3D (trait->arity =3D=3D 2); > > > > + const bool variadic =3D (trait->arity =3D=3D -1); > > > > > > > > /* Get location of initial token. */ > > > > location_t start_loc =3D cp_lexer_peek_token (parser->lexer)->lo= cation; > > > > @@ -11063,12 +11094,12 @@ cp_parser_trait (cp_parser* parser, enum = rid keyword) > > > > cp_lexer_consume_token (parser->lexer); > > > > > > > > matching_parens parens; > > > > - if (kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > + if (trait->kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > cp_parser_require (parser, CPP_LESS, RT_LESS); > > > > else > > > > parens.require_open (parser); > > > > > > > > - if (kind =3D=3D CPTK_IS_DEDUCIBLE) > > > > + if (trait->kind =3D=3D CPTK_IS_DEDUCIBLE) > > > > { > > > > const cp_token* token =3D cp_lexer_peek_token (parser->lexer= ); > > > > type1 =3D cp_parser_id_expression (parser, > > > > @@ -11079,7 +11110,7 @@ cp_parser_trait (cp_parser* parser, enum ri= d keyword) > > > > /*optional_p=3D*/false); > > > > type1 =3D cp_parser_lookup_name_simple (parser, type1, token= ->location); > > > > } > > > > - else if (kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > + else if (trait->kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > /* __type_pack_element takes an expression as its first argume= nt and uses > > > > template-id syntax instead of function call syntax (for con= sistency > > > > with Clang). We special case these properties of __type_pa= ck_element > > > > @@ -11094,7 +11125,7 @@ cp_parser_trait (cp_parser* parser, enum ri= d keyword) > > > > if (type1 =3D=3D error_mark_node) > > > > return error_mark_node; > > > > > > > > - if (kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > + if (trait->kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > { > > > > cp_parser_require (parser, CPP_COMMA, RT_COMMA); > > > > tree trailing =3D cp_parser_enclosed_template_argument_list = (parser); > > > > @@ -11144,7 +11175,7 @@ cp_parser_trait (cp_parser* parser, enum ri= d keyword) > > > > } > > > > > > > > location_t finish_loc =3D cp_lexer_peek_token (parser->lexer)->l= ocation; > > > > - if (kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > + if (trait->kind =3D=3D CPTK_TYPE_PACK_ELEMENT) > > > > /* cp_parser_enclosed_template_argument_list above already too= k care > > > > of parsing the closing '>'. */; > > > > else > > > > @@ -11158,17 +11189,17 @@ cp_parser_trait (cp_parser* parser, enum = rid keyword) > > > > > > > > /* Complete the trait expression, which may mean either processi= ng > > > > the trait expr now or saving it for template instantiation. = */ > > > > - switch (kind) > > > > + switch (trait->kind) > > > > { > > > > case CPTK_BASES: > > > > return cp_expr (finish_bases (type1, false), trait_loc); > > > > case CPTK_DIRECT_BASES: > > > > return cp_expr (finish_bases (type1, true), trait_loc); > > > > default: > > > > - if (type) > > > > - return finish_trait_type (kind, type1, type2, tf_warning_or_e= rror); > > > > + if (trait->type) > > > > + return finish_trait_type (trait->kind, type1, type2, tf_warni= ng_or_error); > > > > else > > > > - return finish_trait_expr (trait_loc, kind, type1, type2); > > > > + return finish_trait_expr (trait_loc, trait->kind, type1, type= 2); > > > > } > > > > } > > > > > > > > @@ -20081,20 +20112,21 @@ cp_parser_simple_type_specifier (cp_parse= r* parser, > > > > > > > > return type; > > > > > > > > -#define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ > > > > - case RID_##CODE: > > > > -#include "cp-trait.def" > > > > -#undef DEFTRAIT_TYPE > > > > - type =3D cp_parser_trait (parser, token->keyword); > > > > + default: > > > > + break; > > > > + } > > > > + > > > > + /* If token is a type-yielding built-in traits, parse it. */ > > > > + const cp_trait* trait =3D cp_lexer_lookup_trait_type (token); > > > > + if (trait) > > > > + { > > > > + type =3D cp_parser_trait (parser, trait); > > > > if (decl_specs) > > > > cp_parser_set_decl_spec_type (decl_specs, type, > > > > token, > > > > /*type_definition_p=3D*/false); > > > > > > > > return type; > > > > - > > > > - default: > > > > - break; > > > > } > > > > > > > > /* If token is an already-parsed decltype not followed by ::, > > > > -- > > > > 2.42.0 > > > > > > > > > > > > > > >