diff mbox series

[C++] overloaded operator fns [5/N]

Message ID bf60c5cd-dea2-8e38-f737-ed40a5970f32@acm.org
State New
Headers show
Series [C++] overloaded operator fns [5/N] | expand

Commit Message

Nathan Sidwell Oct. 31, 2017, 8:08 p.m. UTC
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
diff mbox series

Patch

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))