aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/lex.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2017-11-01 14:03:27 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2017-11-01 14:03:27 +0000
commitd6dd9d7f8efcf92c5c70a9e91e99a9719b31cd51 (patch)
tree46fe2615cfcde921d2e8142f94bf117cca7fcf43 /gcc/cp/lex.c
parent0299d48bad088eccb76cf71de064dbc047b8cf62 (diff)
downloadgcc-d6dd9d7f8efcf92c5c70a9e91e99a9719b31cd51.zip
gcc-d6dd9d7f8efcf92c5c70a9e91e99a9719b31cd51.tar.gz
gcc-d6dd9d7f8efcf92c5c70a9e91e99a9719b31cd51.tar.bz2
[C++ PATCH] overloaded operator fns [6/N]
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00018.html * cp-tree.h (IDENTIFIER_CP_INDEX): Define. (enum ovl_op_flags): Add OVL_OP_FLAG_AMBIARY. (enum ovl_op_code): New. (struct ovl_op_info): Add ovl_op_code field. (ovl_op_info): Size by OVL_OP_MAX. (ovl_op_mapping, ovl_op_alternate): Declare. (OVL_OP_INFO): Adjust for mapping array. (IDENTIFIER_OVL_OP_INFO): New. * decl.c (ambi_op_p, unary_op_p): Delete. (grok_op_properties): Use IDENTIFIER_OVL_OP_INFO and ovl_op_alternate. * lex.c (ovl_op_info): Adjust and static initialize. (ovl_op_mappings, ovl_op_alternate): Define. (init_operators): Iterate over ovl_op_info array and init mappings & alternate arrays. * mangle.c (write_unqualified_id): Use IDENTIFIER_OVL_OP_INFO. * operators.def (DEF_OPERATOR): Remove KIND parm. (DEF_SIMPLE_OPERATOR): Delete. (OPERATOR_TRANSITION): Expand if defined. From-SVN: r254310
Diffstat (limited to 'gcc/cp/lex.c')
-rw-r--r--gcc/cp/lex.c98
1 files changed, 81 insertions, 17 deletions
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index af081f4..7754145 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -77,7 +77,20 @@ cxx_finish (void)
c_common_finish ();
}
-ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES];
+ovl_op_info_t ovl_op_info[2][OVL_OP_MAX] =
+ {
+ {
+ {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0},
+ {NULL_TREE, NULL, NULL, NOP_EXPR, OVL_OP_NOP_EXPR, 0},
+#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS) \
+ {NULL_TREE, NAME, MANGLING, CODE, OVL_OP_##CODE, FLAGS},
+#define OPERATOR_TRANSITION }, { \
+ {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0},
+#include "operators.def"
+ }
+ };
+unsigned char ovl_op_mapping[MAX_TREE_CODES];
+unsigned char ovl_op_alternate[OVL_OP_MAX];
/* Get the name of the kind of identifier T. */
@@ -129,26 +142,77 @@ set_operator_ident (ovl_op_info_t *ptr)
return ident;
}
+/* Initialize data structures that keep track of operator names. */
+
static void
init_operators (void)
{
- tree identifier;
- ovl_op_info_t *oni;
-
-#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, KIND) \
- oni = OVL_OP_INFO (KIND == cik_assign_op, CODE); \
- oni->name = NAME; \
- oni->mangled_name = MANGLING; \
- oni->tree_code = CODE; \
- oni->flags = FLAGS; \
- if (NAME) { \
- identifier = set_operator_ident (oni); \
- if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier)) \
- set_identifier_kind (identifier, KIND); \
- }
+ /* We rely on both these being zero. */
+ gcc_checking_assert (!OVL_OP_ERROR_MARK && !ERROR_MARK);
-#include "operators.def"
-#undef DEF_OPERATOR
+ /* This loop iterates backwards because we need to move the
+ assignment operators down to their correct slots. I.e. morally
+ equivalent to an overlapping memmove where dest > src. Slot
+ zero is for error_mark, so hae no operator. */
+ for (unsigned ix = OVL_OP_MAX; --ix;)
+ {
+ ovl_op_info_t *op_ptr = &ovl_op_info[false][ix];
+
+ if (op_ptr->name)
+ {
+ /* Make sure it fits in lang_decl_fn::operator_code. */
+ gcc_checking_assert (op_ptr->ovl_op_code < (1 << 6));
+ tree ident = set_operator_ident (op_ptr);
+ if (unsigned index = IDENTIFIER_CP_INDEX (ident))
+ {
+ ovl_op_info_t *bin_ptr = &ovl_op_info[false][index];
+
+ /* They should only differ in unary/binary ness. */
+ gcc_checking_assert ((op_ptr->flags ^ bin_ptr->flags)
+ == OVL_OP_FLAG_AMBIARY);
+ bin_ptr->flags |= op_ptr->flags;
+ ovl_op_alternate[index] = ix;
+ }
+ else
+ {
+ IDENTIFIER_CP_INDEX (ident) = ix;
+ set_identifier_kind (ident,
+ op_ptr->flags & OVL_OP_FLAG_ALLOC
+ ? cik_newdel_op : cik_simple_op);
+ }
+ }
+ if (op_ptr->tree_code)
+ {
+ gcc_checking_assert (op_ptr->ovl_op_code == ix
+ && !ovl_op_mapping[op_ptr->tree_code]);
+ ovl_op_mapping[op_ptr->tree_code] = op_ptr->ovl_op_code;
+ }
+
+ ovl_op_info_t *as_ptr = &ovl_op_info[true][ix];
+ if (as_ptr->name)
+ {
+ /* These will be placed at the start of the array, move to
+ the correct slot and initialize. */
+ if (as_ptr->ovl_op_code != ix)
+ {
+ ovl_op_info_t *dst_ptr = &ovl_op_info[true][as_ptr->ovl_op_code];
+ gcc_assert (as_ptr->ovl_op_code > ix && !dst_ptr->tree_code);
+ memcpy (dst_ptr, as_ptr, sizeof (*dst_ptr));
+ memset (as_ptr, 0, sizeof (*as_ptr));
+ as_ptr = dst_ptr;
+ }
+
+ tree ident = set_operator_ident (as_ptr);
+ gcc_checking_assert (!IDENTIFIER_CP_INDEX (ident));
+ IDENTIFIER_CP_INDEX (ident) = as_ptr->ovl_op_code;
+ set_identifier_kind (ident, cik_assign_op);
+
+ gcc_checking_assert (!ovl_op_mapping[as_ptr->tree_code]
+ || (ovl_op_mapping[as_ptr->tree_code]
+ == as_ptr->ovl_op_code));
+ ovl_op_mapping[as_ptr->tree_code] = as_ptr->ovl_op_code;
+ }
+ }
}
/* Initialize the reserved words. */