public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] overloaded operator fns [1/N]
@ 2017-10-31 13:12 Nathan Sidwell
  2017-10-31 14:45 ` [C++ PATCH] overloaded operator fns [2/N] Nathan Sidwell
  0 siblings, 1 reply; 10+ messages in thread
From: Nathan Sidwell @ 2017-10-31 13:12 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 767 bytes --]

This patch breaks DECL_OVERLOADED_OPERATOR_P apart into a predicate (as 
its name suggests) and DECL_OVERLOADED_OPERATOR_CODE, an accessor. I 
also add DECL_OVERLOADED_OPERATOR_IS, whose current implementation is a 
stepping stone to more a compressed operator enumeration.  Also add 
assign_op_identifier and call_op_identifier, which we use reasonably 
commonly.

I also notice that we're marking a lambda's conversion operator as an 
overloaded TYPE_EXPR.  That's weird and unnecessary, so this marks it 
simply as a conversion operator.

We're a little inconsistent in whether we check those two overloads by 
looking for identifier equivalence or examining the operator code 
enumeration.  I've not addressed that.

Applying to trunk.

nathan
-- 
Nathan Sidwell

[-- Attachment #2: op_idents.diff --]
[-- Type: text/x-patch, Size: 23487 bytes --]

2017-10-31  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (assign_op_identifier, call_op_identifier): Define.
	(LAMBDA_FUNCTION_P): Use DECL_OVERLOADED_OPERATOR_IS.
	(DECL_OVERLOADED_OPERATOR_P): Just retuurn true/false.
	(DECL_OVERLOADED_OPERATOR_CODE, DECL_OVERLOADED_OPERATOR_IS): Define.
	* call.c (add_function_candidate): Use
	DECL_OVERLOADED_OPERATOR_IS.
	(build_op_call_1): Use call_op_identifier &
	DECL_OVERLOADED_OPERATOR_IS.
	(build_over_call): Likewise.
	(has_trivial_copy_assign_p): Use assign_op_identifier.
	(build_special_member_call): Likewise.
	* class.c (dfs_declare_virt_assop_and_dtor): Likewise.
	(vbase_has_user_provided_move_assign,
	classtype_has_move_assign_or_move_ctor_p): Likewise.
	* decl.c (duplicate_decls): Use DECL_OVERLOADED_OPERATOR_CODE.
	(grok_special_member_properties): Use assign_op_identifier.
	(start_preparsed_function): Use DECL_OVERLOADED_OPERATOR_IS.
	* decl2.c (mark_used): Use DECL_CONV_FN_P.
	* dump.c (dump_access): Delete prototype.
	(dump_op): Delete.
	(cp_dump_tree): Don't call it.
	* lambda.c (lambda_function): Use call_op_identifier.
	(maybe_add_lambda_conv_op): Not an overloaded operator.  Remove
	unneeded braces.
	* mangle.c (write_unqualified_name): Use DECL_OVERLOADED_OPERTOR_CODE.
	* method.c (do_build_copy_assign): Use assign_op_identifier.
	(synthesize_method): Use DECL_OVERLOADED_OPERATOR_IS.
	(get_copy_assign): Use assign_op_identifier.
	(synthesized_method_walk): Likewise.
	(defaultable_fn_check): Use DECL_OVERLOADED_OPERATOR_IS.
	* parser.c (cp_parser_lambda_declarator_opt): Use
	call_op_identifier.
	* semanitics.c (classtype_has_nothrow_assign_or_copy_p): Use
	assign_op_identifier.
	* tree.c (special_function_p):  Use DECL_OVERLOADED_OPERATOR_IS.
	* typeck.c (check_return_expr): Use DECL_OVERLOADED_OPERATOR_CODE.
	(check_return_expr): Use assign_op_identifier.

Index: call.c
===================================================================
--- call.c	(revision 254243)
+++ call.c	(working copy)
@@ -2082,7 +2082,7 @@ add_function_candidate (struct z_candida
       if (DECL_CONSTRUCTOR_P (fn))
 	i = 1;
       else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
-	       && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
+	       && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR))
 	i = 2;
       else
 	i = 0;
@@ -4474,7 +4474,7 @@ build_op_call_1 (tree obj, vec<tree, va_
 
   if (TYPE_BINFO (type))
     {
-      fns = lookup_fnfields (TYPE_BINFO (type), cp_operator_id (CALL_EXPR), 1);
+      fns = lookup_fnfields (TYPE_BINFO (type), call_op_identifier, 1);
       if (fns == error_mark_node)
 	return error_mark_node;
     }
@@ -4557,11 +4557,9 @@ build_op_call_1 (tree obj, vec<tree, va_
             }
 	  result = error_mark_node;
 	}
-      /* Since cand->fn will be a type, not a function, for a conversion
-	 function, we must be careful not to unconditionally look at
-	 DECL_NAME here.  */
       else if (TREE_CODE (cand->fn) == FUNCTION_DECL
-	       && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
+	       && DECL_OVERLOADED_OPERATOR_P (cand->fn)
+	       && DECL_OVERLOADED_OPERATOR_IS (cand->fn, CALL_EXPR))
 	result = build_over_call (cand, LOOKUP_NORMAL, complain);
       else
 	{
@@ -8116,7 +8114,8 @@ build_over_call (struct z_candidate *can
 	  return val;
 	}
     }
-  else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
+  else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
+	   && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR)
 	   && trivial_fn_p (fn)
 	   && !DECL_DELETED_FN (fn))
     {
@@ -8284,7 +8283,7 @@ first_non_public_field (tree type)
 static bool
 has_trivial_copy_assign_p (tree type, bool access, bool *hasassign)
 {
-  tree fns = get_class_binding (type, cp_assignment_operator_id (NOP_EXPR));
+  tree fns = get_class_binding (type, assign_op_identifier);
   bool all_trivial = true;
 
   /* Iterate over overloads of the assignment operator, checking
@@ -8784,8 +8783,7 @@ build_special_member_call (tree instance
   vec<tree, va_gc> *allocated = NULL;
   tree ret;
 
-  gcc_assert (IDENTIFIER_CDTOR_P (name)
-	      || name == cp_assignment_operator_id (NOP_EXPR));
+  gcc_assert (IDENTIFIER_CDTOR_P (name) || name == assign_op_identifier);
   if (TYPE_P (binfo))
     {
       /* Resolve the name.  */
@@ -8811,7 +8809,7 @@ build_special_member_call (tree instance
       if (!same_type_ignoring_top_level_qualifiers_p
 	  (TREE_TYPE (instance), BINFO_TYPE (binfo)))
 	{
-	  if (name != cp_assignment_operator_id (NOP_EXPR))
+	  if (IDENTIFIER_CDTOR_P (name))
 	    /* For constructors and destructors, either the base is
 	       non-virtual, or it is virtual but we are doing the
 	       conversion from a constructor or destructor for the
@@ -8819,10 +8817,13 @@ build_special_member_call (tree instance
 	       statically.  */
 	    instance = convert_to_base_statically (instance, binfo);
 	  else
-	    /* However, for assignment operators, we must convert
-	       dynamically if the base is virtual.  */
-	    instance = build_base_path (PLUS_EXPR, instance,
-					binfo, /*nonnull=*/1, complain);
+	    {
+	      /* However, for assignment operators, we must convert
+		 dynamically if the base is virtual.  */
+	      gcc_checking_assert (name == assign_op_identifier);
+	      instance = build_base_path (PLUS_EXPR, instance,
+					  binfo, /*nonnull=*/1, complain);
+	    }
 	}
     }
 
Index: class.c
===================================================================
--- class.c	(revision 254243)
+++ class.c	(working copy)
@@ -3011,7 +3011,7 @@ static tree
 dfs_declare_virt_assop_and_dtor (tree binfo, void *data)
 {
   tree bv, fn, t = (tree)data;
-  tree opname = cp_assignment_operator_id (NOP_EXPR);
+  tree opname = assign_op_identifier;
 
   gcc_assert (t && CLASS_TYPE_P (t));
   gcc_assert (binfo && TREE_CODE (binfo) == TREE_BINFO);
@@ -5038,7 +5038,7 @@ vbase_has_user_provided_move_assign (tre
   /* Does the type itself have a user-provided move assignment operator?  */
   if (!CLASSTYPE_LAZY_MOVE_ASSIGN (type))
     for (ovl_iterator iter (get_class_binding_direct
-			    (type, cp_assignment_operator_id (NOP_EXPR)));
+			    (type, assign_op_identifier));
 	 iter; ++iter)
       if (!DECL_ARTIFICIAL (*iter) && move_fn_p (*iter))
 	return true;
@@ -5186,7 +5186,7 @@ classtype_has_move_assign_or_move_ctor_p
 
   if (!CLASSTYPE_LAZY_MOVE_ASSIGN (t))
     for (ovl_iterator iter (get_class_binding_direct
-			    (t, cp_assignment_operator_id (NOP_EXPR)));
+			    (t, assign_op_identifier));
 	 iter; ++iter)
       if ((!user_p || !DECL_ARTIFICIAL (*iter)) && move_fn_p (*iter))
 	return true;
Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 254243)
+++ cp-tree.h	(working copy)
@@ -217,7 +217,7 @@ extern GTY(()) tree cp_global_trees[CPTI
    things) to iterate over their overloads defined by/for a type.  For
    example:
 
-     tree ovlid = cp_assignment_operator_id (NOP_EXPR);
+     tree ovlid = assign_op_identifier;
      tree overloads = get_class_binding (type, ovlid);
      for (ovl_iterator it (overloads); it; ++it) { ... }
 
@@ -244,6 +244,9 @@ extern GTY(()) tree cp_global_trees[CPTI
 /* The name of a destructor that destroys virtual base classes, and
    then deletes the entire object.  */
 #define deleting_dtor_identifier	cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER]
+
+#define assign_op_identifier (cp_assignment_operator_id (NOP_EXPR))
+#define call_op_identifier (cp_operator_id (CALL_EXPR))
 /* The name used for conversion operators -- but note that actual
    conversion functions use special identifiers outside the identifier
    table.  */
@@ -1203,9 +1206,10 @@ struct GTY (()) tree_trait_expr {
   (CLASS_TYPE_P (NODE) && CLASSTYPE_LAMBDA_EXPR (NODE))
 
 /* Test if FUNCTION_DECL is a lambda function.  */
-#define LAMBDA_FUNCTION_P(FNDECL)			\
-  (DECL_DECLARES_FUNCTION_P (FNDECL)			\
-   && DECL_OVERLOADED_OPERATOR_P (FNDECL) == CALL_EXPR	\
+#define LAMBDA_FUNCTION_P(FNDECL)				\
+  (DECL_DECLARES_FUNCTION_P (FNDECL)				\
+   && DECL_OVERLOADED_OPERATOR_P (FNDECL)			\
+   && DECL_OVERLOADED_OPERATOR_IS (FNDECL, CALL_EXPR)		\
    && LAMBDA_TYPE_P (CP_DECL_CONTEXT (FNDECL)))
 
 enum cp_lambda_default_capture_mode_type {
@@ -2810,19 +2814,24 @@ struct GTY(()) lang_decl {
 #define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
   (LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE))
 
-/* If NODE is an overloaded operator, then this returns the TREE_CODE
-   associated with the overloaded operator.  If NODE is not an
-   overloaded operator, ERROR_MARK is returned.  Since the numerical
-   value of ERROR_MARK is zero, this macro can be used as a predicate
-   to test whether or not NODE is an overloaded operator.  */
+/* True iff decl NODE is for an overloaded operator.  */
 #define DECL_OVERLOADED_OPERATOR_P(NODE)		\
-  (IDENTIFIER_ANY_OP_P (DECL_NAME (NODE))		\
-   ? LANG_DECL_FN_CHECK (NODE)->operator_code : ERROR_MARK)
+  IDENTIFIER_ANY_OP_P (DECL_NAME (NODE))
 
 /* Nonzero if NODE is an assignment operator (including += and such).  */
-#define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
+#define DECL_ASSIGNMENT_OPERATOR_P(NODE)		 \
   IDENTIFIER_ASSIGN_OP_P (DECL_NAME (NODE))
 
+/* NODE is a function_decl for an overloaded operator.  Return its
+   operator code.   */
+#define DECL_OVERLOADED_OPERATOR_CODE(NODE)			\
+  (LANG_DECL_FN_CHECK (NODE)->operator_code)
+
+/* DECL is an overloaded operator.  Test whether it is for TREE_CODE
+   (a literal constant).  */
+#define DECL_OVERLOADED_OPERATOR_IS(DECL, CODE)			\
+  (DECL_OVERLOADED_OPERATOR_CODE (DECL) == CODE)
+
 /* For FUNCTION_DECLs: nonzero means that this function is a
    constructor or a destructor with an extra in-charge parameter to
    control whether or not virtual bases are constructed.  */
Index: decl.c
===================================================================
--- decl.c	(revision 254243)
+++ decl.c	(working copy)
@@ -1921,9 +1921,9 @@ next_arg:;
       DECL_FINAL_P (newdecl) |= DECL_FINAL_P (olddecl);
       DECL_OVERRIDE_P (newdecl) |= DECL_OVERRIDE_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
-      if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
+      if (DECL_OVERLOADED_OPERATOR_P (olddecl))
 	SET_OVERLOADED_OPERATOR_CODE
-	  (newdecl, DECL_OVERLOADED_OPERATOR_P (olddecl));
+	  (newdecl, DECL_OVERLOADED_OPERATOR_CODE (olddecl));
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
       /* Optionally warn about more than one declaration for the same
@@ -12816,7 +12816,7 @@ grok_special_member_properties (tree dec
 	  && !ctor && !move_fn_p (decl))
 	TYPE_HAS_CONSTEXPR_CTOR (class_type) = 1;
     }
-  else if (DECL_NAME (decl) == cp_assignment_operator_id (NOP_EXPR))
+  else if (DECL_NAME (decl) == assign_op_identifier)
     {
       /* [class.copy]
 
@@ -14769,9 +14769,11 @@ start_preparsed_function (tree decl1, tr
 
   /* Effective C++ rule 15.  */
   if (warn_ecpp
-      && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
+      && DECL_ASSIGNMENT_OPERATOR_P (decl1)
+      && DECL_OVERLOADED_OPERATOR_IS (decl1, NOP_EXPR)
       && VOID_TYPE_P (TREE_TYPE (fntype)))
-    warning (OPT_Weffc__, "%<operator=%> should return a reference to %<*this%>");
+    warning (OPT_Weffc__,
+	     "%<operator=%> should return a reference to %<*this%>");
 
   /* Make the init_value nonzero so pushdecl knows this is not tentative.
      error_mark_node is replaced below (in poplevel) with the BLOCK.  */
Index: decl2.c
===================================================================
--- decl2.c	(revision 254243)
+++ decl2.c	(working copy)
@@ -5101,11 +5101,11 @@ mark_used (tree decl, tsubst_flags_t com
       && DECL_DELETED_FN (decl))
     {
       if (DECL_ARTIFICIAL (decl)
-	  && DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR
+	  && DECL_CONV_FN_P (decl)
 	  && LAMBDA_TYPE_P (DECL_CONTEXT (decl)))
 	/* We mark a lambda conversion op as deleted if we can't
 	   generate it properly; see maybe_add_lambda_conv_op.  */
-	sorry ("converting lambda which uses %<...%> to function pointer");
+	sorry ("converting lambda that uses %<...%> to function pointer");
       else if (complain & tf_error)
 	{
 	  error ("use of deleted function %qD", decl);
Index: dump.c
===================================================================
--- dump.c	(revision 254243)
+++ dump.c	(working copy)
@@ -24,10 +24,6 @@ along with GCC; see the file COPYING3.
 #include "cp-tree.h"
 #include "tree-dump.h"
 
-static void dump_access (dump_info_p, tree);
-
-static void dump_op (dump_info_p, tree);
-
 /* Dump a representation of the accessibility information associated
    with T.  */
 
@@ -42,163 +38,6 @@ dump_access (dump_info_p di, tree t)
     dump_string_field (di, "accs", "pub");
 }
 
-/* Dump a representation of the specific operator for an overloaded
-   operator associated with node t.  */
-
-static void
-dump_op (dump_info_p di, tree t)
-{
-  switch (DECL_OVERLOADED_OPERATOR_P (t)) {
-    case NEW_EXPR:
-      dump_string (di, "new");
-      break;
-    case VEC_NEW_EXPR:
-      dump_string (di, "vecnew");
-      break;
-    case DELETE_EXPR:
-      dump_string (di, "delete");
-      break;
-    case VEC_DELETE_EXPR:
-      dump_string (di, "vecdelete");
-      break;
-    case UNARY_PLUS_EXPR:
-      dump_string (di, "pos");
-      break;
-    case NEGATE_EXPR:
-      dump_string (di, "neg");
-      break;
-    case ADDR_EXPR:
-      dump_string (di, "addr");
-      break;
-    case INDIRECT_REF:
-      dump_string(di, "deref");
-      break;
-    case BIT_NOT_EXPR:
-      dump_string(di, "not");
-      break;
-    case TRUTH_NOT_EXPR:
-      dump_string(di, "lnot");
-      break;
-    case PREINCREMENT_EXPR:
-      dump_string(di, "preinc");
-      break;
-    case PREDECREMENT_EXPR:
-      dump_string(di, "predec");
-      break;
-    case PLUS_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "plusassign");
-      else
-	dump_string(di, "plus");
-      break;
-    case MINUS_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "minusassign");
-      else
-	dump_string(di, "minus");
-      break;
-    case MULT_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "multassign");
-      else
-	dump_string (di, "mult");
-      break;
-    case TRUNC_DIV_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "divassign");
-      else
-	dump_string (di, "div");
-      break;
-    case TRUNC_MOD_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	 dump_string (di, "modassign");
-      else
-	dump_string (di, "mod");
-      break;
-    case BIT_AND_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "andassign");
-      else
-	dump_string (di, "and");
-      break;
-    case BIT_IOR_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "orassign");
-      else
-	dump_string (di, "or");
-      break;
-    case BIT_XOR_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "xorassign");
-      else
-	dump_string (di, "xor");
-      break;
-    case LSHIFT_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "lshiftassign");
-      else
-	dump_string (di, "lshift");
-      break;
-    case RSHIFT_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "rshiftassign");
-      else
-	dump_string (di, "rshift");
-      break;
-    case EQ_EXPR:
-      dump_string (di, "eq");
-      break;
-    case NE_EXPR:
-      dump_string (di, "ne");
-      break;
-    case LT_EXPR:
-      dump_string (di, "lt");
-      break;
-    case GT_EXPR:
-      dump_string (di, "gt");
-      break;
-    case LE_EXPR:
-      dump_string (di, "le");
-      break;
-    case GE_EXPR:
-      dump_string (di, "ge");
-      break;
-    case TRUTH_ANDIF_EXPR:
-      dump_string (di, "land");
-      break;
-    case TRUTH_ORIF_EXPR:
-      dump_string (di, "lor");
-      break;
-    case COMPOUND_EXPR:
-      dump_string (di, "compound");
-      break;
-    case MEMBER_REF:
-      dump_string (di, "memref");
-      break;
-    case COMPONENT_REF:
-      dump_string (di, "ref");
-      break;
-    case ARRAY_REF:
-      dump_string (di, "subs");
-      break;
-    case POSTINCREMENT_EXPR:
-      dump_string (di, "postinc");
-      break;
-    case POSTDECREMENT_EXPR:
-      dump_string (di, "postdec");
-      break;
-    case CALL_EXPR:
-      dump_string (di, "call");
-      break;
-    case NOP_EXPR:
-      if (DECL_ASSIGNMENT_OPERATOR_P (t))
-	dump_string (di, "assign");
-      break;
-    default:
-      break;
-  }
-}
-
 /* Dump information common to statements from STMT.  */
 
 static void
@@ -303,10 +142,8 @@ cp_dump_tree (void* dump_info, tree t)
     case FUNCTION_DECL:
       if (!DECL_THUNK_P (t))
 	{
-	  if (DECL_OVERLOADED_OPERATOR_P (t)) {
+	  if (DECL_OVERLOADED_OPERATOR_P (t))
 	    dump_string_field (di, "note", "operator");
-	    dump_op (di, t);
-	  }
 	  if (DECL_FUNCTION_MEMBER_P (t))
 	    {
 	      dump_string_field (di, "note", "member");
Index: lambda.c
===================================================================
--- lambda.c	(revision 254243)
+++ lambda.c	(working copy)
@@ -201,7 +201,7 @@ lambda_function (tree lambda)
   if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
       && !COMPLETE_OR_OPEN_TYPE_P (type))
     return NULL_TREE;
-  lambda = lookup_member (type, cp_operator_id (CALL_EXPR),
+  lambda = lookup_member (type, call_op_identifier,
 			  /*protect=*/0, /*want_type=*/false,
 			  tf_warning_or_error);
   if (lambda)
@@ -1258,7 +1258,6 @@ maybe_add_lambda_conv_op (tree type)
   tree fn = convfn;
   DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
   SET_DECL_ALIGN (fn, MINIMUM_METHOD_BOUNDARY);
-  SET_OVERLOADED_OPERATOR_CODE (fn, TYPE_EXPR);
   grokclassfn (type, fn, NO_SPECIAL);
   set_linkage_according_to_type (type, fn);
   rest_of_decl_compilation (fn, namespace_bindings_p (), at_eof);
@@ -1312,11 +1311,9 @@ maybe_add_lambda_conv_op (tree type)
     fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
 
   if (flag_sanitize & SANITIZE_NULL)
-    {
-      /* Don't UBsan this function; we're deliberately calling op() with a null
-	 object argument.  */
-      add_no_sanitize_value (fn, SANITIZE_UNDEFINED);
-    }
+    /* Don't UBsan this function; we're deliberately calling op() with a null
+       object argument.  */
+    add_no_sanitize_value (fn, SANITIZE_UNDEFINED);
 
   add_method (type, fn, false);
 
Index: mangle.c
===================================================================
--- mangle.c	(revision 254243)
+++ mangle.c	(working copy)
@@ -1351,7 +1351,7 @@ write_unqualified_name (tree decl)
 	  else
 	    oni = operator_name_info;
 
-	  write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name);
+	  write_string (oni[DECL_OVERLOADED_OPERATOR_CODE (decl)].mangled_name);
 	}
       else if (UDLIT_OPER_P (DECL_NAME (decl)))
 	write_literal_operator_name (DECL_NAME (decl));
Index: method.c
===================================================================
--- method.c	(revision 254243)
+++ method.c	(working copy)
@@ -815,7 +815,7 @@ do_build_copy_assign (tree fndecl)
 	  parmvec = make_tree_vector_single (converted_parm);
 	  finish_expr_stmt
 	    (build_special_member_call (current_class_ref,
-					cp_assignment_operator_id (NOP_EXPR),
+					assign_op_identifier,
 					&parmvec,
 					base_binfo,
 					flags,
@@ -929,7 +929,8 @@ synthesize_method (tree fndecl)
   start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
   stmt = begin_function_body ();
 
-  if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
+  if (DECL_ASSIGNMENT_OPERATOR_P (fndecl)
+      && DECL_OVERLOADED_OPERATOR_IS (fndecl, NOP_EXPR))
     {
       do_build_copy_assign (fndecl);
       need_body = false;
@@ -1108,7 +1109,7 @@ get_copy_assign (tree type)
   int quals = (TYPE_HAS_CONST_COPY_ASSIGN (type)
 	       ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED);
   tree argtype = build_stub_type (type, quals, false);
-  tree fn = locate_fn_flags (type, cp_assignment_operator_id (NOP_EXPR), argtype,
+  tree fn = locate_fn_flags (type, assign_op_identifier, argtype,
 			     LOOKUP_NORMAL, tf_warning_or_error);
   if (fn == error_mark_node)
     return NULL_TREE;
@@ -1565,7 +1566,7 @@ synthesized_method_walk (tree ctype, spe
     case sfk_move_assignment:
     case sfk_copy_assignment:
       assign_p = true;
-      fnname = cp_assignment_operator_id (NOP_EXPR);
+      fnname = assign_op_identifier;
       break;
 
     case sfk_destructor:
@@ -2318,7 +2319,7 @@ defaultable_fn_check (tree fn)
   else if (DECL_DESTRUCTOR_P (fn))
     kind = sfk_destructor;
   else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
-	   && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
+	   && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR))
     {
       if (copy_fn_p (fn))
 	kind = sfk_copy_assignment;
Index: parser.c
===================================================================
--- parser.c	(revision 254243)
+++ parser.c	(working copy)
@@ -10614,8 +10614,7 @@ cp_parser_lambda_declarator_opt (cp_pars
 
     p = obstack_alloc (&declarator_obstack, 0);
 
-    declarator = make_id_declarator (NULL_TREE, cp_operator_id (CALL_EXPR),
-				     sfk_none);
+    declarator = make_id_declarator (NULL_TREE, call_op_identifier, sfk_none);
 
     quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
 	     ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
Index: semantics.c
===================================================================
--- semantics.c	(revision 254243)
+++ semantics.c	(working copy)
@@ -9020,8 +9020,7 @@ classtype_has_nothrow_assign_or_copy_p (
   tree fns = NULL_TREE;
 
   if (assign_p || TYPE_HAS_COPY_CTOR (type))
-    fns = get_class_binding (type,
-			     assign_p ? cp_assignment_operator_id (NOP_EXPR)
+    fns = get_class_binding (type, assign_p ? assign_op_identifier
 			     : ctor_identifier);
 
   bool saw_copy = false;
Index: tree.c
===================================================================
--- tree.c	(revision 254243)
+++ tree.c	(working copy)
@@ -4847,7 +4847,8 @@ special_function_p (const_tree decl)
     return sfk_move_constructor;
   if (DECL_CONSTRUCTOR_P (decl))
     return sfk_constructor;
-  if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
+  if (DECL_ASSIGNMENT_OPERATOR_P (decl)
+      && DECL_OVERLOADED_OPERATOR_IS (decl, NOP_EXPR))
     {
       if (copy_fn_p (decl))
 	return sfk_copy_assignment;
Index: typeck.c
===================================================================
--- typeck.c	(revision 254243)
+++ typeck.c	(working copy)
@@ -9073,8 +9073,10 @@ check_return_expr (tree retval, bool *no
     }
 
   /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
-  if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
-       || DECL_OVERLOADED_OPERATOR_P (current_function_decl) == VEC_NEW_EXPR)
+  if (DECL_OVERLOADED_OPERATOR_P (current_function_decl)
+      && (DECL_OVERLOADED_OPERATOR_CODE (current_function_decl) == NEW_EXPR
+	  || (DECL_OVERLOADED_OPERATOR_CODE (current_function_decl)
+	      == VEC_NEW_EXPR))
       && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
       && ! flag_check_new
       && retval && null_ptr_cst_p (retval))
@@ -9083,7 +9085,7 @@ check_return_expr (tree retval, bool *no
 
   /* Effective C++ rule 15.  See also start_function.  */
   if (warn_ecpp
-      && DECL_NAME (current_function_decl) == cp_assignment_operator_id (NOP_EXPR))
+      && DECL_NAME (current_function_decl) == assign_op_identifier)
     {
       bool warn = true;
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [C++ PATCH] overloaded operator fns [2/N]
  2017-10-31 13:12 [C++ PATCH] overloaded operator fns [1/N] Nathan Sidwell
@ 2017-10-31 14:45 ` Nathan Sidwell
  2017-10-31 16:30   ` [C++ PATCH] overloaded operator fns [3/N] Nathan Sidwell
  0 siblings, 1 reply; 10+ messages in thread
From: Nathan Sidwell @ 2017-10-31 14:45 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 355 bytes --]

This patch removes cp_operator_id(C) and cp_assignment_operator_id(C), 
replacing them with a singlle ovl_op_identifier(A,C) macro.  There's 
also OVL_OP_INFO(A,C) to get at the other information.  The 
implementation of that macro will change later in this patch series, so 
don't freak on the (A ? assop_ary : op_ary) idiom.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-ident-2.diff --]
[-- Type: text/x-patch, Size: 24552 bytes --]

2017-10-31  Nathan Sidwell  <nathan@acm.org>

	gcc/cp/
	* cp-tree.h (ovl_op_identifier): New.
	(assign_op_identifier, call_op_identifier): Adjust.
	(cp_operator_id, cp_assignment_operator_ide): Delete.
	(SET_OVERLOADED_OPERATOR_CODE): Delete.
	(OVL_OP_INFO): New.
	* call.c (op_error): Use OVL_OP_INFO.
	(build_conditional_expr_1): Use ovl_op_identifier.
	(build_new_op_1): Use OVL_OP_INFO & ovl_op_identifier.
	(build_op_delete_call): Likewise.
	* class.c (type_requires_array_cookie): Use ovl_op_identifier.
	* decl.c (duplicate_decls): Directly copy operator code.
	(builtin_function_1): Do not set operator code.
	(build_library_fn): Directly set operator code.
	(push_cp_library_fn): Use ovl_op_identifier.
	(grok_op_properties): Directly set operator code.
	* decl2.c (maybe_warn_sized_delete): Use ovl_op_identifier.
	* error.c (dump_expr): Use OVL_OP_INFO.
	(op_to_string): Add assop arg. Use OVL_OP_INFO.
	(assop_to_string): Delete.
	(args_to_string): Adjust.
	* init.c (build_new_1): Use ovl_op_identifier.
	* mangle.c (write_unqualified_name): Use OVL_OP_INFO.
	(write_expression): Likewise.
	* method.c (synthesized_method_walk): Use ovl_op_identifier.
	(implicitly_declare_fn): Use assign_op_identifier. Directly set
	operator code.
	* name-lookup.c (get_class_binding): Use assign_op_identifier.
	* parser.c (cp_parser_operator): Use ovl_op_identifier.
	(cp_parser_omp_clause_reduction): Likewise.
	* semantics.c (omp_reduction_id): Likewise.
	* typeck.c (cxx_sizeof_or_alignof_type): Use OVL_OP_INFO.

	libcc1/
	* libcp1plugin.cc (plugin_build_decl): Use ovl_op_identifier.
	Directly set operator code.
	(plugin_build_dependent_expr): Use ovl_op_identifier.

Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 254263)
+++ gcc/cp/call.c	(working copy)
@@ -4620,12 +4620,8 @@ static void
 op_error (location_t loc, enum tree_code code, enum tree_code code2,
 	  tree arg1, tree arg2, tree arg3, bool match)
 {
-  const char *opname;
-
-  if (code == MODIFY_EXPR)
-    opname = assignment_operator_name_info[code2].name;
-  else
-    opname = operator_name_info[code].name;
+  bool assop = code == MODIFY_EXPR;
+  const char *opname = OVL_OP_INFO (assop, assop ? code2 : code)->name;
 
   switch (code)
     {
@@ -5184,7 +5180,7 @@ build_conditional_expr_1 (location_t loc
       add_builtin_candidates (&candidates,
 			      COND_EXPR,
 			      NOP_EXPR,
-			      cp_operator_id (COND_EXPR),
+			      ovl_op_identifier (false, COND_EXPR),
 			      args,
 			      LOOKUP_NORMAL, complain);
 
@@ -5574,7 +5570,6 @@ build_new_op_1 (location_t loc, enum tre
 {
   struct z_candidate *candidates = 0, *cand;
   vec<tree, va_gc> *arglist;
-  tree fnname;
   tree args[3];
   tree result = NULL_TREE;
   bool result_valid_p = false;
@@ -5591,14 +5586,13 @@ build_new_op_1 (location_t loc, enum tre
       || error_operand_p (arg3))
     return error_mark_node;
 
-  if (code == MODIFY_EXPR)
+  bool ismodop = code == MODIFY_EXPR;
+  if (ismodop)
     {
       code2 = TREE_CODE (arg3);
       arg3 = NULL_TREE;
-      fnname = cp_assignment_operator_id (code2);
     }
-  else
-    fnname = cp_operator_id (code);
+  tree fnname = ovl_op_identifier (ismodop, ismodop ? code2 : code);
 
   arg1 = prep_operand (arg1);
 
@@ -5793,7 +5787,7 @@ build_new_op_1 (location_t loc, enum tre
 		? G_("no %<%D(int)%> declared for postfix %qs,"
 		     " trying prefix operator instead")
 		: G_("no %<%D(int)%> declared for postfix %qs");
-	      permerror (loc, msg, fnname, operator_name_info[code].name);
+	      permerror (loc, msg, fnname, OVL_OP_INFO (false, code)->name);
 	    }
 
 	  if (!flag_permissive)
@@ -6205,7 +6199,7 @@ build_op_delete_call (enum tree_code cod
 
   type = strip_array_types (TREE_TYPE (TREE_TYPE (addr)));
 
-  fnname = cp_operator_id (code);
+  fnname = ovl_op_identifier (false, code);
 
   if (CLASS_TYPE_P (type)
       && COMPLETE_TYPE_P (complete_type (type))
@@ -6434,7 +6428,7 @@ build_op_delete_call (enum tree_code cod
 
   if (complain & tf_error)
     error ("no suitable %<operator %s%> for %qT",
-	   operator_name_info[(int)code].name, type);
+	   OVL_OP_INFO (false, code)->name, type);
   return error_mark_node;
 }
 
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 254263)
+++ gcc/cp/class.c	(working copy)
@@ -5304,7 +5304,7 @@ type_requires_array_cookie (tree type)
      the array to the deallocation function, so we will need to store
      a cookie.  */
   fns = lookup_fnfields (TYPE_BINFO (type),
-			 cp_operator_id (VEC_DELETE_EXPR),
+			 ovl_op_identifier (false, VEC_DELETE_EXPR),
 			 /*protect=*/0);
   /* If there are no `operator []' members, or the lookup is
      ambiguous, then we don't need a cookie.  */
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 254263)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -245,24 +245,14 @@ extern GTY(()) tree cp_global_trees[CPTI
    then deletes the entire object.  */
 #define deleting_dtor_identifier	cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER]
 
-#define assign_op_identifier (cp_assignment_operator_id (NOP_EXPR))
-#define call_op_identifier (cp_operator_id (CALL_EXPR))
+#define ovl_op_identifier(ISASS, CODE)  (OVL_OP_INFO(ISASS, CODE)->identifier)
+#define assign_op_identifier (ovl_op_identifier (true, NOP_EXPR))
+#define call_op_identifier (ovl_op_identifier (false, CALL_EXPR))
 /* The name used for conversion operators -- but note that actual
    conversion functions use special identifiers outside the identifier
    table.  */
 #define conv_op_identifier		cp_global_trees[CPTI_CONV_OP_IDENTIFIER]
 
-/* The name of the identifier used internally to represent operator CODE.  */
-#define cp_operator_id(CODE) \
-  (operator_name_info[(int) (CODE)].identifier)
-
-/* The name of the identifier used to represent assignment operator CODE,
-   both simple (i.e., operator= with CODE == NOP_EXPR) and compound (e.g.,
-   operator+= with CODE == PLUS_EXPR).  Includes copy and move assignment.
-   Use copy_fn_p() to test specifically for copy assignment.  */
-#define cp_assignment_operator_id(CODE)				\
-  (assignment_operator_name_info[(int) (CODE)].identifier)
-
 #define delta_identifier		cp_global_trees[CPTI_DELTA_IDENTIFIER]
 #define in_charge_identifier		cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER]
 /* The name of the parameter that contains a pointer to the VTT to use
@@ -2810,10 +2800,6 @@ struct GTY(()) lang_decl {
 #define SET_VAR_HAD_UNKNOWN_BOUND(NODE) \
   (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.unknown_bound_p = true)
 
-/* Set the overloaded operator code for NODE to CODE.  */
-#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
-  (LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE))
-
 /* True iff decl NODE is for an overloaded operator.  */
 #define DECL_OVERLOADED_OPERATOR_P(NODE)		\
   IDENTIFIER_ANY_OP_P (DECL_NAME (NODE))
