This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[c++] fix 2 overload bugs


I've applied this patch to fix 2 overloading bugs.

*) with ms-extensions, a plain 'foo' or 'T::foo' can produce a pointer to member function. We failed in two ways when there is only one candidate function. firstly an assert failed, because the function is not truely overloaded. Secondly, we fell into memory corruption because we copied the DECL node, leading to weird failures later on (in the particular testcase and environment I had, this was an incorrect mangling when -g was not also used). Removing the copy_node led me to bug 2.

*) instantiate_type used to deal with many many tree nodes, and these relied on the copy_node so they could bash an rhs copy. All but compound_expr was removed by Mark some time ago. However, we shouldn't be looking inside compound_exprs either -- those need a definite type too. Previously when I looked at this (and created one of the two changed testcases), I thought one could defer determining the type of a COMPOUND_EXPR, and a COND_EXPR. I now think I was wrong.

[13.4] talks about when the address of overloaded function is resolved. It talks about the target context, not really mentioning the source context. But wording pretty much suggests the source is 'func' or 'T::func' with optional '&' prefix and possible template-id bits. [13.6] discusses builtin operators. It does mention a ficticious 'operator?' implying that its type must be resolved during overload resolution. Strangely that section doesn't mention a builtin 'operator,'. That just seems like an omission. No where else can I see words that suggest 'operator,' can be overloaded and defer type determination. FWIW the edg frontend rejects such deferred resolution.

so, I added a check that the RHS was a known type when building a compound expr, and adjusted the testcases.

built & tested on i686-pc-linux-gnu.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery

2009-05-05  Nathan Sidwell  <nathan@codesourcery.com>

	cp/
	* typeck.c (cp_build_compound_expr): Require RHS to have a known
	type.
	* class.c (resolve_address_of_overloaded_function): Use
	OVL_CURRENT for error message.
	(instantiate_type): Forbid COMPOUND_EXPRs and remove code dealing
	with them.  Do not copy the node.

	testsuite/
	* g++.old-deja/g++.other/overload11.C: Adjust expected errors.
	* g++.dg/template/overload9.C: Likewise.
	* g++.dg/ext/ms-1.C: New.

Index: testsuite/g++.old-deja/g++.other/overload11.C
===================================================================
--- testsuite/g++.old-deja/g++.other/overload11.C	(revision 146966)
+++ testsuite/g++.old-deja/g++.other/overload11.C	(working copy)
@@ -54,11 +54,10 @@ int main (int argc, char **argv)
   
   ptr = (ovl);              // ok
   ptr = (&ovl);             // ok
-  // 13.4 indicates these are ok.
-  ptr = (0, ovl);           // ok { dg-bogus "" "" { xfail *-*-* } }
-  ptr = (0, &ovl);          // ok { dg-bogus "" "" { xfail *-*-* } }
-  ptr = (argc ? ovl : ovl); // ok { dg-bogus "" "" { xfail *-*-* } }
-  ptr = (argc ? &ovl : &ovl);// ok { dg-bogus "" "" { xfail *-*-* } }
+  ptr = (0, ovl);           // ok { dg-error "no context" }
+  ptr = (0, &ovl);          // ok { dg-error "no context" }
+  ptr = (argc ? ovl : ovl); // ok { dg-error "no context" }
+  ptr = (argc ? &ovl : &ovl);// ok { dg-error "no context" }
   
   vptr = (ovl);              // { dg-error "" } no matching candidates
   vptr = (&ovl);             // { dg-error "" } no matching candidates
Index: testsuite/g++.dg/template/overload9.C
===================================================================
--- testsuite/g++.dg/template/overload9.C	(revision 146966)
+++ testsuite/g++.dg/template/overload9.C	(working copy)
@@ -7,12 +7,12 @@ template <typename T> A<T>& operator<<(A
 template <typename T>
 struct A 
 {
-  A<T>& operator<<(A<T>& (*)(A<T>&)); // { dg-message "candidate" }
+  A<T>& operator<<(A<T>& (*)(A<T>&));
 };
 
 template <typename T> A<T>& foo(A<T>&);
 extern A<char> c;
 
 int main () {
-  c << (1, foo); // { dg-error "no match" }
+  c << (1, foo); // { dg-error "no context" }
 }
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 146966)
+++ cp/typeck.c	(working copy)
@@ -5034,6 +5034,12 @@ cp_build_compound_expr (tree lhs, tree r
       return rhs;
     }
 
+  if (type_unknown_p (rhs))
+    {
+      error ("no context to resolve type of %qE", rhs);
+      return error_mark_node;
+    }
+  
   return build2 (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs);
 }
 
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 146966)
+++ cp/class.c	(working copy)
@@ -6147,7 +6147,7 @@ resolve_address_of_overloaded_function (
       if (flags & tf_error)
 	{
 	  error ("no matches converting function %qD to type %q#T",
-		 DECL_NAME (OVL_FUNCTION (overload)),
+		 DECL_NAME (OVL_CURRENT (overload)),
 		 target_type);
 
 	  /* print_candidates expects a chain with the functions in
@@ -6310,13 +6310,8 @@ instantiate_type (tree lhstype, tree rhs
      dependent on overload resolution.  */
   gcc_assert (TREE_CODE (rhs) == ADDR_EXPR
 	      || TREE_CODE (rhs) == COMPONENT_REF
-	      || TREE_CODE (rhs) == COMPOUND_EXPR
-	      || really_overloaded_fn (rhs));
-
-  /* We don't overwrite rhs if it is an overloaded function.
-     Copying it would destroy the tree link.  */
-  if (TREE_CODE (rhs) != OVERLOAD)
-    rhs = copy_node (rhs);
+	      || really_overloaded_fn (rhs)
+	      || (flag_ms_extensions && TREE_CODE (rhs) == FUNCTION_DECL));
 
   /* This should really only be used when attempting to distinguish
      what sort of a pointer to function we have.  For now, any
@@ -6368,19 +6363,6 @@ instantiate_type (tree lhstype, tree rhs
 						/*explicit_targs=*/NULL_TREE,
 						access_path);
 
-    case COMPOUND_EXPR:
-      TREE_OPERAND (rhs, 0)
-	= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
-      if (TREE_OPERAND (rhs, 0) == error_mark_node)
-	return error_mark_node;
-      TREE_OPERAND (rhs, 1)
-	= instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
-      if (TREE_OPERAND (rhs, 1) == error_mark_node)
-	return error_mark_node;
-
-      TREE_TYPE (rhs) = lhstype;
-      return rhs;
-
     case ADDR_EXPR:
     {
       if (PTRMEM_OK_P (rhs))
Index: testsuite/g++.dg/ext/ms-1.C
===================================================================
--- testsuite/g++.dg/ext/ms-1.C	(revision 0)
+++ testsuite/g++.dg/ext/ms-1.C	(revision 0)
@@ -0,0 +1,17 @@
+
+// MS allows more things to be pointers to member functions
+// { dg-options "-fms-extensions" }
+
+struct X
+{
+  void Foo (X *);
+  void Bar ();
+};
+
+void Quux (void (X::*) ());
+
+void X::Foo (X *ptr)  // { dg-message "candidates" }
+{
+  Quux (Foo); // { dg-error "no matches" }
+  Quux (Bar);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]