[C++ PATCH] overloaded operator fns [5/N]
https://gcc.gnu.org/ml/gcc-patches/2017-10/ * 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. From-SVN: r254279
This commit is contained in:
parent
c67624232a
commit
881c969cf6
5 changed files with 68 additions and 61 deletions
|
@ -1,5 +1,18 @@
|
|||
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
|
||||
|
|
|
@ -5485,29 +5485,26 @@ enum ovl_op_flags
|
|||
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. */
|
||||
|
|
|
@ -12898,8 +12898,8 @@ unary_op_p (enum tree_code code)
|
|||
|| 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)
|
||||
|
@ -12912,52 +12912,54 @@ 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;
|
||||
|
||||
|
@ -12987,12 +12989,12 @@ grok_op_properties (tree decl, bool complain)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -13043,9 +13045,9 @@ grok_op_properties (tree decl, bool complain)
|
|||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
|
10
gcc/cp/lex.c
10
gcc/cp/lex.c
|
@ -77,10 +77,7 @@ cxx_finish (void)
|
|||
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. */
|
||||
|
||||
|
@ -117,7 +114,7 @@ set_identifier_kind (tree id, cp_identifier_kind kind)
|
|||
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",
|
||||
|
@ -136,12 +133,13 @@ static void
|
|||
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); \
|
||||
|
|
|
@ -1265,32 +1265,29 @@ write_unqualified_id (tree identifier)
|
|||
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))
|
||||
|
|
Loading…
Add table
Reference in a new issue