diff mbox

[pph] Correct overloading (issue5555059)

Message ID 20120120184527.D6D6322263C@jade.mtv.corp.google.com
State New
Headers show

Commit Message

Lawrence Crowl Jan. 20, 2012, 6:45 p.m. UTC
Correct construction of bindings for overloaded symbols.



--
This patch is available for review at http://codereview.appspot.com/5555059
diff mbox

Patch

Index: gcc/testsuite/ChangeLog.pph

2011-01-20   Lawrence Crowl  <crowl@google.com>

	* g++.dg/pph/x4overset1.cc: Make passing.
	* g++.dg/pph/x4overset2.cc: Make wanted assembly diff.
	* g++.dg/pph/x4overset3.cc: Make passing.
	* g++.dg/pph/x4overset4.cc: Make wanted assembly diff.
	* g++.dg/pph/x6dynarray3.cc: Change xfail signature.

Index: gcc/cp/ChangeLog.pph

2012-01-20   Lawrence Crowl  <crowl@google.com>

	* parser.c (cp_debug_parser_where): Protect against null pointers.
	* name-lookup.c (cxx_binding_make_for_name): New.
	(binding_for_name): Factor construction into the above.
	(modify_binding_for_overload): New.
	(push_overloaded_decl_1): Factor out above function.
	(pph_foreach_on_chain_bl): Add filter parameter.
	(pph_set_identifier_bindings): Likewise.
	(pph_set_chain_identifier_bindings): Likewise.
	(pph_set_chain_namespace_bindings): Likewise.
	(pph_set_namespace_bindings): Likewise.  Correct overloading.
	(pph_set_namespace_namespace_bindings): Add filter parameter in calls.
	(pph_set_global_identifier_bindings): Likewise.


Index: gcc/testsuite/g++.dg/pph/x6dynarray3.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x6dynarray3.cc	(revision 183345)
+++ gcc/testsuite/g++.dg/pph/x6dynarray3.cc	(working copy)
@@ -1,8 +1,6 @@ 
-// { dg-bogus "a0dynarray-dfn1b.hi:8:13: error: no matching function for call to 'operator new" "" { xfail *-*-* } 0 }
 // { dg-bogus "a0dynarray-dfn1b.hi:22:5: error: no suitable 'operator delete" "" { xfail *-*-* } 0 }
-// { dg-bogus "a0dynarray-dfn2b.hi:8:13: error: no matching function for call to 'operator new" "" { xfail *-*-* } 0 }
 // { dg-bogus "a0dynarray-dfn2b.hi:13:9: error: no suitable 'operator delete" "" { xfail *-*-* } 0 }
-// { dg-bogus "a0dynarray-dcl3.hi:11:60: warning: no corresponding deallocation function for 'void. operator new" "" { xfail *-*-* } 0 }
+// { dg-bogus "a0dynarray-dcl3.hi:11:60: error: call of overloaded 'operator new" "" { xfail *-*-* } 0 }
 
 #include "x5dynarray3.h"
 
Index: gcc/testsuite/g++.dg/pph/x4overset1.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4overset1.cc	(revision 183345)
+++ gcc/testsuite/g++.dg/pph/x4overset1.cc	(working copy)
@@ -1,5 +1,3 @@ 
-// pph asm xdiff 56596
-
 #include "x1overset1.h"
 #include "x1overset2.h"
 
Index: gcc/testsuite/g++.dg/pph/x4overset2.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4overset2.cc	(revision 183345)
+++ gcc/testsuite/g++.dg/pph/x4overset2.cc	(working copy)
@@ -1,5 +1,4 @@ 
-// pph asm xdiff 01525
-// wanted 57625
+// pph asm xwant 19882
 // This test produces overload differences because the declaration and
 // call orders are different between pph and textual parsing.
 
Index: gcc/testsuite/g++.dg/pph/x4overset3.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4overset3.cc	(revision 183345)
+++ gcc/testsuite/g++.dg/pph/x4overset3.cc	(working copy)
@@ -1,5 +1,3 @@ 
-// pph asm xdiff 56596
-
 #include "x1overset1.h"
 #include "x1overset2.h"
 #include "x1overset1.h"
