aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/c-common.cc7
-rw-r--r--gcc/c-family/c-common.h5
-rw-r--r--gcc/cp/cp-objcp-common.cc8
-rw-r--r--gcc/cp/cp-tree.h32
-rw-r--r--gcc/cp/lex.cc34
-rw-r--r--gcc/cp/parser.cc105
6 files changed, 126 insertions, 65 deletions
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index d175054d..0f1de44 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -560,13 +560,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 cb9b6f3..62d76c8 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/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index 9439c4d..ee88df5 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -565,6 +565,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))
@@ -578,10 +582,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-tree.h b/gcc/cp/cp-tree.h
index cb89d37..cbf280e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1237,7 +1237,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
};
@@ -1282,9 +1282,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) \
@@ -1297,12 +1297,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) \
@@ -1386,16 +1392,26 @@ 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 indexed by cp_trait_kind. */
+extern const struct cp_trait cp_traits[];
+
/* The types that we are processing. */
#define TRAIT_EXPR_TYPE1(NODE) \
(((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->type1)
diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc
index 64bcfb1..a939e2e 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);
@@ -97,6 +98,19 @@ ovl_op_info_t ovl_op_info[2][OVL_OP_MAX] =
unsigned char ovl_op_mapping[MAX_TREE_CODES];
unsigned char ovl_op_alternate[OVL_OP_MAX];
+/* 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
+};
+/* The trait table cannot have more than 255 (addr_space_t) entries since
+ the index is retrieved through IDENTIFIER_CP_INDEX. */
+static_assert(ARRAY_SIZE (cp_traits) <= 255,
+ "cp_traits array cannot have more than 255 entries");
+
/* Get the name of the kind of identifier T. */
const char *
@@ -283,6 +297,25 @@ init_reswords (void)
}
}
+/* Initialize the C++ traits. */
+static void
+init_cp_traits (void)
+{
+ tree id;
+
+ for (unsigned int i = 0; i < ARRAY_SIZE (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 +357,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 de7af15..f23ef6b 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -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 *);
@@ -1173,12 +1179,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
@@ -1188,6 +1188,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
@@ -1196,6 +1234,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);
}
@@ -2861,7 +2901,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
@@ -6055,12 +6095,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);
@@ -6099,6 +6133,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:
@@ -11029,28 +11066,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;
@@ -20126,20 +20148,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 ::,