@@ -5506,6 +5492,12 @@ extern GTY(()) operator_name_info_t oper
 extern GTY(()) operator_name_info_t assignment_operator_name_info
   [(int) 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))
+
 /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL
    constants.  */
 
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 254263)
+++ gcc/cp/decl.c	(working copy)
@@ -1922,8 +1922,8 @@ next_arg:;
       DECL_OVERRIDE_P (newdecl) |= DECL_OVERRIDE_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
       if (DECL_OVERLOADED_OPERATOR_P (olddecl))
-	SET_OVERLOADED_OPERATOR_CODE
-	  (newdecl, DECL_OVERLOADED_OPERATOR_CODE (olddecl));
+	DECL_OVERLOADED_OPERATOR_CODE (newdecl)
+	  = DECL_OVERLOADED_OPERATOR_CODE (olddecl);
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
       /* Optionally warn about more than one declaration for the same
@@ -4359,7 +4359,6 @@ builtin_function_1 (tree decl, tree cont
   retrofit_lang_decl (decl);
 
   DECL_ARTIFICIAL (decl) = 1;
-  SET_OVERLOADED_OPERATOR_CODE (decl, ERROR_MARK);
   SET_DECL_LANGUAGE (decl, lang_c);
   /* Runtime library routines are, by definition, available in an
      external shared object.  */