Index: gcc/testsuite/g++.dg/pph/x4overset4.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4overset4.cc	(revision 183345)
+++ gcc/testsuite/g++.dg/pph/x4overset4.cc	(working copy)
@@ -1,5 +1,4 @@ 
-// pph asm xdiff 01525
-// wanted 57625
+// pph asm xwant 19882
 // This test produces overload differences because the declaration and
 // call orders are different between pph and textual parsing.
 
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 183345)
+++ gcc/cp/parser.c	(working copy)
@@ -471,12 +471,34 @@  void
 cp_debug_parser_where (FILE *file, cp_parser *parser)
 {
   const size_t window_size = 20;
-  cp_token *token = parser->lexer->next_token;
-  expanded_location eloc = expand_location (token->location);
+  cp_lexer *lexer;
+  cp_token *token;
+  expanded_location eloc;
 
   if (file == NULL)
     file = stderr;
 
+  if (parser == NULL)
+    {
+      fprintf (file, "No parser available.\n");
+      return;
+    }
+
+  lexer = parser->lexer;
+  if (lexer == NULL)
+    {
+      fprintf (file, "No lexer available.\n");
+      return;
+    }
+
+  token = lexer->next_token;
+  if (token == NULL)
+    {
+      fprintf (file, "No token available.\n");
+      return;
+    }
+
+  eloc = expand_location (token->location);
   fprintf (file, "%s:%d:%d ", eloc.file, eloc.line, eloc.column);
   cp_debug_parser_tokens (file, parser, window_size);
 }
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c	(revision 183345)
+++ gcc/cp/name-lookup.c	(working copy)
@@ -2035,19 +2035,12 @@  cp_binding_level_find_binding_for_name (
   return NULL;
 }
 
-/* Always returns a binding for name in scope.  If no binding is
-   found, make a new one.  */
+/* Return an new cxx_binding initialized for a NAME in SCOPE.  */
 
 static cxx_binding *
-binding_for_name (cp_binding_level *scope, tree name)
+cxx_binding_make_for_name (cp_binding_level *scope, tree name)
 {
-  cxx_binding *result;
-
-  result = cp_binding_level_find_binding_for_name (scope, name);
-  if (result)
-    return result;
-  /* Not found, make a new one.  */
-  result = cxx_binding_make (NULL, NULL);
+  cxx_binding *result = cxx_binding_make (NULL, NULL);
   result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
   result->scope = scope;
   result->is_local = false;
@@ -2056,6 +2049,18 @@  binding_for_name (cp_binding_level *scop
   return result;
 }
 
+/* Always returns a binding for name in scope.  If no binding is
+   found, make a new one.  */
+
+static cxx_binding *
+binding_for_name (cp_binding_level *scope, tree name)
+{
+  cxx_binding *result = cp_binding_level_find_binding_for_name (scope, name);
+  if (!result)
+    result = cxx_binding_make_for_name (scope, name);
+  return result;
+}
+
 /* Walk through the bindings associated to the name of FUNCTION,
    and return the first declaration of a function with a
    "C" linkage specification, a.k.a 'extern "C"'.
@@ -2205,6 +2210,29 @@  pushdecl_with_scope (tree x, cp_binding_
   return ret;
 }
 
+static tree
+modify_binding_for_overload (tree decl, tree old, int flags)
+{
+  tree new_binding;
+  if (old || TREE_CODE (decl) == TEMPLATE_DECL
+      /* If it's a using declaration, we always need to build an OVERLOAD,
+	 because it's the only way to remember that the declaration comes
+	 from 'using', and have the lookup behave correctly.  */
+      || (flags & PUSH_USING))
+    {
+      if (old && TREE_CODE (old) != OVERLOAD)
+	new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
+      else
+	new_binding = ovl_cons (decl, old);
+      if (flags & PUSH_USING)
+	OVL_USED (new_binding) = 1;
+    }
+  else
+    /* NAME is not ambiguous.  */
+    new_binding = decl;
+  return new_binding;
+}
+
 
 /* DECL is a FUNCTION_DECL for a non-member function, which may have
    other definitions already in place.  We get around this by making
@@ -2294,22 +2322,7 @@  push_overloaded_decl_1 (tree decl, int f
 	}
     }
 
-  if (old || TREE_CODE (decl) == TEMPLATE_DECL
-      /* If it's a using declaration, we always need to build an OVERLOAD,
-	 because it's the only way to remember that the declaration comes
-	 from 'using', and have the lookup behave correctly.  */
-      || (flags & PUSH_USING))
-    {
-      if (old && TREE_CODE (old) != OVERLOAD)
-	new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
-      else
-	new_binding = ovl_cons (decl, old);
-      if (flags & PUSH_USING)
-	OVL_USED (new_binding) = 1;
-    }
-  else
-    /* NAME is not ambiguous.  */
-    new_binding = decl;
+  new_binding = modify_binding_for_overload (decl, old, flags);
 
   if (doing_global)
     set_namespace_binding (name, current_namespace, new_binding);
