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++ Patch] 28705 & koenig lookup


This patch fixes bug 28705, but it impacts koenig lookup and DR 218. The actual ICE reported in 28705 is somewhat incidental. Here's the non-template version of the testcase
namespace N {
struct A { A(A*); };
}
void g() {
N::A *p;
(void)A(p); // This line
}


Koenig lookup searches N and finds N::A. G++ adds this to the koenig overload set (and will only therefore not allow other overloads into the set). Unfortunately we then go off the rails and don't treat the marked line as a function-style conversion operator (it appears we've never done that right, so this is not a regression). The STD doesn't seem to allow us to treat koenig lookup this way. The koenig lookup wording is somewhat vague, but function call and conversion operators are described as distinct grammar elements, and it would seem odd that one could morph into the other without some explicit wording on the matter. (What's happening is that Koenig lookup provides a way for the overload set to consist of more than simply functions, and that wasn't noticed in the std.)

Now, if there is some function 'A' also in play, what should we do? G++ would currently reject the program as ill formed (it only allows Koenig lookup to find a function overload set, or a single non-function entity). The EDG frontend appears to ignore non-function entities during koenig lookup (and therefore would allow the program).

This patch changes G++ to ignore non-function non-variable entities during koenig lookup. This makes G++ accept strictly more programs than it did before. I don't think it causes G++ to reject a program it previously accepted.

It does not make G++ match EDG's behaviour exactly, because G++ accepts function objects during koenig lookup. I don't want to change that behaviour without a ruling on DR 218 from the committee.

I've not committed this patch, but have tested it on i686-pc-linux-gnu.

Thoughts?

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2006-08-28  Nathan Sidwell  <nathan@codesourcery.com>

	cp/
	PR c++/28705
	* semantics.c (finish_call_expr): Add assert.
	* name-lookup.c (add_function): Only allow functions and objects
	to add to the koenig set.

	testsuite/
	PR c++/28705
	* g++.dg/lookup/koenig5.C: New.
	* g++.dg/template/crash56.C: New.

Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 116467)
+++ cp/semantics.c	(working copy)
@@ -1758,6 +1758,8 @@ finish_call_expr (tree fn, tree args, bo
   orig_fn = fn;
   orig_args = args;
 
+  gcc_assert (!TYPE_P (fn));
+  
   if (processing_template_decl)
     {
       if (type_dependent_expression_p (fn)
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 116467)
+++ cp/name-lookup.c	(working copy)
@@ -4237,28 +4237,39 @@ add_function (struct arg_lookup *k, tree
      assume that the number of duplicates will be small compared to the
      total number of functions being compared, which should usually be the
      case.  */
-
-  /* We must find only functions, or exactly one non-function.  */
-  if (!k->functions)
+  bool fn_is_var = TREE_CODE (fn) == VAR_DECL;
+  
+  if (!is_overloaded_fn (fn) && !fn_is_var)
+    /* Ignore non-function, non-variables.  */
+    return false;
+  else if (!k->functions)
     k->functions = fn;
-  else if (fn == k->functions)
-    ;
-  else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
-    k->functions = build_overload (fn, k->functions);
-  else
+  else if (fn != k->functions)
     {
-      tree f1 = OVL_CURRENT (k->functions);
-      tree f2 = fn;
-      if (is_overloaded_fn (f1))
-	{
-	  fn = f1; f1 = f2; f2 = fn;
-	}
-      error ("%q+D is not a function,", f1);
-      error ("  conflict with %q+D", f2);
-      error ("  in call to %qD", k->name);
-      return true;
-    }
+      bool have_var = TREE_CODE (k->functions) == VAR_DECL;
+
+      if (!have_var && !fn_is_var)
+	k->functions = build_overload (fn, k->functions);
+      else
+	{
+	  tree f1 = k->functions;
 
+	  if (!have_var)
+	    f1 = OVL_CURRENT (f1);
+	  else
+	    {
+	      tree t = f1;
+	      f1 = fn;
+	      fn = t;
+	      have_var = false;
+	    }
+	  
+	  error ("%q+D is a variable", fn);
+	  error ("  and conflicts with %q+D", f1);
+	  error ("  in call to %qD", k->name);
+	}
+    }
+  
   return false;
 }
 
Index: testsuite/g++.dg/lookup/koenig5.C
===================================================================
--- testsuite/g++.dg/lookup/koenig5.C	(revision 0)
+++ testsuite/g++.dg/lookup/koenig5.C	(revision 0)
@@ -0,0 +1,46 @@
+// Koenig lookup is not defined as intended in the std.  DR 218 gives
+// an indication of what is meant.
+
+
+// Copyright (C) 2006 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 27 Aug 2006 <nathan@codesourcery.com>
+
+namespace N
+{
+  struct A {};
+  void One (...);
+  void (*Two) (...);  // { dg-error "a variable" "" }
+  namespace Three {}
+}
+
+namespace M
+{
+  struct B {};
+  struct One {};
+  void (*Two) (...);  // { dg-error "conflicts with" "" }
+  void Three (...);
+}
+
+namespace O 
+{
+  struct C {};
+  void Two (...); // { dg-error "conflicts with" "" }
+}
+  
+void g (N::A *a, M::B *b, O::C *c)
+{
+  One (a); // ok
+  One (b); // { dg-error "not declared" "" }
+  One (a, b); // ok
+
+  Two (a); // ok
+  Two (a, a); // ok
+  Two (b); // ok
+  Two (c); // ok
+  Two (a, b); // { dg-error "in call to" "" }
+  Two (a, c); // { dg-error "in call to" "" }
+  
+  Three (a); // { dg-error "not declared" "" }
+  Three (b); // ok
+  Three (a, b); // ok
+}
Index: testsuite/g++.dg/template/crash56.C
===================================================================
--- testsuite/g++.dg/template/crash56.C	(revision 0)
+++ testsuite/g++.dg/template/crash56.C	(revision 0)
@@ -0,0 +1,15 @@
+// Origin: Wolfgang Bangerth <bangerth@dealii.org>
+
+// PR c++/28705
+
+namespace N
+{
+  struct A { A(A*); };
+  void foo(const A &);
+}
+
+template<typename T> void g()
+{
+  N::A *p;
+  (void) A(p); // { dg-error "" "" }
+}

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