@@ -4447,7 +4446,7 @@ build_library_fn (tree name, enum tree_c
   DECL_EXTERNAL (fn) = 1;
   TREE_PUBLIC (fn) = 1;
   DECL_ARTIFICIAL (fn) = 1;
-  SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
+  DECL_OVERLOADED_OPERATOR_CODE (fn) = operator_code;
   SET_DECL_LANGUAGE (fn, lang_c);
   /* Runtime library routines are, by definition, available in an
      external shared object.  */
@@ -4512,9 +4511,8 @@ static tree
 push_cp_library_fn (enum tree_code operator_code, tree type,
 		    int ecf_flags)
 {
-  tree fn = build_cp_library_fn (cp_operator_id (operator_code),
-				 operator_code,
-				 type, ecf_flags);
+  tree fn = build_cp_library_fn (ovl_op_identifier (false, operator_code),
+				 operator_code, type, ecf_flags);
   pushdecl (fn);
   if (flag_tm)
     apply_tm_attr (fn, get_identifier ("transaction_safe"));
@@ -12938,7 +12936,7 @@ grok_op_properties (tree decl, bool comp
       }
     while (0);
   gcc_assert (operator_code != MAX_TREE_CODES);
-  SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+  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)
@@ -13111,7 +13109,7 @@ grok_op_properties (tree decl, bool comp
 	      gcc_unreachable ();
 	    }
 
-	  SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+	  DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code;
 
 	  if ((operator_code == POSTINCREMENT_EXPR
 	       || operator_code == POSTDECREMENT_EXPR)
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 254263)
+++ gcc/cp/decl2.c	(working copy)
@@ -4455,7 +4455,7 @@ maybe_warn_sized_delete (enum tree_code
   tree sized = NULL_TREE;
   tree unsized = NULL_TREE;
 
-  for (ovl_iterator iter (get_global_binding (cp_operator_id (code)));
+  for (ovl_iterator iter (get_global_binding (ovl_op_identifier (false, code)));
        iter; ++iter)
     {
       tree fn = *iter;
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 254263)
+++ gcc/cp/error.c	(working copy)
@@ -50,13 +50,12 @@ static cxx_pretty_printer * const cxx_pp
 # define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T)))
 
 static const char *args_to_string (tree, int);
-static const char *assop_to_string (enum tree_code);
 static const char *code_to_string (enum tree_code);
 static const char *cv_to_string (tree, int);
 static const char *decl_to_string (tree, int);
 static const char *expr_to_string (tree);
 static const char *fndecl_to_string (tree, int);
-static const char *op_to_string	(enum tree_code);
+static const char *op_to_string	(bool, enum tree_code);
 static const char *parm_to_string (int);
 static const char *type_to_string (tree, int);
 
@@ -2230,8 +2229,7 @@ dump_expr (cxx_pretty_printer *pp, tree
 
     case INIT_EXPR:
     case MODIFY_EXPR:
-      dump_binary_op (pp, assignment_operator_name_info[NOP_EXPR].name,
-		      t, flags);
+      dump_binary_op (pp, OVL_OP_INFO (true, NOP_EXPR)->name, t, flags);
       break;
 
     case PLUS_EXPR:
@@ -2255,7 +2253,7 @@ dump_expr (cxx_pretty_printer *pp, tree
     case EQ_EXPR:
     case NE_EXPR:
     case EXACT_DIV_EXPR:
-      dump_binary_op (pp, operator_name_info[TREE_CODE (t)].name, t, flags);
+      dump_binary_op (pp, OVL_OP_INFO (false, TREE_CODE (t))->name, t, flags);
       break;
 
     case CEIL_DIV_EXPR:
@@ -2386,14 +2384,14 @@ dump_expr (cxx_pretty_printer *pp, tree
     case TRUTH_NOT_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      dump_unary_op (pp, operator_name_info [TREE_CODE (t)].name, t, flags);
+      dump_unary_op (pp, OVL_OP_INFO (false, TREE_CODE (t))->name, t, flags);
       break;
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
       pp_cxx_left_paren (pp);
       dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
-      pp_cxx_ws_string (pp, operator_name_info[TREE_CODE (t)].name);
+      pp_cxx_ws_string (pp, OVL_OP_INFO (false, TREE_CODE (t))->name);
       pp_cxx_right_paren (pp);
       break;
 
@@ -2656,7 +2654,7 @@ dump_expr (cxx_pretty_printer *pp, tree
 
     case REALPART_EXPR:
     case IMAGPART_EXPR:
-      pp_cxx_ws_string (pp, operator_name_info[TREE_CODE (t)].name);
+      pp_cxx_ws_string (pp, OVL_OP_INFO (false, TREE_CODE (t))->name);
       pp_cxx_whitespace (pp);
       dump_expr (pp, TREE_OPERAND (t, 0), flags);
       break;
@@ -3136,9 +3134,9 @@ parm_to_string (int p)
 }
 
 static const char *
-op_to_string (enum tree_code p)
+op_to_string (bool assop, enum tree_code p)
 {
-  tree id = operator_name_info[p].identifier;
+  tree id = ovl_op_identifier (assop, p);
   return id ? IDENTIFIER_POINTER (id) : M_("<unknown>");
 }
 
@@ -3180,13 +3178,6 @@ type_to_string (tree typ, int verbose)
 }
 
 static const char *
-assop_to_string (enum tree_code p)
-{
-  tree id = assignment_operator_name_info[(int) p].identifier;
-  return id ? IDENTIFIER_POINTER (id) : M_("{unknown}");
-}
-
-static const char *
 args_to_string (tree p, int verbose)
 {
   int flags = 0;
@@ -4044,9 +4035,9 @@ cp_printer (pretty_printer *pp, text_inf
     case 'E': result = expr_to_string (next_tree);		break;
     case 'F': result = fndecl_to_string (next_tree, verbose);	break;
     case 'L': result = language_to_string (next_lang);		break;
-    case 'O': result = op_to_string (next_tcode);		break;
+    case 'O': result = op_to_string (false, next_tcode);	break;
     case 'P': result = parm_to_string (next_int);		break;
-    case 'Q': result = assop_to_string (next_tcode);		break;
+    case 'Q': result = op_to_string (true, next_tcode);		break;
     case 'S': result = subst_to_string (next_tree);		break;
     case 'T': result = type_to_string (next_tree, verbose);	break;
     case 'V': result = cv_to_string (next_tree, verbose);	break;
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c	(revision 254263)
+++ gcc/cp/init.c	(working copy)
@@ -3055,7 +3055,7 @@ build_new_1 (vec<tree, va_gc> **placemen
   tree fnname;
   tree fns;
 
-  fnname = cp_operator_id (array_p ? VEC_NEW_EXPR : NEW_EXPR);
+  fnname = ovl_op_identifier (false, array_p ? VEC_NEW_EXPR : NEW_EXPR);
 
   member_new_p = !globally_qualified_p
 		 && CLASS_TYPE_P (elt_type)
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 254263)
+++ gcc/cp/mangle.c	(working copy)
@@ -1345,13 +1345,10 @@ write_unqualified_name (tree decl)
 	}
       else if (DECL_OVERLOADED_OPERATOR_P (decl))
 	{
-	  operator_name_info_t *oni;
-	  if (DECL_ASSIGNMENT_OPERATOR_P (decl))
-	    oni = assignment_operator_name_info;
-	  else
-	    oni = operator_name_info;
-
-	  write_string (oni[DECL_OVERLOADED_OPERATOR_CODE (decl)].mangled_name);
+	  const char *mangled_name
+	    = (OVL_OP_INFO (DECL_ASSIGNMENT_OPERATOR_P (decl),
+	       DECL_OVERLOADED_OPERATOR_CODE (decl))->mangled_name);
+	  write_string (mangled_name);
 	}
       else if (UDLIT_OPER_P (DECL_NAME (decl)))
 	write_literal_operator_name (DECL_NAME (decl));
@@ -3064,8 +3061,8 @@ write_expression (tree expr)
   else if (TREE_CODE (expr) == MODOP_EXPR)
     {
       enum tree_code subop = TREE_CODE (TREE_OPERAND (expr, 1));
-      const char *name = (assignment_operator_name_info[(int) subop]
-			  .mangled_name);
+      const char *name = OVL_OP_INFO (true, subop)->mangled_name;
+
       write_string (name);
       write_expression (TREE_OPERAND (expr, 0));
       write_expression (TREE_OPERAND (expr, 2));
@@ -3090,7 +3087,7 @@ write_expression (tree expr)
       if (NEW_EXPR_USE_GLOBAL (expr))
 	write_string ("gs");
 
-      write_string (operator_name_info[(int) code].mangled_name);
+      write_string (OVL_OP_INFO (false, code)->mangled_name);
 
       for (t = placement; t; t = TREE_CHAIN (t))
 	write_expression (TREE_VALUE (t));
@@ -3130,7 +3127,7 @@ write_expression (tree expr)
       if (DELETE_EXPR_USE_GLOBAL (expr))
 	write_string ("gs");
 
-      write_string (operator_name_info[(int) code].mangled_name);
+      write_string (OVL_OP_INFO (false, code)->mangled_name);
 
       write_expression (TREE_OPERAND (expr, 0));
     }
@@ -3195,7 +3192,7 @@ write_expression (tree expr)
 
 	  if (TREE_CODE (ob) == ARROW_EXPR)
 	    {
-	      write_string (operator_name_info[(int)code].mangled_name);
+	      write_string (OVL_OP_INFO (false, code)->mangled_name);
 	      ob = TREE_OPERAND (ob, 0);
 	      write_expression (ob);
 	    }
@@ -3212,7 +3209,7 @@ write_expression (tree expr)
 	}
 
       /* If it wasn't any of those, recursively expand the expression.  */
-      name = operator_name_info[(int) code].mangled_name;
+      name = OVL_OP_INFO (false, code)->mangled_name;
 
       /* We used to mangle const_cast and static_cast like a C cast.  */
       if (code == CONST_CAST_EXPR
@@ -3221,7 +3218,7 @@ write_expression (tree expr)
 	  if (abi_warn_or_compat_version_crosses (6))
 	    G.need_abi_warning = 1;
 	  if (!abi_version_at_least (6))
-	    name = operator_name_info[CAST_EXPR].mangled_name;
+	    name = OVL_OP_INFO (false, CAST_EXPR)->mangled_name;
 	}
 
       if (name == NULL)
@@ -3322,7 +3319,7 @@ write_expression (tree expr)
 		  if (i == 0)
 		    {
 		      int fcode = TREE_INT_CST_LOW (operand);
-		      write_string (operator_name_info[fcode].mangled_name);
+		      write_string (OVL_OP_INFO (false, fcode)->mangled_name);
 		      continue;
 		    }
 		  else if (code == BINARY_LEFT_FOLD_EXPR)
Index: gcc/cp/method.c
===================================================================
--- gcc/cp/method.c	(revision 254263)
+++ gcc/cp/method.c	(working copy)
@@ -1703,12 +1703,12 @@ synthesized_method_walk (tree ctype, spe
 	{
 	  /* Unlike for base ctor/op=/dtor, for operator delete it's fine
 	     to have a null fn (no class-specific op delete).  */
-	  fn = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR),
+	  fn = locate_fn_flags (ctype, ovl_op_identifier (false, DELETE_EXPR),
 				ptr_type_node, flags, tf_none);
 	  if (fn && fn == error_mark_node)
 	    {
 	      if (complain & tf_error)
-		locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR),
+		locate_fn_flags (ctype, ovl_op_identifier (false, DELETE_EXPR),
 				 ptr_type_node, flags, complain);
 	      if (deleted_p)
 		*deleted_p = true;
@@ -2008,7 +2008,7 @@ implicitly_declare_fn (special_function_
 	  || kind == sfk_move_assignment)
 	{
 	  return_type = build_reference_type (type);
-	  name = cp_assignment_operator_id (NOP_EXPR);
+	  name = assign_op_identifier;
 	}
       else
 	name = ctor_identifier;
@@ -2078,7 +2078,7 @@ implicitly_declare_fn (special_function_
 
   if (!IDENTIFIER_CDTOR_P (name))
     /* Assignment operator.  */
-    SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
+    DECL_OVERLOADED_OPERATOR_CODE (fn) = NOP_EXPR;
   else if (IDENTIFIER_CTOR_P (name))
     DECL_CXX_CONSTRUCTOR_P (fn) = true;
   else
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c	(revision 254263)
+++ gcc/cp/name-lookup.c	(working copy)
@@ -1299,7 +1299,7 @@ get_class_binding (tree klass, tree name
 	  if (CLASSTYPE_LAZY_DESTRUCTOR (klass))
 	    lazily_declare_fn (sfk_destructor, klass);
 	}
-      else if (name == cp_assignment_operator_id (NOP_EXPR))
+      else if (name == assign_op_identifier)
 	{
 	  if (CLASSTYPE_LAZY_COPY_ASSIGN (klass))
 	    lazily_declare_fn (sfk_copy_assignment, klass);
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 254263)
+++ gcc/cp/parser.c	(working copy)
@@ -15006,7 +15006,7 @@ cp_parser_operator (cp_parser* parser)
      operator token.  */
   if (op != ERROR_MARK)
     {
-      id = assop ? cp_assignment_operator_id (op) : cp_operator_id (op);
+      id = ovl_op_identifier (assop, op);
       if (!consumed)
 	cp_lexer_consume_token (parser->lexer);
     }
@@ -32588,21 +32588,21 @@ cp_parser_omp_clause_reduction (cp_parse
 	    code = MIN_EXPR;
 	  else if (strcmp (p, "max") == 0)
 	    code = MAX_EXPR;
-	  else if (id == cp_operator_id (PLUS_EXPR))
+	  else if (id == ovl_op_identifier (false, PLUS_EXPR))
 	    code = PLUS_EXPR;
-	  else if (id == cp_operator_id (MULT_EXPR))
+	  else if (id == ovl_op_identifier (false, MULT_EXPR))
 	    code = MULT_EXPR;
-	  else if (id == cp_operator_id (MINUS_EXPR))
+	  else if (id == ovl_op_identifier (false, MINUS_EXPR))
 	    code = MINUS_EXPR;
-	  else if (id == cp_operator_id (BIT_AND_EXPR))
+	  else if (id == ovl_op_identifier (false, BIT_AND_EXPR))
 	    code = BIT_AND_EXPR;
-	  else if (id == cp_operator_id (BIT_IOR_EXPR))
+	  else if (id == ovl_op_identifier (false, BIT_IOR_EXPR))
 	    code = BIT_IOR_EXPR;
-	  else if (id == cp_operator_id (BIT_XOR_EXPR))
+	  else if (id == ovl_op_identifier (false, BIT_XOR_EXPR))
 	    code = BIT_XOR_EXPR;
-	  else if (id == cp_operator_id (TRUTH_ANDIF_EXPR))
+	  else if (id == ovl_op_identifier (false, TRUTH_ANDIF_EXPR))
 	    code = TRUTH_ANDIF_EXPR;
-	  else if (id == cp_operator_id (TRUTH_ORIF_EXPR))
+	  else if (id == ovl_op_identifier (false, TRUTH_ORIF_EXPR))
 	    code = TRUTH_ORIF_EXPR;
 	  id = omp_reduction_id (code, id, NULL_TREE);
 	  tree scope = parser->scope;
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 254263)
+++ gcc/cp/semantics.c	(working copy)
@@ -5099,7 +5099,7 @@ omp_reduction_id (enum tree_code reducti
     case BIT_IOR_EXPR:
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
-      reduction_id = cp_operator_id (reduction_code);
+      reduction_id = ovl_op_identifier (false, reduction_code);
       break;
     case MIN_EXPR:
       p = "min";
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 254263)
+++ gcc/cp/typeck.c	(working copy)
@@ -1562,7 +1562,7 @@ cxx_sizeof_or_alignof_type (tree type, e
       if (complain)
 	pedwarn (input_location, OPT_Wpointer_arith, 
 		 "invalid application of %qs to a member function", 
-		 operator_name_info[(int) op].name);
+		 OVL_OP_INFO (false, op)->name);
       else
 	return error_mark_node;
       value = size_one_node;
Index: libcc1/libcp1plugin.cc
===================================================================
--- libcc1/libcp1plugin.cc	(revision 254263)
+++ libcc1/libcp1plugin.cc	(working copy)
@@ -1346,12 +1346,7 @@ plugin_build_decl (cc1_plugin::connectio
 	    }
 
 	  if (opcode != ERROR_MARK)
-	    {
-	      if (assop)
-		identifier = cp_assignment_operator_id (opcode);
-	      else
-		identifier = cp_operator_id (opcode);
-	    }
+	    identifier = ovl_op_identifier (assop, opcode);
 	}
       decl = build_lang_decl_loc (loc, code, identifier, sym_type);
       /* FIXME: current_lang_name is lang_name_c while compiling an
@@ -1410,19 +1405,14 @@ plugin_build_decl (cc1_plugin::connectio
 	  DECL_DECLARED_INLINE_P (decl) = 1;
 	  DECL_INITIAL (decl) = error_mark_node;
 	}
-      if (ctor || dtor)
-	{
-	  if (ctor)
-	    DECL_CXX_CONSTRUCTOR_P (decl) = 1;
-	  if (dtor)
-	    DECL_CXX_DESTRUCTOR_P (decl) = 1;
-	}
-      else
-	{
-	  if ((sym_flags & GCC_CP_FLAG_SPECIAL_FUNCTION)
-	      && opcode != ERROR_MARK)
-	    SET_OVERLOADED_OPERATOR_CODE (decl, opcode);
-	}
+
+      if (ctor)
+	DECL_CXX_CONSTRUCTOR_P (decl) = 1;
+      else if (dtor)
+	DECL_CXX_DESTRUCTOR_P (decl) = 1;
+      else if ((sym_flags & GCC_CP_FLAG_SPECIAL_FUNCTION)
+	       && opcode != ERROR_MARK)
+	DECL_OVERLOADED_OPERATOR_CODE (decl) = opcode;
     }
   else if (RECORD_OR_UNION_CODE_P (code))
     {
@@ -2649,12 +2639,7 @@ plugin_build_dependent_expr (cc1_plugin:
       gcc_assert (convop || !conv_type);
 
       if (opcode != ERROR_MARK)
-	{
-	  if (assop)
-	    identifier = cp_assignment_operator_id (opcode);
-	  else
-	    identifier = cp_operator_id (opcode);
-	}
+	identifier = ovl_op_identifier (assop, opcode);
 
       gcc_assert (identifier);
     }

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [C++ PATCH] overloaded operator fns [3/N]
  2017-10-31 14:45 ` [C++ PATCH] overloaded operator fns [2/N] Nathan Sidwell
@ 2017-10-31 16:30   ` Nathan Sidwell
  2017-10-31 18:45     ` [C++ PATCH] overloaded operator fns [4/N] Nathan Sidwell
  0 siblings, 1 reply; 10+ messages in thread
From: Nathan Sidwell @ 2017-10-31 16:30 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 220 bytes --]

This patch replaces the operator info 'arity' field with a 'flags' field 
that encodes more information.  Adjusted the few places that look at 
this.  More use will be made in future patches.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-ident-3.diff --]
[-- Type: text/x-patch, Size: 14210 bytes --]

2017-10-31  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (enum ovl_op_flags): New.
	(struct operator_name_info_t): Rename arity to flags.
	* lex.c (set_operator_ident): New.
	(init_operators): Use it.  Adjust for flags.
	* mangle.c (write_unqualified_id): Adjust for flags.
	* operators.def: Replace arity with flags.

Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 254267)
+++ cp-tree.h	(working copy)
@@ -5474,16 +5474,27 @@ enum auto_deduction_context
 
 extern void init_reswords (void);
 
-typedef struct GTY(()) operator_name_info_t {
+/* 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  */
+  };
+
+struct GTY(()) operator_name_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 arity of the operator.  */
-  int arity;
-} operator_name_info_t;
+  /* 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
Index: lex.c
===================================================================
--- lex.c	(revision 254263)
+++ lex.c	(working copy)
@@ -82,13 +82,6 @@ operator_name_info_t operator_name_info[
 /* Similar, but for assignment operators.  */
 operator_name_info_t assignment_operator_name_info[(int) MAX_TREE_CODES];
 
-/* Initialize data structures that keep track of operator names.  */
-
-#define DEF_OPERATOR(NAME, C, M, AR, AP) \
- CONSTRAINT (C, sizeof "operator " + sizeof NAME <= 256);
-#include "operators.def"
-#undef DEF_OPERATOR
-
 /* Get the name of the kind of identifier T.  */
 
 const char *
@@ -120,28 +113,40 @@ set_identifier_kind (tree id, cp_identif
   IDENTIFIER_KIND_BIT_0 (id) |= (kind >> 0) & 1;
 }
 
+/* Create and tag the internal operator name for the overloaded
+   operator PTR describes.  */
+
+static tree
+set_operator_ident (operator_name_info_t *ptr)
+{
+  char buffer[32];
+  size_t len = snprintf (buffer, sizeof (buffer), "operator%s%s",
+			 &" "[ptr->name[0] && ptr->name[0] != '_'
+			      && !ISALPHA (ptr->name[0])],
+			 ptr->name);
+  gcc_checking_assert (len < sizeof (buffer));
+
+  tree ident = get_identifier_with_length (buffer, len);
+  ptr->identifier = ident;
+
+  return ident;
+}
+
 static void
 init_operators (void)
 {
   tree identifier;
-  char buffer[256];
-  struct operator_name_info_t *oni;
+  operator_name_info_t *oni;
 
-#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, KIND)			\
-  sprintf (buffer, "operator%s%s", !NAME[0]				\
-	   || NAME[0] == '_' || ISALPHA (NAME[0]) ? " " : "", NAME);	\
-  identifier = get_identifier (buffer);					\
-									\
-  if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier))	\
-    set_identifier_kind (identifier, KIND);				\
-  									\
-  oni = (KIND == cik_assign_op						\
-	 ? &assignment_operator_name_info[(int) CODE]			\
-	 : &operator_name_info[(int) CODE]);				\
-  oni->identifier = identifier;						\
+#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->arity = ARITY;
+  oni->flags = FLAGS;							\
+  identifier = set_operator_ident (oni);				\
+									\
+  if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier))	\
+    set_identifier_kind (identifier, KIND);
 
 #include "operators.def"
 #undef DEF_OPERATOR
Index: mangle.c
===================================================================
--- mangle.c	(revision 254267)
+++ mangle.c	(working copy)
@@ -1276,7 +1276,7 @@ write_unqualified_id (tree identifier)
 	  {
 	    /* The ABI says that we prefer binary operator
 	       names to unary operator names.  */
-	    if (operator_name_info[i].arity == 2)
+	    if (operator_name_info[i].flags == OVL_OP_FLAG_BINARY)
 	      {
 		mangled_name = operator_name_info[i].mangled_name;
 		break;
Index: operators.def
===================================================================
--- operators.def	(revision 254263)
+++ operators.def	(working copy)
@@ -45,11 +45,10 @@ along with GCC; see the file COPYING3.
      mangled under the new ABI.  For `operator +', for example, this
      would be "pl".
 
-   ARITY
+   FLAGS
 
-     The arity of the operator, or -1 if any arity is allowed.  (As
-     for `operator ()'.)  Postincrement and postdecrement operators
-     are marked as binary.
+     ovl_op_flags bits.  Postincrement and postdecrement operators are
+     marked as binary.
 
    ASSN_P
 
@@ -66,95 +65,99 @@ along with GCC; see the file COPYING3.
    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, ARITY) \
-  DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, cik_simple_op)
+#define DEF_SIMPLE_OPERATOR(NAME, CODE, MANGLING, FLAGS) \
+  DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_simple_op)
 
 /* 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.  */
 
