summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog22
-rw-r--r--gcc/cp/cp-tree.h48
-rw-r--r--gcc/cp/decl.c143
-rw-r--r--gcc/cp/lex.c98
-rw-r--r--gcc/cp/mangle.c26
-rw-r--r--gcc/cp/operators.def167
6 files changed, 268 insertions, 236 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 00ac5938ee1..8f4cc9951ec 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,25 @@
+2017-11-01 Nathan Sidwell <nathan@acm.org>
+
+ * 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.
+
2017-10-31 David Malcolm <dmalcolm@redhat.com>
* pt.c (listify): Use %< and %> for description of #include.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 257c8776f0e..76ee8541daf 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1072,6 +1072,11 @@ enum cp_identifier_kind {
& IDENTIFIER_KIND_BIT_1 (NODE) \
& IDENTIFIER_KIND_BIT_0 (NODE))
+/* Access a C++-specific index for identifier NODE.
+ Used to optimize operator mappings etc. */
+#define IDENTIFIER_CP_INDEX(NODE) \
+ (IDENTIFIER_NODE_CHECK(NODE)->base.u.bits.address_space)
+
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
#define C_TYPE_FIELDS_READONLY(TYPE) \
(LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly)
@@ -5477,12 +5482,25 @@ extern void init_reswords (void);
/* Various flags for the overloaded operator information. */
enum ovl_op_flags
{
- OVL_OP_FLAG_NONE = 0,
- OVL_OP_FLAG_UNARY = 1,
- OVL_OP_FLAG_BINARY = 2,
- OVL_OP_FLAG_ALLOC = 4, /* operator new or delete */
- OVL_OP_FLAG_DELETE = 1, /* operator delete */
- OVL_OP_FLAG_VEC = 2 /* vector new or delete */
+ OVL_OP_FLAG_NONE = 0, /* Don't care. */
+ OVL_OP_FLAG_UNARY = 1, /* Is unary. */
+ OVL_OP_FLAG_BINARY = 2, /* Is binary. */
+ OVL_OP_FLAG_AMBIARY = 3, /* May be unary or binary. */
+ OVL_OP_FLAG_ALLOC = 4, /* operator new or delete. */
+ OVL_OP_FLAG_DELETE = 1, /* operator delete. */
+ OVL_OP_FLAG_VEC = 2 /* vector new or delete. */
+ };
+
+/* Compressed operator codes. Order is determined by operators.def
+ and does not match that of tree_codes. */
+enum ovl_op_code
+ {
+ OVL_OP_ERROR_MARK,
+ OVL_OP_NOP_EXPR,
+#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS) OVL_OP_##CODE,
+#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING) /* NOTHING */
+#include "operators.def"
+ OVL_OP_MAX
};
struct GTY(()) ovl_op_info_t {
@@ -5492,19 +5510,29 @@ struct GTY(()) ovl_op_info_t {
const char *name;
/* The mangled name of the operator. */
const char *mangled_name;
- /* The tree code. */
+ /* The (regular) tree code. */
enum tree_code tree_code : 16;
+ /* The (compressed) operator code. */
+ enum ovl_op_code ovl_op_code : 8;
/* The ovl_op_flags of the operator */
unsigned flags : 8;
};
-/* Overloaded operator info indexed by ass_op_p & tree_code. */
-extern GTY(()) ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES];
+/* Overloaded operator info indexed by ass_op_p & ovl_op_code. */
+extern GTY(()) ovl_op_info_t ovl_op_info[2][OVL_OP_MAX];
+/* Mapping from tree_codes to ovl_op_codes. */
+extern GTY(()) unsigned char ovl_op_mapping[MAX_TREE_CODES];
+/* Mapping for ambi-ary operators from the binary to the unary. */
+extern GTY(()) unsigned char ovl_op_alternate[OVL_OP_MAX];
/* 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) \
- (&ovl_op_info[(IS_ASS_P) != 0][(TREE_CODE)])
+ (&ovl_op_info[(IS_ASS_P) != 0][ovl_op_mapping[(TREE_CODE)]])
+/* Overloaded operator info for an identifier for which
+ IDENTIFIER_ANY_OP_P is true. */
+#define IDENTIFIER_OVL_OP_INFO(NODE) \
+ (&ovl_op_info[IDENTIFIER_ASSIGN_OP_P (NODE)][IDENTIFIER_CP_INDEX (NODE)])
/* A type-qualifier, or bitmask therefore, using the TYPE_QUAL
constants. */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d60b8dd775a..f43c960c939 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -65,8 +65,6 @@ static const char *redeclaration_error_message (tree, tree);
static int decl_jump_unsafe (tree);
static void require_complete_types_for_parms (tree);
-static bool ambi_op_p (enum tree_code);
-static bool unary_op_p (enum tree_code);
static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, int);
static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *,
@@ -12874,30 +12872,6 @@ grok_ctor_properties (const_tree ctype, const_tree decl)
return true;
}
-/* An operator with this code is unary, but can also be binary. */
-
-static bool
-ambi_op_p (enum tree_code code)
-{
- return (code == INDIRECT_REF
- || code == ADDR_EXPR
- || code == UNARY_PLUS_EXPR
- || code == NEGATE_EXPR
- || code == PREINCREMENT_EXPR
- || code == PREDECREMENT_EXPR);
-}
-
-/* An operator with this name can only be unary. */
-
-static bool
-unary_op_p (enum tree_code code)
-{
- return (code == TRUTH_NOT_EXPR
- || code == BIT_NOT_EXPR
- || code == COMPONENT_REF
- || code == TYPE_EXPR);
-}
-
/* DECL is a declaration for an overloaded or conversion operator. If
COMPLAIN is true, errors are issued for invalid declarations. */
@@ -12905,15 +12879,15 @@ bool
grok_op_properties (tree decl, bool complain)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
+ bool methodp = TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE;
tree name = DECL_NAME (decl);
tree class_type = DECL_CONTEXT (decl);
if (class_type && !CLASS_TYPE_P (class_type))
class_type = NULL_TREE;
- tree_code operator_code = ERROR_MARK;
- unsigned op_flags = OVL_OP_FLAG_NONE;
+ tree_code operator_code;
+ unsigned op_flags;
if (IDENTIFIER_CONV_OP_P (name))
{
/* Conversion operators are TYPE_EXPR for the purposes of this
@@ -12923,21 +12897,11 @@ grok_op_properties (tree decl, bool complain)
}
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 ovl_op_info_t *ovl_op = OVL_OP_INFO (assign_op, 0);
- if (false)
- ;
-#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 ();
- gcc_assert (operator_code != ERROR_MARK);
- op_flags = ovl_op[operator_code].flags;
+ const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (name);
+
+ operator_code = ovl_op->tree_code;
+ op_flags = ovl_op->flags;
+ gcc_checking_assert (operator_code != ERROR_MARK);
DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code;
}
@@ -13071,70 +13035,43 @@ grok_op_properties (tree decl, bool complain)
}
/* Verify correct number of arguments. */
- if (ambi_op_p (operator_code))
+ switch (op_flags)
{
+ case OVL_OP_FLAG_AMBIARY:
if (arity == 1)
- /* We pick the one-argument operator codes by default, so
- we don't have to change anything. */
- ;
- else if (arity == 2)
{
- /* If we thought this was a unary operator, we now know
- it to be a binary operator. */
- switch (operator_code)
- {
- case INDIRECT_REF:
- operator_code = MULT_EXPR;
- break;
-
- case ADDR_EXPR:
- operator_code = BIT_AND_EXPR;
- break;
-
- case UNARY_PLUS_EXPR:
- operator_code = PLUS_EXPR;
- break;
-
- case NEGATE_EXPR:
- operator_code = MINUS_EXPR;
- break;
-
- case PREINCREMENT_EXPR:
- operator_code = POSTINCREMENT_EXPR;
- break;
-
- case PREDECREMENT_EXPR:
- operator_code = POSTDECREMENT_EXPR;
- break;
-
- default:
- gcc_unreachable ();
- }
-
+ /* We have a unary instance of an ambi-ary op. Remap to the
+ unary one. */
+ unsigned alt = ovl_op_alternate[ovl_op_mapping [operator_code]];
+ const ovl_op_info_t *ovl_op = &ovl_op_info[false][alt];
+ gcc_checking_assert (ovl_op->flags == OVL_OP_FLAG_UNARY);
+ operator_code = ovl_op->tree_code;
DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code;
-
- if ((operator_code == POSTINCREMENT_EXPR
- || operator_code == POSTDECREMENT_EXPR)
- && ! processing_template_decl
- && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
- {
- error (methodp
- ? G_("postfix %qD must have %<int%> as its argument")
- : G_("postfix %qD must have %<int%> as its second argument"),
- decl);
- return false;
- }
}
- else
+ else if (arity != 2)
{
+ /* This was an ambiguous operator but is invalid. */
error (methodp
? G_("%qD must have either zero or one argument")
: G_("%qD must have either one or two arguments"), decl);
return false;
}
- }
- else if (unary_op_p (operator_code))
- {
+ else if ((operator_code == POSTINCREMENT_EXPR
+ || operator_code == POSTDECREMENT_EXPR)
+ && ! processing_template_decl
+ /* x++ and x--'s second argument must be an int. */
+ && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)),
+ integer_type_node))
+ {
+ error (methodp
+ ? G_("postfix %qD must have %<int%> as its argument")
+ : G_("postfix %qD must have %<int%> as its second argument"),
+ decl);
+ return false;
+ }
+ break;
+
+ case OVL_OP_FLAG_UNARY:
if (arity != 1)
{
error (methodp
@@ -13142,9 +13079,9 @@ grok_op_properties (tree decl, bool complain)
: G_("%qD must have exactly one argument"), decl);
return false;
}
- }
- else
- {
+ break;
+
+ case OVL_OP_FLAG_BINARY:
if (arity != 2)
{
error (methodp
@@ -13152,8 +13089,12 @@ grok_op_properties (tree decl, bool complain)
: G_("%qD must have exactly two arguments"), decl);
return false;
}
+ break;
+
+ default:
+ gcc_unreachable ();
}
-
+
/* There can be no default arguments. */
for (tree arg = argtypes; arg != void_list_node; arg = TREE_CHAIN (arg))
if (TREE_PURPOSE (arg))
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index af081f4d024..7754145f648 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. */
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 7feb889e9aa..27530f98f8f 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1265,30 +1265,8 @@ write_unqualified_id (tree identifier)
write_conversion_operator_name (TREE_TYPE (identifier));
else if (IDENTIFIER_ANY_OP_P (identifier))
{
- 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 (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);
+ const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (identifier);
+ write_string (ovl_op->mangled_name);
}
else if (UDLIT_OPER_P (identifier))
write_literal_operator_name (identifier);
diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def
index 51d2c3a09f4..119529ccddd 100644
--- a/gcc/cp/operators.def
+++ b/gcc/cp/operators.def
@@ -50,110 +50,109 @@ along with GCC; see the file COPYING3. If not see
ovl_op_flags bits. Postincrement and postdecrement operators are
marked as binary.
- ASSN_P
-
- A boolean value. If nonzero, this is an assignment operator.
-
Before including this file, you should define DEF_OPERATOR
to take these arguments.
There is code (such as in grok_op_properties) that depends on the
- order the operators are presented in this file. In particular,
- unary operators must precede binary operators. */
-
-/* Use DEF_SIMPLE_OPERATOR to define a non-assignment operator. Its
- arguments are as for DEF_OPERATOR, but there is no need to provide
- an ASSIGNMENT_P argument; it is always zero. */
-
-#define DEF_SIMPLE_OPERATOR(NAME, CODE, MANGLING, FLAGS) \
- DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_simple_op)
+ order the operators are presented in this file. Unary_ops must
+ preceed a matching binary op (i.e. '+'). Assignment operators must
+ be last, after OPERATOR_TRANSITION. */
/* Use DEF_ASSN_OPERATOR to define an assignment operator. Its
arguments are as for DEF_OPERATOR, but there is no need to provide
- an ASSIGNMENT_P argument; it is always one. */
+ FLAGS (OVL_OP_FLAG_BINARY). */
-#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, FLAGS) \
- DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_assign_op)
+#ifndef DEF_ASSN_OPERATOR
+#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING) \
+ DEF_OPERATOR(NAME, CODE, MANGLING, OVL_OP_FLAG_BINARY)
+#endif
-/* Memory allocation operators. */
-DEF_OPERATOR ("new", NEW_EXPR, "nw", OVL_OP_FLAG_ALLOC, cik_newdel_op)
+/* Memory allocation operators. ARITY has special meaning. */
+DEF_OPERATOR ("new", NEW_EXPR, "nw", OVL_OP_FLAG_ALLOC)
DEF_OPERATOR ("new []", VEC_NEW_EXPR, "na",
- OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC, cik_newdel_op)
+ OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC)
DEF_OPERATOR ("delete", DELETE_EXPR, "dl",
- OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE, cik_newdel_op)
+ OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)
DEF_OPERATOR ("delete []", VEC_DELETE_EXPR, "da",
- OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC,
- cik_newdel_op)
+ OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC)
/* Unary operators. */
-DEF_SIMPLE_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("-", NEGATE_EXPR, "ng", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("&", ADDR_EXPR, "ad", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("*", INDIRECT_REF, "de", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("~", BIT_NOT_EXPR, "co", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("++", PREINCREMENT_EXPR, "pp", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("--", PREDECREMENT_EXPR, "mm", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("->", COMPONENT_REF, "pt", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", OVL_OP_FLAG_UNARY)
+
/* These are extensions. */
-DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("alignof", ALIGNOF_EXPR, "az", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", OVL_OP_FLAG_UNARY)
/* Binary operators. */
-DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("+", PLUS_EXPR, "pl", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("-", MINUS_EXPR, "mi", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("*", MULT_EXPR, "ml", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("&", BIT_AND_EXPR, "an", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("|", BIT_IOR_EXPR, "or", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("^", BIT_XOR_EXPR, "eo", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("<<", LSHIFT_EXPR, "ls", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR (">>", RSHIFT_EXPR, "rs", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("==", EQ_EXPR, "eq", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("!=", NE_EXPR, "ne", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("<", LT_EXPR, "lt", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR (">", GT_EXPR, "gt", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("<=", LE_EXPR, "le", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR (">=", GE_EXPR, "ge", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR (",", COMPOUND_EXPR, "cm", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("->*", MEMBER_REF, "pm", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR (".*", DOTSTAR_EXPR, "ds", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("[]", ARRAY_REF, "ix", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", OVL_OP_FLAG_BINARY)
+DEF_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", OVL_OP_FLAG_BINARY)
/* Miscellaneous. */
-DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE)
+DEF_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE)
+DEF_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE)
/* Operators needed for mangling. */
-DEF_SIMPLE_OPERATOR (NULL, CAST_EXPR, "cv", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, CONST_CAST_EXPR, "cc", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, SCOPE_REF, "sr", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR (NULL, BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE)
+DEF_OPERATOR (NULL, CAST_EXPR, "cv", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR (NULL, DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR (NULL, REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR (NULL, CONST_CAST_EXPR, "cc", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR (NULL, STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_UNARY)
+DEF_OPERATOR (NULL, SCOPE_REF, "sr", OVL_OP_FLAG_NONE)
+DEF_OPERATOR (NULL, EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_NONE)
+DEF_OPERATOR (NULL, UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_NONE)
+DEF_OPERATOR (NULL, UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_NONE)
+DEF_OPERATOR (NULL, BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE)
+DEF_OPERATOR (NULL, BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE)
+
+#ifdef OPERATOR_TRANSITION
+OPERATOR_TRANSITION
+#undef OPERATOR_TRANSITION
+#endif
/* Assignment operators. */
-DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", OVL_OP_FLAG_BINARY)
-DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", OVL_OP_FLAG_BINARY)
-
+DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS")
+DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL")
+DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI")
+DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL")
+DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV")
+DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM")
+DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN")
+DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR")
+DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO")
+DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS")
+DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS")
+
+#undef DEF_ASSN_OPERATOR
+#undef DEF_OPERATOR