@@ -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 },
@@ -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,
@@ -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;
@@ -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) \
@@ -1375,16 +1381,27 @@ struct GTY (()) tree_argument_pack_select {
int index;
};
-/* The different kinds of traits that we encounter. */
-
-enum cp_trait_kind
-{
+/* The different kinds of traits that we encounter. The size is limited to
+ addr_space_t since a trait is looked up by IDENTIFIER_CP_INDEX. */
+enum cp_trait_kind : addr_space_t {
#define DEFTRAIT(TCC, CODE, NAME, ARITY) \
CPTK_##CODE,
#include "cp-trait.def"
#undef DEFTRAIT
};
+/* The trait type. */
+struct cp_trait {
+ const char *name;
+ cp_trait_kind kind;
+ short arity;
+ bool type;
+};
+
+/* The trait table. */
+extern const struct cp_trait cp_traits[];
+extern const addr_space_t num_cp_traits;
+
/* The types that we are processing. */
#define TRAIT_EXPR_TYPE1(NODE) \
(((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->type1)
@@ -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,25 @@ init_reswords (void)
}
}
+/* Initialize the C++ traits. */
+static void
+init_cp_traits (void)
+{
+ tree id;
+
+ for (unsigned int i = 0; i < num_cp_traits; ++i)
+ {
+ id = get_identifier (cp_traits[i].name);
+ IDENTIFIER_CP_INDEX (id) = cp_traits[i].kind;
+ set_identifier_kind (id, cik_trait);
+ }
+
+ /* An alias for __is_same. */
+ id = get_identifier ("__is_same_as");
+ IDENTIFIER_CP_INDEX (id) = CPTK_IS_SAME;
+ set_identifier_kind (id, cik_trait);
+}
+
static void
init_cp_pragma (void)
{
@@ -324,6 +344,7 @@ cxx_init (void)
input_location = BUILTINS_LOCATION;
init_reswords ();
+ init_cp_traits ();
init_tree ();
init_cp_semantics ();
init_operators ();
@@ -246,6 +246,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 *);
@@ -279,6 +285,21 @@ static FILE *cp_lexer_debug_stream;
sizeof, typeof, or alignof. */
int cp_unevaluated_operand;
+/* The trait table, declared in cp-tree.h. */
+const cp_trait cp_traits[] =
+{
+#define DEFTRAIT(TCC, CODE, NAME, ARITY) \
+ { NAME, CPTK_##CODE, ARITY, (TCC == tcc_type) },
+#include "cp-trait.def"
+#undef DEFTRAIT
+};
+const addr_space_t num_cp_traits = ARRAY_SIZE (cp_traits);
+
+/* The trait table cannot have more than 255 (addr_space_t) entries since
+ the index is retrieved through IDENTIFIER_CP_INDEX. */
+static_assert(num_cp_traits <= 255,
+ "cp_traits array cannot have more than 255 entries");
+
/* Dump up to NUM tokens in BUFFER to FILE starting with token
START_TOKEN. If START_TOKEN is NULL, the dump starts with the
first token in BUFFER. If NUM is 0, dump all the tokens. If
@@ -1167,12 +1188,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 +1197,44 @@ 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)
+{
+ if (token->type == CPP_NAME && IDENTIFIER_TRAIT_P (token->u.value))
+ return &cp_traits[IDENTIFIER_CP_INDEX (token->u.value)];
+
+ 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 +1243,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 +2909,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
@@ -6029,12 +6084,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);
@@ -6073,6 +6122,9 @@ cp_parser_primary_expression (cp_parser *parser,
`::' as the beginning of a qualified-id, or the "operator"
keyword. */
case CPP_NAME:
+ if (const cp_trait* trait = cp_lexer_lookup_trait_expr (token))
+ return cp_parser_trait (parser, trait);
+ /* FALLTHRU */
case CPP_SCOPE:
case CPP_TEMPLATE_ID:
case CPP_NESTED_NAME_SPECIFIER:
@@ -11041,28 +11093,13 @@ 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;
+ const cp_trait_kind kind = trait->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);
+ const bool type = trait->type;
/* Get location of initial token. */
location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -20089,20 +20126,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 ::,