-#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, ARITY) \
-  DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, cik_assign_op)
+#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, FLAGS) \
+  DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_assign_op)
 
 /* Memory allocation operators.  */
-DEF_OPERATOR ("new", NEW_EXPR, "nw", -1, cik_newdel_op)
-DEF_OPERATOR ("new []", VEC_NEW_EXPR, "na", -1, cik_newdel_op)
-DEF_OPERATOR ("delete", DELETE_EXPR, "dl", -1, cik_newdel_op)
-DEF_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", -1, cik_newdel_op)
+DEF_OPERATOR ("new", NEW_EXPR, "nw", OVL_OP_FLAG_ALLOC, cik_newdel_op)
+DEF_OPERATOR ("new []", VEC_NEW_EXPR, "na",
+	      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC, cik_newdel_op)
+DEF_OPERATOR ("delete", DELETE_EXPR, "dl",
+	      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE, cik_newdel_op)
+DEF_OPERATOR ("delete []", VEC_DELETE_EXPR, "da",
+	      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC,
+	      cik_newdel_op)
 
 /* Unary operators.  */
-DEF_SIMPLE_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", 1)
-DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", 1)
-DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", 1)
-DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", 1)
-DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", 1)
-DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", 1)
-DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", 1)
-DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", 1)
-DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", 1)
+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)
 /* These are extensions.  */
-DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", 1)
-DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", 1)
-DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1)
+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)
 
 /* The cast operators.  */
-DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", 1)
-DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", 1)
-DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", 1)
-DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", 1)
-DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", 1)
+DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", OVL_OP_FLAG_UNARY)
+DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_UNARY)
+DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_UNARY)
+DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", OVL_OP_FLAG_UNARY)
+DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_UNARY)
 
 /* Binary operators.  */
-DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", 2)
-DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", 2)
-DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", 2)
-DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", 2)
-DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", 2)
-DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", 2)
-DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", 2)
-DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", 2)
-DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", 2)
-DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", 2)
-DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", 2)
-DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", 2)
-DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", 2)
-DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", 2)
-DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", 2)
-DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", 2)
-DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2)
-DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2)
-DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2)
-DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2)
-DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", 2)
-DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2)
-DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2)
-DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2)
-DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", 2)
+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)
 /* This one is needed for mangling.  */
-DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", 2)
+DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", OVL_OP_FLAG_BINARY)
 
 /* Assignment operators.  */
-DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", 2)
-DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", 2)
-DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", 2)
-DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", 2)
-DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", 2)
-DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM", 2)
-DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", 2)
-DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", 2)
-DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", 2)
-DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", 2)
-DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", 2)
+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)
 
 /* Ternary operators.  */
-DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", 3)
+DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE)
 
 /* Miscellaneous.  */
-DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", -1)
+DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE)
 
 /* Variadic templates extension. */
-DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", 1)
-DEF_SIMPLE_OPERATOR ("... +", UNARY_LEFT_FOLD_EXPR, "fl", 2)
-DEF_SIMPLE_OPERATOR ("+ ...", UNARY_RIGHT_FOLD_EXPR, "fr", 2)
-DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_LEFT_FOLD_EXPR, "fL", 3)
-DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_RIGHT_FOLD_EXPR, "fR", 3)
+DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_UNARY)
+DEF_SIMPLE_OPERATOR ("... +", UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_BINARY)
+DEF_SIMPLE_OPERATOR ("+ ...", UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_BINARY)
+DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE)
+DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [C++ PATCH] overloaded operator fns [4/N]
  2017-10-31 16:30   ` [C++ PATCH] overloaded operator fns [3/N] Nathan Sidwell
@ 2017-10-31 18:45     ` Nathan Sidwell
  2017-10-31 20:20       ` [C++ PATCH] overloaded operator fns [5/N] Nathan Sidwell
  0 siblings, 1 reply; 10+ messages in thread
From: Nathan Sidwell @ 2017-10-31 18:45 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 440 bytes --]

The overloaded operator table conflates a couple of things -- both 
mangling and special names.  Entries just for mangling do not need a 
special name.  This sets them to NULL and no associated identifier is 
created.  init_operators created a bunch of pseudo entries, ostensibly 
'because errors', with a comment that we shouldn't be generating them. 
Turns out we don't appear to be using them, so also nuked.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-ident-4.diff --]
[-- Type: text/x-patch, Size: 6111 bytes --]

2017-10-31  Nathan Sidwell  <nathan@acm.org>

	* lex.c (init_operators): Allow NULL operator name.  Don't add
	special cases.
	* operators.def: Use NULL for mangling only operators.  Move to
	after regular operators but move assignment operators last.

Index: lex.c
===================================================================
--- lex.c	(revision 254271)
+++ lex.c	(working copy)
@@ -143,48 +143,14 @@ init_operators (void)
   oni->name = NAME;							\
   oni->mangled_name = MANGLING;						\
   oni->flags = FLAGS;							\
-  identifier = set_operator_ident (oni);				\
-									\
-  if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier))	\
-    set_identifier_kind (identifier, KIND);
+  if (NAME) {								\
+    identifier = set_operator_ident (oni);				\
+    if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier))	\
+      set_identifier_kind (identifier, KIND);				\
+  }
 
 #include "operators.def"
 #undef DEF_OPERATOR
-
-  operator_name_info[(int) TYPE_EXPR] = operator_name_info[(int) CAST_EXPR];
-  operator_name_info[(int) ERROR_MARK].identifier
-    = get_identifier ("<invalid operator>");
-
-  /* Handle some special cases.  These operators are not defined in
-     the language, but can be produced internally.  We may need them
-     for error-reporting.  (Eventually, we should ensure that this
-     does not happen.  Error messages involving these operators will
-     be confusing to users.)  */
-
-  operator_name_info [(int) INIT_EXPR].name
-    = operator_name_info [(int) MODIFY_EXPR].name;
-
-  operator_name_info [(int) EXACT_DIV_EXPR].name = "(ceiling /)";
-  operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /)";
-  operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /)";
-  operator_name_info [(int) ROUND_DIV_EXPR].name = "(round /)";
-  operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %)";
-  operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %)";
-  operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %)";
-
-  operator_name_info [(int) ABS_EXPR].name = "abs";
-  operator_name_info [(int) TRUTH_AND_EXPR].name = "strict &&";
-  operator_name_info [(int) TRUTH_OR_EXPR].name = "strict ||";
-  operator_name_info [(int) RANGE_EXPR].name = "...";
-  operator_name_info [(int) UNARY_PLUS_EXPR].name = "+";
-
-  assignment_operator_name_info [(int) EXACT_DIV_EXPR].name = "(exact /=)";
-  assignment_operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /=)";
-  assignment_operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /=)";
-  assignment_operator_name_info [(int) ROUND_DIV_EXPR].name = "(round /=)";
-  assignment_operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %=)";
-  assignment_operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %=)";
-  assignment_operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %=)";
 }
 
 /* Initialize the reserved words.  */
Index: operators.def
===================================================================
--- operators.def	(revision 254271)
+++ operators.def	(working copy)
@@ -100,13 +100,6 @@ DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_
 DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", OVL_OP_FLAG_UNARY)
 DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", OVL_OP_FLAG_UNARY)
 
-/* The cast operators.  */
-DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", 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)
@@ -133,8 +126,23 @@ DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF
 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)
-/* This one is needed for mangling.  */
-DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", 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)
+
+/* 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)
 
 /* Assignment operators.  */
 DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", OVL_OP_FLAG_BINARY)
@@ -149,15 +157,3 @@ DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "
 DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", OVL_OP_FLAG_BINARY)
 DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", OVL_OP_FLAG_BINARY)
 
-/* Ternary operators.  */
-DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE)
-
-/* Miscellaneous.  */
-DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE)
-
-/* Variadic templates extension. */
-DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_UNARY)
-DEF_SIMPLE_OPERATOR ("... +", UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("+ ...", UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_BINARY)
-DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE)
-DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [C++ PATCH] overloaded operator fns [5/N]
  2017-10-31 18:45     ` [C++ PATCH] overloaded operator fns [4/N] Nathan Sidwell
@ 2017-10-31 20:20       ` Nathan Sidwell
  2017-11-01 14:02         ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell
  0 siblings, 1 reply; 10+ messages in thread
From: Nathan Sidwell @ 2017-10-31 20:20 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 496 bytes --]

This patch replaces the separate operator_name_info & 
assignment_operator_name_info arrays with a single 2D ovl_op_info array. 
  I also add a tree_code field to the renamed ovl_op_info_t, which 
although in this instance is simply a 1:1 mapping to the array index, 
will morph soon as the indices will not be by tree_code.

Although this tweaks the array scanning, the ultimate aim is that that 
scanning goes away, and a simple indirection gets us to what we want.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-ident-5.diff --]
[-- Type: text/x-patch, Size: 8787 bytes --]

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.

Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 254271)
+++ cp-tree.h	(working copy)
@@ -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.  */
Index: decl.c
===================================================================
--- decl.c	(revision 254267)
+++ decl.c	(working copy)
@@ -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 comp
   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 comp
 	    }
 	}
 
-      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 comp
 	}
     }
 
-  /* 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)
Index: lex.c
===================================================================
--- lex.c	(revision 254276)
+++ lex.c	(working copy)
@@ -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_identif
    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);				\
Index: mangle.c
===================================================================
--- mangle.c	(revision 254271)
+++ mangle.c	(working copy)
@@ -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))

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [C++ PATCH] overloaded operator fns [6/N]
  2017-10-31 20:20       ` [C++ PATCH] overloaded operator fns [5/N] Nathan Sidwell
@ 2017-11-01 14:02         ` Nathan Sidwell
  2017-11-01 15:45           ` Nathan Sidwell
  2017-11-01 18:29           ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell
  0 siblings, 2 replies; 10+ messages in thread
From: Nathan Sidwell @ 2017-11-01 14:02 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 711 bytes --]

This patch adds a new enum for the overloaded operators, we only 
enumerate the codes we need, and thus can shrink the ovl_op_info array. 
We do need to create a mapping array to go from tree_code to ovl_op_code.

More significantly is the use of the base.u.bits.address_space field, 
which is otherwise unused in an identifier.  We can use this as an 
arbitrary 8-bit index.  Which indeed this patch does for the overloaded 
operators.  This means grok_op_properties and mangling can directly 
index the operator information, rather than search for them.  We also 
simplify the ambi-ary operators by detecting these cases during 
initialization and constructing an alternate array.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-ident-6.diff --]
[-- Type: text/x-patch, Size: 26043 bytes --]

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.

Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 254279)
+++ cp-tree.h	(working copy)
@@ -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.  */
Index: decl.c
===================================================================
--- decl.c	(revision 254279)
+++ decl.c	(working copy)
@@ -65,8 +65,6 @@ static const char *redeclaration_error_m
 
 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,
   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 comp
     }
   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 comp
     }
 
   /* 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 comp
 		 : 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 comp
 		 : 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))
Index: lex.c
===================================================================
--- lex.c	(revision 254279)
+++ lex.c	(working copy)
@@ -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;
+  /* We rely on both these being zero.  */
+  gcc_checking_assert (!OVL_OP_ERROR_MARK && !ERROR_MARK);
 
-#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);				\
-  }
-
-#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.  */
Index: mangle.c
===================================================================
--- mangle.c	(revision 254279)
+++ mangle.c	(working copy)
@@ -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);
Index: operators.def
===================================================================
--- operators.def	(revision 254279)
+++ operators.def	(working copy)
@@ -50,110 +50,109 @@ along with GCC; see the file COPYING3.
      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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] overloaded operator fns [6/N]
  2017-11-01 14:02         ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell
