diff mbox series

[C++] class member ordering

Message ID 510f7c74-6417-20c6-9979-7301ddcbaec7@acm.org
State New
Headers show
Series [C++] class member ordering | expand

Commit Message

Nathan Sidwell Sept. 21, 2017, 2:50 a.m. UTC
This patch makes the class member ordering well defined, in the face of 
decls with identical locations.

We spuriously generate duplicate TYPE_DECLS, which we shouldn't do.  But 
we can also reach this via (at least) template parameter pack expansions.

Fixed by using DECL_UID as a more complete ordering than 
DECL_SOURCE_LOCATION.

nathan
diff mbox series

Patch

2017-09-20  Nathan Sidwell  <nathan@acm.org>

	* name-lookup.c (member_name_cmp): Use DECL_UID for final
	ordering.

Index: name-lookup.c
===================================================================
--- name-lookup.c	(revision 252918)
+++ name-lookup.c	(working copy)
@@ -1434,29 +1434,38 @@  member_name_cmp (const void *a_p, const
     b = OVL_FUNCTION (b);
 
   /* We're in STAT_HACK or USING_DECL territory (or possibly error-land). */
-  if (TREE_CODE (a) == TREE_CODE (b))
-    /* We can get two TYPE_DECLs or two USING_DECLs.  Place in source
-       order.  */
-    return DECL_SOURCE_LOCATION (a) < DECL_SOURCE_LOCATION (b) ? -1 : +1;
-
-  /* If one of them is a TYPE_DECL, it loses.  */
-  if (TREE_CODE (a) == TYPE_DECL)
-    return +1;
-  else if (TREE_CODE (b) == TYPE_DECL)
-    return -1;
-
-  /* If one of them is a USING_DECL, it loses.  */
-  if (TREE_CODE (a) == USING_DECL)
-    return +1;
-  else if (TREE_CODE (b) == USING_DECL)
-    return -1;
-
-  /* There are no other cases, as duplicate detection should have
-     kicked in earlier.  However, some erroneous cases get though.
-     Order by source location.  We should really prevent this
-     happening.  */
-  gcc_assert (errorcount);
-  return DECL_SOURCE_LOCATION (a) < DECL_SOURCE_LOCATION (b) ? -1 : +1;
+  if (TREE_CODE (a) != TREE_CODE (b))
+    {
+      /* If one of them is a TYPE_DECL, it loses.  */
+      if (TREE_CODE (a) == TYPE_DECL)
+	return +1;
+      else if (TREE_CODE (b) == TYPE_DECL)
+	return -1;
+
+      /* If one of them is a USING_DECL, it loses.  */
+      if (TREE_CODE (a) == USING_DECL)
+	return +1;
+      else if (TREE_CODE (b) == USING_DECL)
+	return -1;
+
+      /* There are no other cases with different kinds of decls, as
+	 duplicate detection should have kicked in earlier.  However,
+	 some erroneous cases get though. */
+      gcc_assert (errorcount);
+    }
+  
+  /* Using source location would be the best thing here, but we can
+     get identically-located decls in the following circumstances:
+
+     1) duplicate artificial type-decls for the same type.
+
+     2) pack expansions of using-decls.
+
+     We should not be doing #1, but in either case it doesn't matter
+     how we order these.  Use UID as a proxy for source ordering, so
+     that identically-located decls still have a well-defined stable
+     ordering.  */
+  return DECL_UID (a) < DECL_UID (b) ? -1 : +1;
 }
 
 static struct {