@@ -6114,14 +6127,14 @@  pph_debug_binding_inaction (const char *
    with argument BL.  */
 
 static void
-pph_foreach_on_chain_bl (tree first, cp_binding_level *bl,
-			 void (*function)(tree, cp_binding_level *))
+pph_foreach_on_chain_bl (tree first, cp_binding_level *bl, int flags,
+			 void (*function)(tree, cp_binding_level *, int))
 {
   unsigned i;
   tree decl;
   VEC(tree,heap) *w = chain2vec (first);
   FOR_EACH_VEC_ELT_REVERSE (tree, w, i, decl)
-    (*function) (decl, bl);
+    (*function) (decl, bl, flags);
   VEC_free (tree, heap, w);
 }
 
@@ -6129,7 +6142,8 @@  pph_foreach_on_chain_bl (tree first, cp_
 /* Set a identifier binding.  */
 
 static void
-pph_set_identifier_bindings (tree decl, cp_binding_level *bl)
+pph_set_identifier_bindings (tree decl, cp_binding_level *bl,
+			     int flags ATTRIBUTE_UNUSED)
 {
   /* Set the identifier binding for a single decl.  */
   tree id = DECL_NAME (decl);
@@ -6141,48 +6155,88 @@  pph_set_identifier_bindings (tree decl, 
 }
 
 
-/*  Set the identifier bindings for an individual chain.  */
+/* Set the identifier bindings for an individual chain.  */
 
 static void
-pph_set_chain_identifier_bindings (tree first, cp_binding_level *bl)
+pph_set_chain_identifier_bindings (tree first, cp_binding_level *bl, int flags)
 {
-  pph_foreach_on_chain_bl (first, bl, pph_set_identifier_bindings);
+  pph_foreach_on_chain_bl (first, bl, flags, pph_set_identifier_bindings);
+}
+
+
+#if 0
+/* Add an overload to a binding.  */
+
+static tree
+pph_add_overload (tree decl, tree older)
+{
+  tree newer;
+  if (older && TREE_CODE (older) != OVERLOAD)
+    newer = ovl_cons (decl, ovl_cons (older, NULL_TREE));
+  else
+    newer = ovl_cons (decl, older);
+  return newer;
 }
+#endif
 
 
 /*  Set a namespace identifier binding.  */
 
 static void
-pph_set_namespace_bindings (tree decl, cp_binding_level *bl)
+pph_set_namespace_bindings (tree decl, cp_binding_level *bl, int flags)
 {
   /* Set the namespace identifier binding for a single decl.  */
   tree id = DECL_NAME (decl);
   if (id)
     {
-      /* This code plagarizes from set_namespace_binding.
+      /* FIXME pph: This code plagarizes from push_overloaded_decl_1 and
+	 binding_for_name.  It may be incomplete.  */
+      cxx_binding *b = cp_binding_level_find_binding_for_name (bl, id);
+      if (b)
+	{
+	  tree old = b->value;
+	  if (is_overloaded_fn (old))
+	    {
+	      /* We don't overload implicit built-ins.  duplicate_decls()
+		 may fail to merge the decls if the new decl is e.g. a
+		 template function.  */
+              if (TREE_CODE (old) == FUNCTION_DECL
+		  && DECL_ANTICIPATED (old)
+		  && !DECL_HIDDEN_FRIEND_P (old))
+		old = NULL;
+              decl = modify_binding_for_overload (decl, old, flags);
+	    }
+	}
+      else
+	b = cxx_binding_make_for_name (bl, id);
+
+      /* FIXME pph: This code plagarizes from set_namespace_binding.
 	 It has trouble with supplement_binding, methinks.  */
-      /* FIXME pph: we should do more merging here.  */
-      cxx_binding *b = binding_for_name (bl, id);
       if (!b->value)
 	{
 	  b->value = decl;
-	  pph_debug_binding_action ("v-bind", decl);
+	  pph_debug_binding_action ("new bind", decl);
+	}
+      if (TREE_CODE (decl) == OVERLOAD)
+	{
+	  b->value = decl;
+	  pph_debug_binding_action ("ovl bind", decl);
 	}
       else if (TREE_CODE (b->value) == TYPE_DECL &&
     	   TREE_CODE (decl) != TYPE_DECL)
 	{
 	  b->type = b->value;
 	  b->value = decl;
-	  pph_debug_binding_action ("p-bind", decl);
+	  pph_debug_binding_action ("t/v bind", decl);
 	}
       else if (TREE_CODE (b->value) != TYPE_DECL &&
     	   TREE_CODE (decl) == TYPE_DECL)
 	{
 	  b->type = decl;
-	  pph_debug_binding_action ("t-bind", decl);
+	  pph_debug_binding_action ("v/t bind", decl);
 	}
       else
-	pph_debug_binding_inaction ("n-bind", decl);
+	pph_debug_binding_inaction ("not bind", decl);
     }
 }
 
@@ -6190,9 +6244,9 @@  pph_set_namespace_bindings (tree decl, c
 /*  Set the namespace identifier bindings.  */
 
 static void
-pph_set_chain_namespace_bindings (tree first, cp_binding_level *bl)
+pph_set_chain_namespace_bindings (tree first, cp_binding_level *bl, int flags)
 {
-  pph_foreach_on_chain_bl (first, bl, pph_set_namespace_bindings);
+  pph_foreach_on_chain_bl (first, bl, flags, pph_set_namespace_bindings);
 }
 
 
@@ -6234,10 +6288,12 @@  pph_set_namespace_namespace_binding (tre
 static void
 pph_set_namespace_namespace_bindings (cp_binding_level *bl)
 {
-  pph_set_chain_namespace_bindings (bl->names, bl);
-  pph_set_chain_namespace_bindings (bl->namespaces, bl);
-  pph_set_chain_namespace_bindings (bl->usings, bl);
-  /* FIXME pph: pph_set_chain_namespace_bindings (bl->using_directives, bl);  */
+  pph_set_chain_namespace_bindings (bl->names, bl, 0);
+  pph_set_chain_namespace_bindings (bl->namespaces, bl, 0);
+  pph_set_chain_namespace_bindings (bl->usings, bl, PUSH_USING);
+  /* FIXME pph:
+  pph_set_chain_namespace_bindings (bl->using_directives, bl, 0);
+  */
   pph_foreach_on_chain (bl->namespaces, pph_set_namespace_namespace_binding);
 }
 
@@ -6249,10 +6305,10 @@  void
 pph_set_global_identifier_bindings (void)
 {
   cp_binding_level *bl = scope_chain->bindings;
-  pph_set_chain_identifier_bindings (bl->names, bl);
-  pph_set_chain_identifier_bindings (bl->namespaces, bl);
-  pph_set_chain_identifier_bindings (bl->usings, bl);
-  pph_set_chain_identifier_bindings (bl->using_directives, bl);
+  pph_set_chain_identifier_bindings (bl->names, bl, 0);
+  pph_set_chain_identifier_bindings (bl->namespaces, bl, 0);
+  pph_set_chain_identifier_bindings (bl->usings, bl, PUSH_USING);
+  pph_set_chain_identifier_bindings (bl->using_directives, bl, 0);
   pph_set_namespace_namespace_bindings (bl);
 }