@ 2017-11-01 15:45           ` Nathan Sidwell
  2017-11-01 18:29           ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell
  1 sibling, 0 replies; 10+ messages in thread
From: Nathan Sidwell @ 2017-11-01 15:45 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 506 bytes --]

This patch shrinks the lang_fn_decl's operator_code field from 16 to 6 
bits, by storing the compressed operator code instead of the tree_code.

I rename DECL_OVERLOADED_OPERATOR_CODE to 
DECL_OVERLOADED_OPERATOR_CODE_RAW, to remind that it's not a tree_code. 
DECL_OVERLOADED_OPERATOR_CODE_IS remains with checking a literal tree 
code.  It uses preprocessor concatenation to directly map the tree_code 
name to the compressed operator enumeration.  So no runtime indirection!

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-ident-7.diff --]
[-- Type: text/x-patch, Size: 8237 bytes --]

2017-11-01  Nathan Sidwell  <nathan@acm.org>

	gcc/cp/
	* cp-tree.h (assign_op_identifier, call_op_identifier): Use
	compressed code.
	(struct lang_decl_fn): Use compressed operator code.
	(DECL_OVERLOADED_OPERATOR_CODE): Replace with ...
	(DECL_OVERLOADED_OPERATOR_CODE_RAW): ... this.
	(DECL_OVERLOADED_OPERATOR_CODE_IS): Use it.
	* decl.c (duplicate_decls): Use DECL_OVERLOADED_OPERATOR_CODE_RAW.
	(build_library_fn): Likewise.
	(grok_op_properties): Likewise.
	* mangle.c (write_unqualified_name): Likewise.
	* method.c (implicitly_declare_fn): Likewise.
	* typeck.c (check_return_expr): Use DECL_OVERLOADED_OPERATOR_IS.

	libcc1/
	* libcp1plugin.cc (plugin_build_decl): Use
	DECL_OVERLOADED_OPERATOR_CODE_RAW.

Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 254311)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -246,8 +246,8 @@ extern GTY(()) tree cp_global_trees[CPTI
 #define deleting_dtor_identifier	cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER]
 
 #define ovl_op_identifier(ISASS, CODE)  (OVL_OP_INFO(ISASS, CODE)->identifier)
-#define assign_op_identifier (ovl_op_identifier (true, NOP_EXPR))
-#define call_op_identifier (ovl_op_identifier (false, CALL_EXPR))
+#define assign_op_identifier (ovl_op_info[true][OVL_OP_NOP_EXPR].identifier)
+#define call_op_identifier (ovl_op_info[false][OVL_OP_CALL_EXPR].identifier)
 /* The name used for conversion operators -- but note that actual
    conversion functions use special identifiers outside the identifier
    table.  */
@@ -2479,26 +2479,24 @@ struct GTY(()) lang_decl_min {
 struct GTY(()) lang_decl_fn {
   struct lang_decl_min min;
 
-  /* In an overloaded operator, this is the value of
-     DECL_OVERLOADED_OPERATOR_P.
-     FIXME: We should really do better in compressing this.  */
-  ENUM_BITFIELD (tree_code) operator_code : 16;
-
+  /* In a overloaded operator, this is the compressed operator code.  */
+  unsigned ovl_op_code : 6;
   unsigned global_ctor_p : 1;
   unsigned global_dtor_p : 1;
+
   unsigned static_function : 1;
   unsigned pure_virtual : 1;
   unsigned defaulted_p : 1;
   unsigned has_in_charge_parm_p : 1;
   unsigned has_vtt_parm_p : 1;
   unsigned pending_inline_p : 1;
-
   unsigned nonconverting : 1;
   unsigned thunk_p : 1;
+
   unsigned this_thunk_p : 1;
   unsigned hidden_friend_p : 1;
   unsigned omp_declare_reduction_p : 1;
-  /* 3 spare bits.  */
+  unsigned spare : 13;
 
   /* 32-bits padding on 64-bit host.  */
 
@@ -2814,14 +2812,14 @@ struct GTY(()) lang_decl {
   IDENTIFIER_ASSIGN_OP_P (DECL_NAME (NODE))
 
 /* NODE is a function_decl for an overloaded operator.  Return its
-   operator code.   */
-#define DECL_OVERLOADED_OPERATOR_CODE(NODE)			\
-  (LANG_DECL_FN_CHECK (NODE)->operator_code)
+   compressed (raw) operator code.  Note that this is not a TREE_CODE.  */
+#define DECL_OVERLOADED_OPERATOR_CODE_RAW(NODE)		\
+  (LANG_DECL_FN_CHECK (NODE)->ovl_op_code)
 
 /* DECL is an overloaded operator.  Test whether it is for TREE_CODE
    (a literal constant).  */
 #define DECL_OVERLOADED_OPERATOR_IS(DECL, CODE)			\
-  (DECL_OVERLOADED_OPERATOR_CODE (DECL) == CODE)
+  (DECL_OVERLOADED_OPERATOR_CODE_RAW (DECL) == OVL_OP_##CODE)
 
 /* For FUNCTION_DECLs: nonzero means that this function is a
    constructor or a destructor with an extra in-charge parameter to
@@ -5526,7 +5524,8 @@ extern GTY(()) unsigned char ovl_op_mapp
 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.  */
+   overloaded operator info.  Tree codes for non-overloaded operators
+   map to the error-operator.  */
 #define OVL_OP_INFO(IS_ASS_P, TREE_CODE)			\
   (&ovl_op_info[(IS_ASS_P) != 0][ovl_op_mapping[(TREE_CODE)]])
 /* Overloaded operator info for an identifier for which
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 254311)
+++ gcc/cp/decl.c	(working copy)
@@ -1920,8 +1920,8 @@ next_arg:;
       DECL_OVERRIDE_P (newdecl) |= DECL_OVERRIDE_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
       if (DECL_OVERLOADED_OPERATOR_P (olddecl))
-	DECL_OVERLOADED_OPERATOR_CODE (newdecl)
-	  = DECL_OVERLOADED_OPERATOR_CODE (olddecl);
+	DECL_OVERLOADED_OPERATOR_CODE_RAW (newdecl)
+	  = DECL_OVERLOADED_OPERATOR_CODE_RAW (olddecl);
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
       /* Optionally warn about more than one declaration for the same
@@ -4444,7 +4444,8 @@ build_library_fn (tree name, enum tree_c
   DECL_EXTERNAL (fn) = 1;
   TREE_PUBLIC (fn) = 1;
   DECL_ARTIFICIAL (fn) = 1;
-  DECL_OVERLOADED_OPERATOR_CODE (fn) = operator_code;
+  DECL_OVERLOADED_OPERATOR_CODE_RAW (fn)
+    = OVL_OP_INFO (false, operator_code)->ovl_op_code;
   SET_DECL_LANGUAGE (fn, lang_c);
   /* Runtime library routines are, by definition, available in an
      external shared object.  */
@@ -12902,7 +12903,7 @@ grok_op_properties (tree decl, bool comp
       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;
+      DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) = ovl_op->ovl_op_code;
     }
 
   if (op_flags & OVL_OP_FLAG_ALLOC)
@@ -13046,7 +13047,7 @@ grok_op_properties (tree decl, bool comp
 	  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;
+	  DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) = ovl_op->ovl_op_code;
 	}
       else if (arity != 2)
 	{
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 254311)
+++ gcc/cp/mangle.c	(working copy)
@@ -1321,8 +1321,8 @@ write_unqualified_name (tree decl)
       else if (DECL_OVERLOADED_OPERATOR_P (decl))
 	{
 	  const char *mangled_name
-	    = (OVL_OP_INFO (DECL_ASSIGNMENT_OPERATOR_P (decl),
-	       DECL_OVERLOADED_OPERATOR_CODE (decl))->mangled_name);
+	    = (ovl_op_info[DECL_ASSIGNMENT_OPERATOR_P (decl)]
+	       [DECL_OVERLOADED_OPERATOR_CODE_RAW (decl)].mangled_name);
 	  write_string (mangled_name);
 	}
       else if (UDLIT_OPER_P (DECL_NAME (decl)))
Index: gcc/cp/method.c
===================================================================
--- gcc/cp/method.c	(revision 254311)
+++ gcc/cp/method.c	(working copy)
@@ -2078,7 +2078,7 @@ implicitly_declare_fn (special_function_
 
   if (!IDENTIFIER_CDTOR_P (name))
     /* Assignment operator.  */
-    DECL_OVERLOADED_OPERATOR_CODE (fn) = NOP_EXPR;
+    DECL_OVERLOADED_OPERATOR_CODE_RAW (fn) = OVL_OP_NOP_EXPR;
   else if (IDENTIFIER_CTOR_P (name))
     DECL_CXX_CONSTRUCTOR_P (fn) = true;
   else
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 254311)
+++ gcc/cp/typeck.c	(working copy)
@@ -9074,9 +9074,8 @@ check_return_expr (tree retval, bool *no
 
   /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
   if (DECL_OVERLOADED_OPERATOR_P (current_function_decl)
-      && (DECL_OVERLOADED_OPERATOR_CODE (current_function_decl) == NEW_EXPR
-	  || (DECL_OVERLOADED_OPERATOR_CODE (current_function_decl)
-	      == VEC_NEW_EXPR))
+      && (DECL_OVERLOADED_OPERATOR_IS (current_function_decl,  NEW_EXPR)
+	  || DECL_OVERLOADED_OPERATOR_IS (current_function_decl, VEC_NEW_EXPR))
       && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
       && ! flag_check_new
       && retval && null_ptr_cst_p (retval))
Index: libcc1/libcp1plugin.cc
===================================================================
--- libcc1/libcp1plugin.cc	(revision 254311)
+++ libcc1/libcp1plugin.cc	(working copy)
@@ -1412,7 +1412,7 @@ plugin_build_decl (cc1_plugin::connectio
 	DECL_CXX_DESTRUCTOR_P (decl) = 1;
       else if ((sym_flags & GCC_CP_FLAG_SPECIAL_FUNCTION)
 	       && opcode != ERROR_MARK)
-	DECL_OVERLOADED_OPERATOR_CODE (decl) = opcode;
+	DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) = ovl_op_mapping[opcode];
     }
   else if (RECORD_OR_UNION_CODE_P (code))
     {

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [C++ PATCH] overloaded operator fns [8/N]
  2017-11-01 14:02         ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell
  2017-11-01 15:45           ` Nathan Sidwell
@ 2017-11-01 18:29           ` Nathan Sidwell
  2017-11-01 20:09             ` Jason Merrill
  1 sibling, 1 reply; 10+ messages in thread
From: Nathan Sidwell @ 2017-11-01 18:29 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 538 bytes --]

This is the last of the overloaded operator reworking.  Now we can 
cheaply go from identifier->overload info, there's no need to specially 
mark identifiers as new or delete operators themselves.  Thus we can 
reorder the cp_identifier_kind enumeration and leave space in it for 
udlit operators.

This patch does that renumbering, and reserves a value for udlit 
operators.  Those are currently detected by string compare, which isn't 
the most satisfactory way to do it.  But it's a change for another day.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-ident-8.diff --]
[-- Type: text/x-patch, Size: 7169 bytes --]

