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 5421B385773F for ; Thu, 12 Oct 2023 17:03:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5421B385773F 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=1697130189; 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=V7pNy6jqKui0BMhrntV8KtqJJ/2eXO57KwBXE+h2C3o=; b=IcC9QuDsjA0at8ZwGH6JiqMrSO8ci7fa7Fm8NlfyVIRCc4n8CAM6TdkfMxGg3+dnIyoexP nXAvG8hTQ3AcedW91T6QKpIBa3w1qcg+OQ5MhaKTie5gyqGpRproDJBI6pQbzlygZ8kLMn oobqDnPKfYdAPT9AxwVx1V6OTpraOdI= Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-593-yUP_9nxxPNOWwLok7UBhog-1; Thu, 12 Oct 2023 13:03:02 -0400 X-MC-Unique: yUP_9nxxPNOWwLok7UBhog-1 Received: by mail-qt1-f198.google.com with SMTP id d75a77b69052e-41b49c0c2b8so11901791cf.0 for ; Thu, 12 Oct 2023 10:03:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697130181; x=1697734981; 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=dpgLPIDsSAvShTZWIfz/A4Gc6PPVLODjMhGWBsvPikY=; b=vjCDvkGwFoKojW2zOo4wc6VRiyi7gsPbh9Ql35UR+gwfMPoeDy5+5azAbCgx1H3BFO w5FCW2u/7Vor6/00jkVRSEc5Z3Z0lchh7SGpNrY5FGJgxPZJ97FZn9GdBfGaRzrjfp1w 4liIHukSlwugcAPzFJ9K1odxtXRB3+ASROCtA8o6imicCHdMrYowi3/9scrphfrtZ6kz hlt5pIiJOmj7VaQcJcA2VeGf0krM1f+ZzcLdTftbztSscO5kuZ9t/kgODKyRUUAIoWZk lr6yr7eHffGcx6/P5Oy9qAlZtdb5QTmaFF+gLw45R/sCjI8tiCRKyMClkTLYp02n2sDD MJWg== X-Gm-Message-State: AOJu0YxQVP3YMFZtuyTG0BcmtDlG3JTnY5mHgyrbYFVWPgS2/sTPCXQS YBnalQd2Lymdh/RtE7gRN9vu8dz1O+tMLWJMkxgvFGIXncpUmlAIt1eUmdKQifkzeLb4Wgquqke AwgiuS7UEEeGu4RB0e1PKZBg= X-Received: by 2002:a05:622a:282:b0:410:a895:21fd with SMTP id z2-20020a05622a028200b00410a89521fdmr32265479qtw.23.1697130181048; Thu, 12 Oct 2023 10:03:01 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEMxnuLm+ET6sq9q4XBPyo8zf9aHTMkqw7ahVd/JOohBH4Pc6+S+oZg0zLc2eYXR5e+9njt3Q== X-Received: by 2002:a05:622a:282:b0:410:a895:21fd with SMTP id z2-20020a05622a028200b00410a89521fdmr32265402qtw.23.1697130180376; Thu, 12 Oct 2023 10:03:00 -0700 (PDT) Received: from [192.168.1.130] (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id l25-20020ac84cd9000000b004181c32dcc3sm6334336qtv.16.2023.10.12.10.02.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Oct 2023 10:03:00 -0700 (PDT) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Thu, 12 Oct 2023 13:02:59 -0400 (EDT) To: Ken Matsui cc: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org, jason@redhat.com Subject: Re: [PATCH v17 02/39] c-family, c++: Look up built-in traits through gperf In-Reply-To: <20231011215049.1052142-3-kmatsui@gcc.gnu.org> Message-ID: <99d01572-89ae-77a6-2a9b-c52206d6072c@idea> References: <20231010221520.3680267-1-kmatsui@gcc.gnu.org> <20231011215049.1052142-1-kmatsui@gcc.gnu.org> <20231011215049.1052142-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.1 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 Wed, 11 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. > > 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. > * lex.cc (init_reswords): Make ridpointers for RID_TRAIT_EXPR and > RID_TRAIT_TYPE empty, which do not have corresponding unique > cannonical spellings. > * 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 | 26 ++++ > 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/lex.cc | 5 + > gcc/cp/parser.cc | 70 ++++------- > 9 files changed, 419 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..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 = @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,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)/cp/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 $(srcdir)/cp/cp-trait.def > + cat $< > $@ > + $(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/lex.cc b/gcc/cp/lex.cc > index 64bcfb18196..9eeb29adde5 100644 > --- a/gcc/cp/lex.cc > +++ b/gcc/cp/lex.cc > @@ -260,6 +260,11 @@ init_reswords (void) > set_identifier_kind (id, cik_keyword); > } > > + /* RID_TRAIT_EXPR and RID_TRAIT_TYPE do not have > + corresponding unique canonical spellings. */ > + ridpointers [(int) RID_TRAIT_EXPR] = nullptr; > + ridpointers [(int) RID_TRAIT_TYPE] = nullptr; Thanks! This gets the job done, but perhaps it suggests that treating these identifiers as keywords, and having them share the same rid code, isn't quite the best approach... really we'd want these identifiers to be classified as "conditional" keywords that are only treated as actual keywords whenever they're followed by a '(' (since the only thing you can do with a built-in trait is to call it) and are otherwise treated as ordinary identifiers in other contexts. This way existing uses of these names in e.g. libstdc++ will continue to be accepted, and won't need to be renamed. And we might as well implement this as part of this patch, since it'd replace the RID_TRAIT_EXPR / RID_TRAIT_TYPE approach. So I think we should: * get rid of RID_TRAIT_EXPR / RID_TRAIT_TYPE * add a new 'cik_trait' kind to cp_identifier_kind. Actually let's replace the unused cik_reserved_for_udlit with cik_trait, since we currently can't handle more than 7 kinds (we use 3 bits to encode cp_identifier_kind within the flags of an IDENTIFIER node) * set each built-in trait's identifier kind to cik_trait rather than to cik_keyword (in init_reswords or around there) * within the parser, replace existing RID_TRAIT_EXPR and RID_TRAIT_TYPE checks to instead check for a CPP_NAME token having a cik_trait identifier (for an expression- or type-yielding trait as appropriate) * In a follow-up patch, we can then refine these checks to additionally require that the subsequent token in the token stream is '(' (or '<' for the special __type_pack_element built-in trait) This last step will allow us to accept code like 'int __remove_cv = 42;" :D > + > for (i = 0; i < NUM_INT_N_ENTS; i++) > { > char name[50]; > 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 > >