Message ID | 20231013223957.1634024-3-kmatsui@gcc.gnu.org |
---|---|
State | New |
Headers | show |
Series | Optimize type traits performance | expand |
On Fri, 13 Oct 2023, Ken Matsui wrote: > Since RID_MAX soon reaches 255 and all built-in traits are used approximately > once in a C++ translation unit, this patch removes all RID values for built-in > traits and uses gperf to look up the specific trait. Rather than holding > traits as keywords, we set all trait identifiers as cik_trait, which 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 identifier to cp_trait_kind would be implicit in each IDENTIFIER node, which would perhaps be a nice simplification (and just as fast if not faster than gperf)? > > 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 traits. > > 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-yielding > built-in trait. > (cp_keyword_starts_decl_specifier_p): Remove all RID value cases > 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 for > 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 <ppalka@redhat.com> > Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org> > --- > 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_reswords[] = > { "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_TRANSMEM }, > 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_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..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 built-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=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 > +<http://www.gnu.org/licenses/>. */ > +%} > +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 > +<http://www.gnu.org/licenses/>. */ > +%} > +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 <bug-gperf@gnu.org>." > +#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 > +<http://www.gnu.org/licenses/>. */ > +#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<unsigned char>(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/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 = 4, /* Non-assignment operator name. */ > cik_assign_op = 5, /* An assignment operator name. */ > cik_conv_op = 6, /* Conversion operator name. */ > - cik_reserved_for_udlit = 7, /* Not yet in use */ > + cik_trait = 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 see > #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 = get_identifier (NAME); \ > + set_identifier_kind (id, cik_trait); > +#include "cp/cp-trait.def" > +#undef DEFTRAIT > + > + /* An alias for __is_same. */ > + id = 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 = 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 see > #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 >= 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 = token->u.value; > + > + if (token->type == CPP_NAME > + && TREE_CODE (id) == IDENTIFIER_NODE > + && IDENTIFIER_TRAIT_P (id)) > + { > + const char *id_str = IDENTIFIER_POINTER (id); > + const int id_len = 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 = 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 = 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 = 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_args > 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 *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); > - > // C++ concepts > case RID_REQUIRES: > return cp_parser_requires_expression (parser); > @@ -6065,6 +6107,12 @@ cp_parser_primary_expression (cp_parser *parser, > `::' as the beginning of a qualified-id, or the "operator" > keyword. */ > case CPP_NAME: > + { > + const cp_trait* trait = 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 *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, const cp_trait* trait) > { > - cp_trait_kind kind; > tree type1, type2 = NULL_TREE; > - bool binary = false; > - bool variadic = false; > - bool type = false; > - > - 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 (); > - } > + const bool binary = (trait->arity == 2); > + const bool variadic = (trait->arity == -1); > > /* Get location of initial token. */ > location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; > @@ -11063,12 +11094,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 +11110,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 +11125,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 +11175,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 +11189,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,20 +20112,21 @@ 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); > + default: > + break; > + } > + > + /* If token is a type-yielding built-in traits, parse it. */ > + const cp_trait* trait = cp_lexer_lookup_trait_type (token); > + if (trait) > + { > + type = cp_parser_trait (parser, trait); > if (decl_specs) > cp_parser_set_decl_spec_type (decl_specs, type, > token, > /*type_definition_p=*/false); > > return type; > - > - default: > - break; > } > > /* If token is an already-parsed decltype not followed by ::, > -- > 2.42.0 > >
On Sun, Oct 15, 2023 at 1:43 PM Patrick Palka <ppalka@redhat.com> wrote: > > On Fri, 13 Oct 2023, Ken Matsui wrote: > > > Since RID_MAX soon reaches 255 and all built-in traits are used approximately > > once in a C++ translation unit, this patch removes all RID values for built-in > > traits and uses gperf to look up the specific trait. Rather than holding > > traits as keywords, we set all trait identifiers as cik_trait, which 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 identifier > to cp_trait_kind would be implicit in each IDENTIFIER node, which would > 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? > > > > 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 traits. > > > > 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-yielding > > built-in trait. > > (cp_keyword_starts_decl_specifier_p): Remove all RID value cases > > 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 for > > 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 <ppalka@redhat.com> > > Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org> > > --- > > 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_reswords[] = > > { "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_TRANSMEM }, > > 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_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..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 built-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=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 > > +<http://www.gnu.org/licenses/>. */ > > +%} > > +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 > > +<http://www.gnu.org/licenses/>. */ > > +%} > > +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 <bug-gperf@gnu.org>." > > +#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 > > +<http://www.gnu.org/licenses/>. */ > > +#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<unsigned char>(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/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 = 4, /* Non-assignment operator name. */ > > cik_assign_op = 5, /* An assignment operator name. */ > > cik_conv_op = 6, /* Conversion operator name. */ > > - cik_reserved_for_udlit = 7, /* Not yet in use */ > > + cik_trait = 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 see > > #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 = get_identifier (NAME); \ > > + set_identifier_kind (id, cik_trait); > > +#include "cp/cp-trait.def" > > +#undef DEFTRAIT > > + > > + /* An alias for __is_same. */ > > + id = 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 = 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 see > > #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 >= 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 = token->u.value; > > + > > + if (token->type == CPP_NAME > > + && TREE_CODE (id) == IDENTIFIER_NODE > > + && IDENTIFIER_TRAIT_P (id)) > > + { > > + const char *id_str = IDENTIFIER_POINTER (id); > > + const int id_len = 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 = 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 = 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 = 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_args > > 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 *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); > > - > > // C++ concepts > > case RID_REQUIRES: > > return cp_parser_requires_expression (parser); > > @@ -6065,6 +6107,12 @@ cp_parser_primary_expression (cp_parser *parser, > > `::' as the beginning of a qualified-id, or the "operator" > > keyword. */ > > case CPP_NAME: > > + { > > + const cp_trait* trait = 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 *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, const cp_trait* trait) > > { > > - cp_trait_kind kind; > > tree type1, type2 = NULL_TREE; > > - bool binary = false; > > - bool variadic = false; > > - bool type = false; > > - > > - 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 (); > > - } > > + const bool binary = (trait->arity == 2); > > + const bool variadic = (trait->arity == -1); > > > > /* Get location of initial token. */ > > location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; > > @@ -11063,12 +11094,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 +11110,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 +11125,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 +11175,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 +11189,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,20 +20112,21 @@ 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); > > + default: > > + break; > > + } > > + > > + /* If token is a type-yielding built-in traits, parse it. */ > > + const cp_trait* trait = cp_lexer_lookup_trait_type (token); > > + if (trait) > > + { > > + type = cp_parser_trait (parser, trait); > > if (decl_specs) > > cp_parser_set_decl_spec_type (decl_specs, type, > > token, > > /*type_definition_p=*/false); > > > > return type; > > - > > - default: > > - break; > > } > > > > /* If token is an already-parsed decltype not followed by ::, > > -- > > 2.42.0 > > > > >
On Sun, 15 Oct 2023, Ken Matsui wrote: > On Sun, Oct 15, 2023 at 1:43 PM Patrick Palka <ppalka@redhat.com> wrote: > > > > On Fri, 13 Oct 2023, Ken Matsui wrote: > > > > > Since RID_MAX soon reaches 255 and all built-in traits are used approximately > > > once in a C++ translation unit, this patch removes all RID values for built-in > > > traits and uses gperf to look up the specific trait. Rather than holding > > > traits as keywords, we set all trait identifiers as cik_trait, which 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 identifier > > to cp_trait_kind would be implicit in each IDENTIFIER node, which would > > 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 :) > > > > > > > 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 traits. > > > > > > 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-yielding > > > built-in trait. > > > (cp_keyword_starts_decl_specifier_p): Remove all RID value cases > > > 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 for > > > 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 <ppalka@redhat.com> > > > Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org> > > > --- > > > 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_reswords[] = > > > { "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_TRANSMEM }, > > > 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_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..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 built-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=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 > > > +<http://www.gnu.org/licenses/>. */ > > > +%} > > > +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 > > > +<http://www.gnu.org/licenses/>. */ > > > +%} > > > +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 <bug-gperf@gnu.org>." > > > +#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 > > > +<http://www.gnu.org/licenses/>. */ > > > +#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<unsigned char>(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/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 = 4, /* Non-assignment operator name. */ > > > cik_assign_op = 5, /* An assignment operator name. */ > > > cik_conv_op = 6, /* Conversion operator name. */ > > > - cik_reserved_for_udlit = 7, /* Not yet in use */ > > > + cik_trait = 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 see > > > #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 = get_identifier (NAME); \ > > > + set_identifier_kind (id, cik_trait); > > > +#include "cp/cp-trait.def" > > > +#undef DEFTRAIT > > > + > > > + /* An alias for __is_same. */ > > > + id = 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 = 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 see > > > #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 >= 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 = token->u.value; > > > + > > > + if (token->type == CPP_NAME > > > + && TREE_CODE (id) == IDENTIFIER_NODE > > > + && IDENTIFIER_TRAIT_P (id)) > > > + { > > > + const char *id_str = IDENTIFIER_POINTER (id); > > > + const int id_len = 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 = 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 = 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 = 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_args > > > 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 *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); > > > - > > > // C++ concepts > > > case RID_REQUIRES: > > > return cp_parser_requires_expression (parser); > > > @@ -6065,6 +6107,12 @@ cp_parser_primary_expression (cp_parser *parser, > > > `::' as the beginning of a qualified-id, or the "operator" > > > keyword. */ > > > case CPP_NAME: > > > + { > > > + const cp_trait* trait = 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 *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, const cp_trait* trait) > > > { > > > - cp_trait_kind kind; > > > tree type1, type2 = NULL_TREE; > > > - bool binary = false; > > > - bool variadic = false; > > > - bool type = false; > > > - > > > - 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 (); > > > - } > > > + const bool binary = (trait->arity == 2); > > > + const bool variadic = (trait->arity == -1); > > > > > > /* Get location of initial token. */ > > > location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; > > > @@ -11063,12 +11094,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 +11110,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 +11125,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 +11175,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 +11189,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,20 +20112,21 @@ 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); > > > + default: > > > + break; > > > + } > > > + > > > + /* If token is a type-yielding built-in traits, parse it. */ > > > + const cp_trait* trait = cp_lexer_lookup_trait_type (token); > > > + if (trait) > > > + { > > > + type = cp_parser_trait (parser, trait); > > > if (decl_specs) > > > cp_parser_set_decl_spec_type (decl_specs, type, > > > token, > > > /*type_definition_p=*/false); > > > > > > return type; > > > - > > > - default: > > > - break; > > > } > > > > > > /* If token is an already-parsed decltype not followed by ::, > > > -- > > > 2.42.0 > > > > > > > > > >
On Sun, Oct 15, 2023 at 2:50 PM Patrick Palka <ppalka@redhat.com> wrote: > > On Sun, 15 Oct 2023, Ken Matsui wrote: > > > On Sun, Oct 15, 2023 at 1:43 PM Patrick Palka <ppalka@redhat.com> wrote: > > > > > > On Fri, 13 Oct 2023, Ken Matsui wrote: > > > > > > > Since RID_MAX soon reaches 255 and all built-in traits are used approximately > > > > once in a C++ translation unit, this patch removes all RID values for built-in > > > > traits and uses gperf to look up the specific trait. Rather than holding > > > > traits as keywords, we set all trait identifiers as cik_trait, which 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 identifier > > > to cp_trait_kind would be implicit in each IDENTIFIER node, which would > > > 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 traits. > > > > > > > > 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-yielding > > > > built-in trait. > > > > (cp_keyword_starts_decl_specifier_p): Remove all RID value cases > > > > 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 for > > > > 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 <ppalka@redhat.com> > > > > Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org> > > > > --- > > > > 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_reswords[] = > > > > { "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_TRANSMEM }, > > > > 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_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..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 built-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=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 > > > > +<http://www.gnu.org/licenses/>. */ > > > > +%} > > > > +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 > > > > +<http://www.gnu.org/licenses/>. */ > > > > +%} > > > > +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 <bug-gperf@gnu.org>." > > > > +#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 > > > > +<http://www.gnu.org/licenses/>. */ > > > > +#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<unsigned char>(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/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 = 4, /* Non-assignment operator name. */ > > > > cik_assign_op = 5, /* An assignment operator name. */ > > > > cik_conv_op = 6, /* Conversion operator name. */ > > > > - cik_reserved_for_udlit = 7, /* Not yet in use */ > > > > + cik_trait = 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 see > > > > #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 = get_identifier (NAME); \ > > > > + set_identifier_kind (id, cik_trait); > > > > +#include "cp/cp-trait.def" > > > > +#undef DEFTRAIT > > > > + > > > > + /* An alias for __is_same. */ > > > > + id = 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 = 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 see > > > > #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 >= 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 = token->u.value; > > > > + > > > > + if (token->type == CPP_NAME > > > > + && TREE_CODE (id) == IDENTIFIER_NODE > > > > + && IDENTIFIER_TRAIT_P (id)) > > > > + { > > > > + const char *id_str = IDENTIFIER_POINTER (id); > > > > + const int id_len = 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 = 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 = 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 = 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_args > > > > 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 *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); > > > > - > > > > // C++ concepts > > > > case RID_REQUIRES: > > > > return cp_parser_requires_expression (parser); > > > > @@ -6065,6 +6107,12 @@ cp_parser_primary_expression (cp_parser *parser, > > > > `::' as the beginning of a qualified-id, or the "operator" > > > > keyword. */ > > > > case CPP_NAME: > > > > + { > > > > + const cp_trait* trait = 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 *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, const cp_trait* trait) > > > > { > > > > - cp_trait_kind kind; > > > > tree type1, type2 = NULL_TREE; > > > > - bool binary = false; > > > > - bool variadic = false; > > > > - bool type = false; > > > > - > > > > - 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 (); > > > > - } > > > > + const bool binary = (trait->arity == 2); > > > > + const bool variadic = (trait->arity == -1); > > > > > > > > /* Get location of initial token. */ > > > > location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; > > > > @@ -11063,12 +11094,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 +11110,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 +11125,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 +11175,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 +11189,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,20 +20112,21 @@ 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); > > > > + default: > > > > + break; > > > > + } > > > > + > > > > + /* If token is a type-yielding built-in traits, parse it. */ > > > > + const cp_trait* trait = cp_lexer_lookup_trait_type (token); > > > > + if (trait) > > > > + { > > > > + type = cp_parser_trait (parser, trait); > > > > if (decl_specs) > > > > cp_parser_set_decl_spec_type (decl_specs, type, > > > > token, > > > > /*type_definition_p=*/false); > > > > > > > > return type; > > > > - > > > > - default: > > > > - break; > > > > } > > > > > > > > /* If token is an already-parsed decltype not followed by ::, > > > > -- > > > > 2.42.0 > > > > > > > > > > > > > > >
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_reswords[] = { "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_TRANSMEM }, 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_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..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 built-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=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 +<http://www.gnu.org/licenses/>. */ +%} +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 +<http://www.gnu.org/licenses/>. */ +%} +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 <bug-gperf@gnu.org>." +#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 +<http://www.gnu.org/licenses/>. */ +#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<unsigned char>(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/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 = 4, /* Non-assignment operator name. */ cik_assign_op = 5, /* An assignment operator name. */ cik_conv_op = 6, /* Conversion operator name. */ - cik_reserved_for_udlit = 7, /* Not yet in use */ + cik_trait = 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 see #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 = get_identifier (NAME); \ + set_identifier_kind (id, cik_trait); +#include "cp/cp-trait.def" +#undef DEFTRAIT + + /* An alias for __is_same. */ + id = 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 = 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 see #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 >= 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 = token->u.value; + + if (token->type == CPP_NAME + && TREE_CODE (id) == IDENTIFIER_NODE + && IDENTIFIER_TRAIT_P (id)) + { + const char *id_str = IDENTIFIER_POINTER (id); + const int id_len = 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 = 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 = 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 = 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_args 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 *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); - // C++ concepts case RID_REQUIRES: return cp_parser_requires_expression (parser); @@ -6065,6 +6107,12 @@ cp_parser_primary_expression (cp_parser *parser, `::' as the beginning of a qualified-id, or the "operator" keyword. */ case CPP_NAME: + { + const cp_trait* trait = 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 *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, const cp_trait* trait) { - cp_trait_kind kind; tree type1, type2 = NULL_TREE; - bool binary = false; - bool variadic = false; - bool type = false; - - 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 (); - } + const bool binary = (trait->arity == 2); + const bool variadic = (trait->arity == -1); /* Get location of initial token. */ location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; @@ -11063,12 +11094,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 +11110,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 +11125,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 +11175,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 +11189,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,20 +20112,21 @@ 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); + default: + break; + } + + /* If token is a type-yielding built-in traits, parse it. */ + const cp_trait* trait = cp_lexer_lookup_trait_type (token); + if (trait) + { + type = cp_parser_trait (parser, trait); if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, type, token, /*type_definition_p=*/false); return type; - - default: - break; } /* If token is an already-parsed decltype not followed by ::,
Since RID_MAX soon reaches 255 and all built-in traits are used approximately once in a C++ translation unit, this patch removes all RID values for built-in traits and uses gperf to look up the specific trait. Rather than holding traits as keywords, we set all trait identifiers as cik_trait, which 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. 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 traits. 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-yielding built-in trait. (cp_keyword_starts_decl_specifier_p): Remove all RID value cases 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 for 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 <ppalka@redhat.com> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org> --- 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