2017-11-01  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (enum cp_identifier_kind): Delete cik_newdel_op.
	Renumber and reserve udlit value.
	(IDENTIFIER_NEWDEL_OP): Delete.
	(IDENTIFIER_OVL_OP): New.
	(IDENTIFIER_ASSIGN_OP): Adjust.
	(IDENTIFIER_CONV_OP): Adjust.
	(IDENTIFIER_OVL_OP_INFO): Adjust.
	(IDENTIFIER_OVL_OP_FLAGS): New.
	* decl.c (grokdeclarator): Use IDENTIFIER_OVL_OP_FLAGS.
	* lex.c (get_identifier_kind_name): Adjust.
	(init_operators): Don't special case new/delete ops.
	* mangle.c (write_unqualified_id): Use IDENTIFIER_OVL_OP.
	* pt.c (push_template_decl_real): Use IDENTIFIER_OVL_OP_FLAGS.
	* typeck.c (check_return_expr): Likewise.

Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 254314)
+++ cp-tree.h	(working copy)
@@ -996,9 +996,9 @@ enum cp_identifier_kind {
   cik_dtor = 3,		/* Destructor (in-chg, deleting, complete or
 			   base).  */
   cik_simple_op = 4,	/* Non-assignment operator name.  */
-  cik_newdel_op = 5,	/* New or delete operator name.  */
-  cik_assign_op = 6,	/* An assignment operator name.  */
-  cik_conv_op = 7,	/* Conversion 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_max
 };
 
@@ -1053,24 +1053,22 @@ enum cp_identifier_kind {
 #define IDENTIFIER_ANY_OP_P(NODE)		\
   (IDENTIFIER_KIND_BIT_2 (NODE))
 
-/* True if this identifier is for new or delete operator.  Value 5.  */
-#define IDENTIFIER_NEWDEL_OP_P(NODE)		\
-  (IDENTIFIER_KIND_BIT_2 (NODE)			\
-   & (!IDENTIFIER_KIND_BIT_1 (NODE))		\
-   & IDENTIFIER_KIND_BIT_0 (NODE))
+/* True if this identifier is for an overloaded operator. Values 4, 5.  */
+#define IDENTIFIER_OVL_OP_P(NODE)		\
+  (IDENTIFIER_ANY_OP_P (NODE)			\
+   & (!IDENTIFIER_KIND_BIT_1 (NODE)))
 
-/* True if this identifier is for any assignment. Values 6.  */
+/* True if this identifier is for any assignment. Values 5.  */
 #define IDENTIFIER_ASSIGN_OP_P(NODE)		\
-  (IDENTIFIER_KIND_BIT_2 (NODE)			\
-   & IDENTIFIER_KIND_BIT_1 (NODE)		\
-   & (!IDENTIFIER_KIND_BIT_0 (NODE)))
+  (IDENTIFIER_OVL_OP_P (NODE)			\
+   & IDENTIFIER_KIND_BIT_0 (NODE))
 
 /* True if this identifier is the name of a type-conversion
    operator.  Value 7.  */
 #define IDENTIFIER_CONV_OP_P(NODE)		\
-  (IDENTIFIER_KIND_BIT_2 (NODE)			\
+  (IDENTIFIER_ANY_OP_P (NODE)			\
    & IDENTIFIER_KIND_BIT_1 (NODE)		\
-   & IDENTIFIER_KIND_BIT_0 (NODE))
+   & (!IDENTIFIER_KIND_BIT_0 (NODE)))
 
 /* Access a C++-specific index for identifier NODE.
    Used to optimize operator mappings etc.  */
@@ -5529,9 +5527,11 @@ extern GTY(()) unsigned char ovl_op_alte
 #define OVL_OP_INFO(IS_ASS_P, 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.  */
+   IDENTIFIER_OVL_OP_P is true.  */
 #define IDENTIFIER_OVL_OP_INFO(NODE) \
-  (&ovl_op_info[IDENTIFIER_ASSIGN_OP_P (NODE)][IDENTIFIER_CP_INDEX (NODE)])
+  (&ovl_op_info[IDENTIFIER_KIND_BIT_0 (NODE)][IDENTIFIER_CP_INDEX (NODE)])
+#define IDENTIFIER_OVL_OP_FLAGS(NODE) \
+  (IDENTIFIER_OVL_OP_INFO (NODE)->flags)
 
 /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL
    constants.  */
Index: decl.c
===================================================================
--- decl.c	(revision 254314)
+++ decl.c	(working copy)
@@ -11744,7 +11744,8 @@ grokdeclarator (const cp_declarator *dec
 
   if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
       && !(identifier_p (unqualified_id)
-	   && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
+	   && IDENTIFIER_OVL_OP_P (unqualified_id)
+	   && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC)))
     {
       cp_cv_quals real_quals = memfn_quals;
       if (cxx_dialect < cxx14 && constexpr_p
@@ -11857,7 +11858,9 @@ grokdeclarator (const cp_declarator *dec
 
 		if (virtualp
 		    && identifier_p (unqualified_id)
-		    && IDENTIFIER_NEWDEL_OP_P (unqualified_id))
+		    && IDENTIFIER_OVL_OP_P (unqualified_id)
+		    && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id)
+			& OVL_OP_FLAG_ALLOC))
 		  {
 		    error ("%qD cannot be declared %<virtual%>, since it "
 			   "is always static", unqualified_id);
Index: lex.c
===================================================================
--- lex.c	(revision 254314)
+++ lex.c	(working copy)
@@ -100,7 +100,8 @@ get_identifier_kind_name (tree id)
   /* Keep in sync with cp_id_kind enumeration.  */
   static const char *const names[cik_max] = {
     "normal", "keyword", "constructor", "destructor",
-    "assign-op", "op-assign-op", "simple-op", "conv-op", };
+    "simple-op", "assign-op", "conv-op", "<reserved>udlit-op"
+  };
 
   unsigned kind = 0;
   kind |= IDENTIFIER_KIND_BIT_2 (id) << 2;
@@ -176,9 +177,7 @@ init_operators (void)
 	  else
 	    {
 	      IDENTIFIER_CP_INDEX (ident) = ix;
-	      set_identifier_kind (ident,
-				   op_ptr->flags & OVL_OP_FLAG_ALLOC
-				   ? cik_newdel_op : cik_simple_op);
+	      set_identifier_kind (ident, cik_simple_op);
 	    }
 	}
       if (op_ptr->tree_code)
Index: mangle.c
===================================================================
--- mangle.c	(revision 254314)
+++ mangle.c	(working copy)
@@ -1263,7 +1263,7 @@ write_unqualified_id (tree identifier)
 {
   if (IDENTIFIER_CONV_OP_P (identifier))
     write_conversion_operator_name (TREE_TYPE (identifier));
-  else if (IDENTIFIER_ANY_OP_P (identifier))
+  else if (IDENTIFIER_OVL_OP_P (identifier))
     {
       const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (identifier);
       write_string (ovl_op->mangled_name);
Index: pt.c
===================================================================
--- pt.c	(revision 254314)
+++ pt.c	(working copy)
@@ -5329,7 +5329,9 @@ push_template_decl_real (tree decl, bool
 	      error ("destructor %qD declared as member template", decl);
 	      return error_mark_node;
 	    }
-	  if (IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl))
+	  if (IDENTIFIER_OVL_OP_P (DECL_NAME (decl))
+	      && (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (decl))
+		  & OVL_OP_FLAG_ALLOC)
 	      && (!prototype_p (TREE_TYPE (decl))
 		  || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node
 		  || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
Index: typeck.c
===================================================================
--- typeck.c	(revision 254314)
+++ typeck.c	(working copy)
@@ -9073,9 +9073,9 @@ check_return_expr (tree retval, bool *no
     }
 
   /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
-  if (DECL_OVERLOADED_OPERATOR_P (current_function_decl)
-      && (DECL_OVERLOADED_OPERATOR_IS (current_function_decl,  NEW_EXPR)
-	  || DECL_OVERLOADED_OPERATOR_IS (current_function_decl, VEC_NEW_EXPR))
+  if (IDENTIFIER_OVL_OP_P (DECL_NAME (current_function_decl))
+      && ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (current_function_decl))
+	   & (OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)) == OVL_OP_FLAG_ALLOC)
       && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
       && ! flag_check_new
       && retval && null_ptr_cst_p (retval))

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] overloaded operator fns [8/N]
  2017-11-01 18:29           ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell
@ 2017-11-01 20:09             ` Jason Merrill
  2017-11-02 14:15               ` Nathan Sidwell
  0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2017-11-01 20:09 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: GCC Patches

On Wed, Nov 1, 2017 at 2:29 PM, Nathan Sidwell <nathan@acm.org> wrote:
> This is the last of the overloaded operator reworking.  Now we can cheaply
> go from identifier->overload info, there's no need to specially mark
> identifiers as new or delete operators themselves.  Thus we can reorder the
> cp_identifier_kind enumeration and leave space in it for udlit operators.
>
> This patch does that renumbering, and reserves a value for udlit operators.
> Those are currently detected by string compare, which isn't the most
> satisfactory way to do it.  But it's a change for another day.

> -    && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
> +    && IDENTIFIER_OVL_OP_P (unqualified_id)
> +    && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC)))

Why not keep the name IDENTIFIER_NEWDEL_OP_P, which expands to this?

Jason

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] overloaded operator fns [8/N]
  2017-11-01 20:09             ` Jason Merrill
@ 2017-11-02 14:15               ` Nathan Sidwell
  0 siblings, 0 replies; 10+ messages in thread
From: Nathan Sidwell @ 2017-11-02 14:15 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 534 bytes --]

On 11/01/2017 04:08 PM, Jason Merrill wrote:
> On Wed, Nov 1, 2017 at 2:29 PM, Nathan Sidwell <nathan@acm.org> wrote:

>> -    && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
>> +    && IDENTIFIER_OVL_OP_P (unqualified_id)
>> +    && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC)))
> 
> Why not keep the name IDENTIFIER_NEWDEL_OP_P, which expands to this?

Hm, I guess that would be better.  This patch does that, and introduces 
IDENTIFIER_NEW_OP_P, for when we just want the new operators.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: op-newdel.diff --]
[-- Type: text/x-patch, Size: 3517 bytes --]

2017-11-02  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (IDENTIFIER_NEWDEL_OP_P): Restore, adjust.
	(IDENTIFIER_NEW_OP_P): New.
	* decl.c (grokdeclarator): Restore IDENTIFIER_NEWDEL_OP_P use.
	* pt.c (push_template_decl_real): Likewise.
	* typeck.c (check_return_expr): Use IDENTIFIER_NEW_OP_P.

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 254344)
+++ cp/cp-tree.h	(working copy)
@@ -1070,6 +1070,17 @@ enum cp_identifier_kind {
    & IDENTIFIER_KIND_BIT_1 (NODE)		\
    & (!IDENTIFIER_KIND_BIT_0 (NODE)))
 
+/* True if this identifier is a new or delete operator.  */
+#define IDENTIFIER_NEWDEL_OP_P(NODE)		\
+  (IDENTIFIER_OVL_OP_P (NODE)			\
+   && IDENTIFIER_OVL_OP_FLAGS (NODE) & OVL_OP_FLAG_ALLOC)
+
+/* True if this identifier is a new operator.  */
+#define IDENTIFIER_NEW_OP_P(NODE)					\
+  (IDENTIFIER_OVL_OP_P (NODE)						\
+   && (IDENTIFIER_OVL_OP_FLAGS (NODE)					\
+       & (OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)) == OVL_OP_FLAG_ALLOC)
+
 /* Access a C++-specific index for identifier NODE.
    Used to optimize operator mappings etc.  */
 #define IDENTIFIER_CP_INDEX(NODE)		\
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 254344)
+++ cp/decl.c	(working copy)
@@ -11744,8 +11744,7 @@ grokdeclarator (const cp_declarator *dec
 
   if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
       && !(identifier_p (unqualified_id)
-	   && IDENTIFIER_OVL_OP_P (unqualified_id)
-	   && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC)))
+	   && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
     {
       cp_cv_quals real_quals = memfn_quals;
       if (cxx_dialect < cxx14 && constexpr_p
@@ -11858,9 +11857,7 @@ grokdeclarator (const cp_declarator *dec
 
 		if (virtualp
 		    && identifier_p (unqualified_id)
-		    && IDENTIFIER_OVL_OP_P (unqualified_id)
-		    && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id)
-			& OVL_OP_FLAG_ALLOC))
+		    && IDENTIFIER_NEWDEL_OP_P (unqualified_id))
 		  {
 		    error ("%qD cannot be declared %<virtual%>, since it "
 			   "is always static", unqualified_id);
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 254344)
+++ cp/pt.c	(working copy)
@@ -5329,9 +5329,7 @@ push_template_decl_real (tree decl, bool
 	      error ("destructor %qD declared as member template", decl);
 	      return error_mark_node;
 	    }
-	  if (IDENTIFIER_OVL_OP_P (DECL_NAME (decl))
-	      && (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (decl))
-		  & OVL_OP_FLAG_ALLOC)
+	  if (IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl))
 	      && (!prototype_p (TREE_TYPE (decl))
 		  || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node
 		  || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 254344)
+++ cp/typeck.c	(working copy)
@@ -9073,9 +9073,7 @@ check_return_expr (tree retval, bool *no
     }
 
   /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
-  if (IDENTIFIER_OVL_OP_P (DECL_NAME (current_function_decl))
-      && ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (current_function_decl))
-	   & (OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)) == OVL_OP_FLAG_ALLOC)
+  if (IDENTIFIER_NEW_OP_P (DECL_NAME (current_function_decl))
       && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
       && ! flag_check_new
       && retval && null_ptr_cst_p (retval))

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-11-02 14:15 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-31 13:12 [C++ PATCH] overloaded operator fns [1/N] Nathan Sidwell
2017-10-31 14:45 ` [C++ PATCH] overloaded operator fns [2/N] Nathan Sidwell
2017-10-31 16:30   ` [C++ PATCH] overloaded operator fns [3/N] Nathan Sidwell
2017-10-31 18:45     ` [C++ PATCH] overloaded operator fns [4/N] Nathan Sidwell
2017-10-31 20:20       ` [C++ PATCH] overloaded operator fns [5/N] Nathan Sidwell
2017-11-01 14:02         ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell
2017-11-01 15:45           ` Nathan Sidwell
2017-11-01 18:29           ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell
2017-11-01 20:09             ` Jason Merrill
2017-11-02 14:15               ` Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).