2017-10-31 Nathan Sidwell <nathan@acm.org>
+ * cp-tree.h (struct operator_name_info_t): Rename to ...
+ (struct ovl_op_info_t): ... here. Add tree_code field.
+ (operator_name_info, assignment_operator_name_info): Delete.
+ (ovl_op_info): Declare.
+ (OVL_OP_INFO): Adjust.
+ * decl.c (grok_op_properties): Use ovl_op_flags.
+ * lex.c (operator_name_info, assignment_operator_name_info):
+ Delete.
+ (ovl_op_info): Define.
+ (set_operator_ident): Adjust.
+ (init_operators): Set tree_code.
+ * mangle.c (write_unqualified_id): Adjust operator array scan.
+
* lex.c (init_operators): Allow NULL operator name. Don't add
special cases.
* operators.def: Use NULL for mangling only operators. Move to
OVL_OP_FLAG_VEC = 2 /* vector new or delete */
};
-struct GTY(()) operator_name_info_t {
+struct GTY(()) ovl_op_info_t {
/* The IDENTIFIER_NODE for the operator. */
tree identifier;
/* The name of the operator. */
const char *name;
/* The mangled name of the operator. */
const char *mangled_name;
+ /* The tree code. */
+ enum tree_code tree_code : 16;
/* The ovl_op_flags of the operator */
unsigned flags : 8;
};
-/* A mapping from tree codes to operator name information. */
-extern GTY(()) operator_name_info_t operator_name_info
- [(int) MAX_TREE_CODES];
-/* Similar, but for assignment operators. */
-extern GTY(()) operator_name_info_t assignment_operator_name_info
- [(int) MAX_TREE_CODES];
+/* Overloaded operator info indexed by ass_op_p & tree_code. */
+extern GTY(()) ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES];
/* Given an ass_op_p boolean and a tree code, return a pointer to its
overloaded operator info. */
#define OVL_OP_INFO(IS_ASS_P, TREE_CODE) \
- (((IS_ASS_P) ? assignment_operator_name_info : operator_name_info) \
- + (TREE_CODE))
+ (&ovl_op_info[(IS_ASS_P) != 0][(TREE_CODE)])
/* A type-qualifier, or bitmask therefore, using the TYPE_QUAL
constants. */
|| code == TYPE_EXPR);
}
-/* DECL is a declaration for an overloaded operator. If COMPLAIN is true,
- errors are issued for invalid declarations. */
+/* DECL is a declaration for an overloaded or conversion operator. If
+ COMPLAIN is true, errors are issued for invalid declarations. */
bool
grok_op_properties (tree decl, bool complain)
if (class_type && !CLASS_TYPE_P (class_type))
class_type = NULL_TREE;
- enum tree_code operator_code = ERROR_MARK;
+ tree_code operator_code = ERROR_MARK;
+ unsigned op_flags = OVL_OP_FLAG_NONE;
if (IDENTIFIER_CONV_OP_P (name))
- operator_code = TYPE_EXPR;
+ {
+ /* Conversion operators are TYPE_EXPR for the purposes of this
+ function. */
+ operator_code = TYPE_EXPR;
+ op_flags = OVL_OP_FLAG_UNARY;
+ }
else
{
/* It'd be nice to hang something else of the identifier to
find CODE more directly. */
bool assign_op = IDENTIFIER_ASSIGN_OP_P (name);
- const operator_name_info_t *oni
- = (assign_op ? assignment_operator_name_info : operator_name_info);
-
+ const ovl_op_info_t *ovl_op = OVL_OP_INFO (assign_op, 0);
if (false)
;
-#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, KIND) \
- else if (assign_op == (KIND == cik_assign_op) \
- && oni[int (CODE)].identifier == name) \
+#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, KIND) \
+ else if (ovl_op[CODE].identifier == name) \
operator_code = (CODE);
#include "operators.def"
#undef DEF_OPERATOR
else
gcc_unreachable ();
- }
- while (0);
- gcc_assert (operator_code != MAX_TREE_CODES);
- DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code;
+ gcc_assert (operator_code != ERROR_MARK);
+ op_flags = ovl_op[operator_code].flags;
+ DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code;
+ }
- if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR
- || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
+ if (op_flags & OVL_OP_FLAG_ALLOC)
{
/* operator new and operator delete are quite special. */
if (class_type)
- switch (operator_code)
+ switch (op_flags)
{
- case NEW_EXPR:
+ case OVL_OP_FLAG_ALLOC:
TYPE_HAS_NEW_OPERATOR (class_type) = 1;
break;
- case DELETE_EXPR:
+ case OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE:
TYPE_GETS_DELETE (class_type) |= 1;
break;
- case VEC_NEW_EXPR:
+ case OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC:
TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1;
break;
- case VEC_DELETE_EXPR:
+ case OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC:
TYPE_GETS_DELETE (class_type) |= 2;
break;
}
}
- if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
+ if (op_flags & OVL_OP_FLAG_DELETE)
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
else
{
- TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
DECL_IS_OPERATOR_NEW (decl) = 1;
+ TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
}
return true;
}
}
- /* There are no restrictions on the arguments to an overloaded
- "operator ()". */
if (operator_code == CALL_EXPR)
+ /* There are no further restrictions on the arguments to an overloaded
+ "operator ()". */
return true;
if (operator_code == COND_EXPR)
c_common_finish ();
}
-/* A mapping from tree codes to operator name information. */
-operator_name_info_t operator_name_info[(int) MAX_TREE_CODES];
-/* Similar, but for assignment operators. */
-operator_name_info_t assignment_operator_name_info[(int) MAX_TREE_CODES];
+ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES];
/* Get the name of the kind of identifier T. */
operator PTR describes. */
static tree
-set_operator_ident (operator_name_info_t *ptr)
+set_operator_ident (ovl_op_info_t *ptr)
{
char buffer[32];
size_t len = snprintf (buffer, sizeof (buffer), "operator%s%s",
init_operators (void)
{
tree identifier;
- operator_name_info_t *oni;
+ 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); \
write_conversion_operator_name (TREE_TYPE (identifier));
else if (IDENTIFIER_ANY_OP_P (identifier))
{
- int i;
const char *mangled_name = NULL;
+ bool assop = IDENTIFIER_ASSIGN_OP_P (identifier);
/* Unfortunately, there is no easy way to go from the
name of the operator back to the corresponding tree
code. */
- for (i = 0; i < MAX_TREE_CODES; ++i)
- if (operator_name_info[i].identifier == identifier)
- {
- /* The ABI says that we prefer binary operator
- names to unary operator names. */
- if (operator_name_info[i].flags == OVL_OP_FLAG_BINARY)
- {
- mangled_name = operator_name_info[i].mangled_name;
- break;
- }
- else if (!mangled_name)
- mangled_name = operator_name_info[i].mangled_name;
- }
- else if (assignment_operator_name_info[i].identifier
- == identifier)
- {
- mangled_name
- = assignment_operator_name_info[i].mangled_name;
- break;
- }
+ for (unsigned i = 0; i < MAX_TREE_CODES; ++i)
+ {
+ const ovl_op_info_t *ovl_op = OVL_OP_INFO (assop, i);
+
+ if (ovl_op->identifier == identifier)
+ {
+ /* The ABI says that we prefer binary operator
+ names to unary operator names. */
+ if (ovl_op->flags == OVL_OP_FLAG_BINARY)
+ {
+ mangled_name = ovl_op->mangled_name;
+ break;
+ }
+ else if (!mangled_name)
+ mangled_name = ovl_op->mangled_name;
+ }
+ }
write_string (mangled_name);
}
else if (UDLIT_OPER_P (identifier))