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 B712D385CC8A for ; Wed, 11 Oct 2023 20:10:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B712D385CC8A 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=1697055002; 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: in-reply-to:in-reply-to:references:references; bh=2XDzYU/vEmiM4tOZ5/80UBRk4w4G1fdEXC1XZVGj8Ns=; b=Mje17xo1PszJ29dizQNNZe9hqD3XugfB0/NA2rrmahEXuJlk1sFo1QjmX8nMRS1nmJbu9Y PVxvb4RzK+V3SdYh6mBRoy2rIu2UYOIxhP6oqJpcM+H/wyy12XlM89u+H4pFAXf03zKzNB OEGLGFw1iJOS5qwjvscXMXsM4Mm6AnM= Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-62-WinToASjPgGd0ZwPtcTpqQ-1; Wed, 11 Oct 2023 16:09:40 -0400 X-MC-Unique: WinToASjPgGd0ZwPtcTpqQ-1 Received: by mail-qt1-f200.google.com with SMTP id d75a77b69052e-418116b13a7so2512851cf.3 for ; Wed, 11 Oct 2023 13:09:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697054970; x=1697659770; h=mime-version:references:message-id:in-reply-to:subject:cc:to:date :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=0jDyHFshbnI/0T5SRvJlSEdP8ueef0EMh/4I8hAKEfc=; b=vIh2ngMlhm1kaHH4/mI/vl6x1rA/cpp15cehfEPGn5GzaHFp2ODe0aV0ukTJuqXE6I OqMUOBdGAqT9NPVQhHwsb13+hRbDoWK9HBjxiToqMj8UxbAGSVSOri6roxJMYdOWo+VC n4E2ACrG17QVdDgjx3Xf2Rexk2c1wmnbHGI4xDzqocvJHyxA2GSHxb0g7GfQs6QBv7NT Q84WQW9JG8Ho06AcdYQ3o2RLyUN3aXkIFY94f0k2dhHZGlkX+DoZs0Y69YHqGiXxtDRW rA0g8ivlMSvZdSG4yuLArsyibrXkpYn14PI6Emdbxr+T6ozt0BN5kzsvFr9R4FIl2+1K hACw== X-Gm-Message-State: AOJu0Yx6g0owJ3jD1NT04w+8pOY/FRZOmqETLyEyuXrnvpXXGUGBb93G HS2O50aL3Zn0O73jcC6GO7YCT4UckjibPsZqzal0aYhQvd7vQviLOvTVrv/PY+e+wHkQA6y0MdO 1HsXyk8iKKqOsr9k= X-Received: by 2002:a05:622a:1742:b0:410:9af1:f9b2 with SMTP id l2-20020a05622a174200b004109af1f9b2mr29915275qtk.3.1697054970136; Wed, 11 Oct 2023 13:09:30 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEwSdZYJasqpFyVT6Z0wT0RCeO6qvuMufj5WmdGtY6IsBVSVLykrbAi8mVBbpok4Np/2lMcKg== X-Received: by 2002:a05:622a:1742:b0:410:9af1:f9b2 with SMTP id l2-20020a05622a174200b004109af1f9b2mr29915251qtk.3.1697054969599; Wed, 11 Oct 2023 13:09:29 -0700 (PDT) Received: from [192.168.1.130] (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id cj20-20020a05622a259400b004197079f2f8sm5611727qtb.64.2023.10.11.13.09.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Oct 2023 13:09:29 -0700 (PDT) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Wed, 11 Oct 2023 16:09:28 -0400 (EDT) To: Ken Matsui cc: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org, jason@redhat.com Subject: Re: [PATCH v16 02/39] c-family, c++: Look up built-in traits through gperf In-Reply-To: <20231010221520.3680267-3-kmatsui@gcc.gnu.org> Message-ID: <885b17e9-866f-4cef-12b8-d44c3b350d31@idea> References: <20231010095229.3364786-1-kmatsui@gcc.gnu.org> <20231010221520.3680267-1-kmatsui@gcc.gnu.org> <20231010221520.3680267-3-kmatsui@gcc.gnu.org> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-23.3 required=5.0 tests=BAYES_00,DKIM_INVALID,DKIM_SIGNED,GIT_PATCH_0,KAM_DMARC_NONE,KAM_DMARC_STATUS,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SCC_5_SHORT_WORD_LINES,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=unavailable 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 Tue, 10 Oct 2023, Ken Matsui wrote: > Since RID_MAX soon reaches 255 and all traits are used approximately once in > a C++ translation unit, this patch instead uses only RID_TRAIT_EXPR and > RID_TRAIT_TYPE for all traits and uses gperf to look up the specific trait. Nice! This looks good to me, but I wonder what the corresponding ridpointers entry should be for RID_TRAIT_TYPE and RID_TRAIT_EXPR? It seems we currently assume every rid code has a unique canonical spelling which we keep in ridpointers[RID_FOO], but that's of course not the case for RID_TRAIT_TYPE and RID_TRAIT_EXPR. Maybe we should make init_reswords() keep the ridpointers entry empty for RID_TRAIT_EXPR and RID_TRAIT_TYPE? > > gcc/c-family/ChangeLog: > > * c-common.cc (c_common_reswords): Map all traits to RID_TRAIT_EXPR > and RID_TRAIT_TYPE instead. > * c-common.h (enum rid): Remove all existing RID values for traits. > Use RID_TRAIT_EXPR and RID_TRAIT_TYPE instead. > > 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 existing RID values > for traits. Use RID_TRAIT_EXPR and RID_TRAIT_TYPE instead. > * parser.cc (cp_keyword_starts_decl_specifier_p): Likewise, for > type-yielding traits. Use RID_TRAIT_TYPE instead. > (cp_parser_simple_type_specifier): Likewise. > (cp_parser_primary_expression): Likewise, for expression-yielding > traits. Use RID_TRAIT_EXPR instead. > (cp_parser_trait): Look up traits through gperf instead of enum rid. > * cp-trait-head.in: New file. > * cp-trait.gperf: New file. > * cp-trait.h: New file. > > Signed-off-by: Ken Matsui > --- > gcc/c-family/c-common.cc | 12 +- > gcc/c-family/c-common.h | 7 +- > gcc/cp/Make-lang.in | 24 ++++ > gcc/cp/cp-objcp-common.cc | 6 +- > gcc/cp/cp-trait-head.in | 30 +++++ > gcc/cp/cp-trait.gperf | 74 ++++++++++++ > gcc/cp/cp-trait.h | 247 ++++++++++++++++++++++++++++++++++++++ > gcc/cp/parser.cc | 70 ++++------- > 8 files changed, 412 insertions(+), 58 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..f219ccd29e5 100644 > --- a/gcc/c-family/c-common.cc > +++ b/gcc/c-family/c-common.cc > @@ -508,12 +508,16 @@ const struct c_common_resword c_common_reswords[] = > { "wchar_t", RID_WCHAR, D_CXXONLY }, > { "while", RID_WHILE, 0 }, > > -#define DEFTRAIT(TCC, CODE, NAME, ARITY) \ > - { NAME, RID_##CODE, D_CXXONLY }, > +#define DEFTRAIT_EXPR(CODE, NAME, ARITY) \ > + { NAME, RID_TRAIT_EXPR, D_CXXONLY }, > #include "cp/cp-trait.def" > -#undef DEFTRAIT > +#undef DEFTRAIT_EXPR > /* An alias for __is_same. */ > - { "__is_same_as", RID_IS_SAME, D_CXXONLY }, > + { "__is_same_as", RID_TRAIT_EXPR, D_CXXONLY }, > +#define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ > + { NAME, RID_TRAIT_TYPE, D_CXXONLY }, > +#include "cp/cp-trait.def" > +#undef DEFTRAIT_TYPE > > /* 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 1fdba7ef3ea..a1a641f4175 100644 > --- a/gcc/c-family/c-common.h > +++ b/gcc/c-family/c-common.h > @@ -168,10 +168,9 @@ 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++ traits, defined in cp-trait.def. */ > + RID_TRAIT_EXPR, > + RID_TRAIT_TYPE, > > /* C++11 */ > RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT, > diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in > index 2727fb7f8cc..8d4e3a1f594 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 = @AWK@ > + > # Actual names to use when installing a native compiler. > CXX_INSTALL_NAME := $(shell echo c++|sed '$(program_transform_name)') > GXX_INSTALL_NAME := $(shell echo g++|sed '$(program_transform_name)') > @@ -186,6 +188,28 @@ 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)/cp/cp-trait.h > + > +# The cp-trait.gperf file itself is generated from a cp-trait.def file. > +$(srcdir)/cp/cp-trait.gperf: $(srcdir)/cp/cp-trait.def $(srcdir)/cp/cp-trait-head.in > + cat $(srcdir)/cp/cp-trait-head.in > $@ > + $(AWK) -F', *' '/^DEFTRAIT_/ { \ > + type = (index($$1, "DEFTRAIT_TYPE") != 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 = "bfd opcodes binutils fixincludes gas gcc gmp mpfr mpc isl gold intl ld libbacktrace libcpp libcody libdecnumber libiberty libiberty-linker-plugin libiconv zlib lto-plugin libctf libsframe" > components_in_prev_target = "libstdc++-v3 libsanitizer libvtv libgcc libbacktrace libphobos zlib libgomp libatomic" > > diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc > index 93b027b80ce..c414d8f5a13 100644 > --- a/gcc/cp/cp-objcp-common.cc > +++ b/gcc/cp/cp-objcp-common.cc > @@ -434,10 +434,8 @@ 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 > + case RID_TRAIT_EXPR: > + case RID_TRAIT_TYPE: > 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=C++ > +%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 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 > +. */ > +%} > +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=C++ > +%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 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 > +. */ > +%} > +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, false > +"__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, false > +"__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_REPRESENTATIONS, 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, false > +"__is_nothrow_convertible", CPTK_IS_NOTHROW_CONVERTIBLE, 2, false > +"__is_pointer_interconvertible_base_of", CPTK_IS_POINTER_INTERCONVERTIBLE_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, false > +"__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_TEMPORARY, 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-file ../../gcc/cp/cp-trait.h ../../gcc/cp/cp-trait.gperf */ > + > +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ > + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ > + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ > + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ > + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ > + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ > + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ > + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ > + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ > + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ > + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ > + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ > + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ > + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ > + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ > + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ > + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ > + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ > + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ > + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ > + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ > + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ > + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) > +/* The character set is not based on ISO-646. */ > +#error "gperf generated tables don't work with this execution character 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 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 > +. */ > +#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 = 79, duplicates = 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[] = > + { > + 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 = len; > + > + switch (hval) > + { > + default: > + hval += 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 = 45, > + MIN_WORD_LENGTH = 7, > + MAX_WORD_LENGTH = 37, > + MIN_HASH_VALUE = 7, > + MAX_HASH_VALUE = 85 > + }; > + > + static const struct cp_trait wordlist[] = > + { > +#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, false}, > +#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_CONSTRUCTIBLE, -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_INTERCONVERTIBLE_BASE_OF, 2, false}, > +#line 52 "../../gcc/cp/cp-trait.gperf" > + {"__is_nothrow_assignable", CPTK_IS_NOTHROW_ASSIGNABLE, 2, false}, > +#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, false}, > +#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_FROM_TEMPORARY, 2, false}, > +#line 65 "../../gcc/cp/cp-trait.gperf" > + {"__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_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[] = > + { > + -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 <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) > + { > + unsigned int key = hash (str, len); > + > + if (key <= MAX_HASH_VALUE) > + { > + int index = lookup[key]; > + > + if (index >= 0) > + { > + const char *s = wordlist[index].name; > + > + if (*str == *s && !strcmp (str + 1, s + 1)) > + return &wordlist[index]; > + } > + } > + } > + return 0; > +} > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index f3abae716fe..432c43400ab 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see > #include "contracts.h" > #include "bitmap.h" > #include "builtins.h" > +#include "cp-trait.h" > > > /* The lexer. */ > @@ -1165,12 +1166,8 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword) > /* 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 > + /* C++ type-yielding built-in traits, defined in cp-trait.def. */ > + case RID_TRAIT_TYPE: > return true; > > default: > @@ -2854,7 +2851,7 @@ static void cp_parser_late_parsing_default_args > static tree cp_parser_sizeof_operand > (cp_parser *, enum rid); > static cp_expr cp_parser_trait > - (cp_parser *, enum rid); > + (cp_parser *, tree); > static bool cp_parser_declares_only_class_p > (cp_parser *); > static void cp_parser_set_storage_class > @@ -6021,11 +6018,8 @@ cp_parser_primary_expression (cp_parser *parser, > 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); > + case RID_TRAIT_EXPR: > + return cp_parser_trait (parser, token->u.value); > > // C++ concepts > case RID_REQUIRES: > @@ -11033,28 +11027,15 @@ cp_parser_builtin_offsetof (cp_parser *parser) > /* 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, tree keyword) > { > - cp_trait_kind kind; > - tree type1, type2 = NULL_TREE; > - bool binary = false; > - bool variadic = false; > - bool type = false; > + const char* keyword_str = IDENTIFIER_POINTER (keyword); > + int keyword_len = IDENTIFIER_LENGTH (keyword); > + const cp_trait* trait = cp_trait_lookup::find (keyword_str, keyword_len); > > - switch (keyword) > - { > -#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 (); > - } > + tree type1, type2 = NULL_TREE; > + bool binary = (trait->arity == 2); > + bool variadic = (trait->arity == -1); > > /* Get location of initial token. */ > location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; > @@ -11063,12 +11044,12 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > cp_lexer_consume_token (parser->lexer); > > matching_parens parens; > - if (kind == CPTK_TYPE_PACK_ELEMENT) > + if (trait->kind == CPTK_TYPE_PACK_ELEMENT) > cp_parser_require (parser, CPP_LESS, RT_LESS); > else > parens.require_open (parser); > > - if (kind == CPTK_IS_DEDUCIBLE) > + if (trait->kind == CPTK_IS_DEDUCIBLE) > { > const cp_token* token = cp_lexer_peek_token (parser->lexer); > type1 = cp_parser_id_expression (parser, > @@ -11079,7 +11060,7 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > /*optional_p=*/false); > type1 = cp_parser_lookup_name_simple (parser, type1, token->location); > } > - else if (kind == CPTK_TYPE_PACK_ELEMENT) > + else if (trait->kind == CPTK_TYPE_PACK_ELEMENT) > /* __type_pack_element takes an expression as its first argument and uses > template-id syntax instead of function call syntax (for consistency > with Clang). We special case these properties of __type_pack_element > @@ -11094,7 +11075,7 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > if (type1 == error_mark_node) > return error_mark_node; > > - if (kind == CPTK_TYPE_PACK_ELEMENT) > + if (trait->kind == CPTK_TYPE_PACK_ELEMENT) > { > cp_parser_require (parser, CPP_COMMA, RT_COMMA); > tree trailing = cp_parser_enclosed_template_argument_list (parser); > @@ -11144,7 +11125,7 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > } > > location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; > - if (kind == CPTK_TYPE_PACK_ELEMENT) > + if (trait->kind == CPTK_TYPE_PACK_ELEMENT) > /* cp_parser_enclosed_template_argument_list above already took care > of parsing the closing '>'. */; > else > @@ -11158,17 +11139,17 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) > > /* Complete the trait expression, which may mean either processing > 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_error); > + if (trait->type) > + return finish_trait_type (trait->kind, type1, type2, tf_warning_or_error); > else > - return finish_trait_expr (trait_loc, kind, type1, type2); > + return finish_trait_expr (trait_loc, trait->kind, type1, type2); > } > } > > @@ -20081,11 +20062,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, > > return type; > > -#define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ > - case RID_##CODE: > -#include "cp-trait.def" > -#undef DEFTRAIT_TYPE > - type = cp_parser_trait (parser, token->keyword); > + case RID_TRAIT_TYPE: > + type = cp_parser_trait (parser, token->u.value); > if (decl_specs) > cp_parser_set_decl_spec_type (decl_specs, type, > token, > -- > 2.42.0 > >