diff mbox

C++ PATCH for c++/44870 (wrong overload resolution error in template)

Message ID 4DE52DE3.1060302@redhat.com
State New
Headers show

Commit Message

Jason Merrill May 31, 2011, 6:05 p.m. UTC
lvalue_kind has tried to give an approximate answer for value category 
in templates; in the past, it was OK to say that an arbitrary expression 
was an lvalue, as the only effect would be that errors we could have 
given at template definition time would be delayed until instantiation, 
which is still conforming.  But now that we have rvalue references that 
can't bind to lvalues, it has become important to get the right answer. 
  So this patch makes us look through NON_DEPENDENT_EXPR at the actual 
underlying tree structure.  We need to add a couple more cases for 
lvalue expressions that only appear in templates, and handle overloaded 
functions/operators that return class type; I will not be surprised if 
there are other cases I didn't think of, but we are still in stage 1... :)

Tested x86_64-pc-linux-gnu, applying to trunk.

Comments

H.J. Lu June 1, 2011, 1:47 p.m. UTC | #1
On Tue, May 31, 2011 at 11:05 AM, Jason Merrill <jason@redhat.com> wrote:
> lvalue_kind has tried to give an approximate answer for value category in
> templates; in the past, it was OK to say that an arbitrary expression was an
> lvalue, as the only effect would be that errors we could have given at
> template definition time would be delayed until instantiation, which is
> still conforming.  But now that we have rvalue references that can't bind to
> lvalues, it has become important to get the right answer.  So this patch
> makes us look through NON_DEPENDENT_EXPR at the actual underlying tree
> structure.  We need to add a couple more cases for lvalue expressions that
> only appear in templates, and handle overloaded functions/operators that
> return class type; I will not be surprised if there are other cases I didn't
> think of, but we are still in stage 1... :)
>
> Tested x86_64-pc-linux-gnu, applying to trunk.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49253
diff mbox

Patch

commit 319a7842876443fedd284888a5481f4aa58b7afe
Author: Jason Merrill <jason@redhat.com>
Date:   Sat May 28 22:41:42 2011 -0400

    	PR c++/44870
    	* tree.c (lvalue_kind): Recurse on NON_DEPENDENT_EXPR.  Handle
    	ARROW_EXPR, TYPEID_EXPR, and arbitrary class-valued expressions.
    	(build_min_non_dep): Preserve reference refs.
    	(build_min_non_dep_call_vec): Likewise

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c93110b..11e195e 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -139,6 +139,7 @@  lvalue_kind (const_tree ref)
 	  && DECL_IN_AGGR_P (ref))
 	return clk_none;
     case INDIRECT_REF:
+    case ARROW_EXPR:
     case ARRAY_REF:
     case PARM_DECL:
     case RESULT_DECL:
@@ -170,6 +171,7 @@  lvalue_kind (const_tree ref)
       break;
 
     case MODIFY_EXPR:
+    case TYPEID_EXPR:
       return clk_ordinary;
 
     case COMPOUND_EXPR:
@@ -182,7 +184,9 @@  lvalue_kind (const_tree ref)
       return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none);
 
     case CALL_EXPR:
-      /* Any class-valued call would be wrapped in a TARGET_EXPR.  */
+      /* We can see calls outside of TARGET_EXPR in templates.  */
+      if (CLASS_TYPE_P (TREE_TYPE (ref)))
+	return clk_class;
       return clk_none;
 
     case FUNCTION_DECL:
@@ -199,14 +203,16 @@  lvalue_kind (const_tree ref)
       return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
 
     case NON_DEPENDENT_EXPR:
-      /* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
-	 things like "&E" where "E" is an expression with a
-	 non-dependent type work. It is safe to be lenient because an
-	 error will be issued when the template is instantiated if "E"
-	 is not an lvalue.  */
-      return clk_ordinary;
+      /* We used to just return clk_ordinary for NON_DEPENDENT_EXPR because
+	 it was safe enough for C++98, but in C++0x lvalues don't bind to
+	 rvalue references, so we get bogus errors (c++/44870).  */
+      return lvalue_kind (TREE_OPERAND (ref, 0));
 
     default:
+      if (!TREE_TYPE (ref))
+	return clk_none;
+      if (CLASS_TYPE_P (TREE_TYPE (ref)))
+	return clk_class;
       break;
     }
 
@@ -1985,6 +1991,9 @@  build_min_non_dep (enum tree_code code, tree non_dep, ...)
 
   va_start (p, non_dep);
 
+  if (REFERENCE_REF_P (non_dep))
+    non_dep = TREE_OPERAND (non_dep, 0);
+
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
   TREE_TYPE (t) = TREE_TYPE (non_dep);
@@ -2002,7 +2011,7 @@  build_min_non_dep (enum tree_code code, tree non_dep, ...)
     COMPOUND_EXPR_OVERLOADED (t) = 1;
 
   va_end (p);
-  return t;
+  return convert_from_reference (t);
 }
 
 /* Similar to `build_nt_call_vec', but for template definitions of
@@ -2013,9 +2022,11 @@  tree
 build_min_non_dep_call_vec (tree non_dep, tree fn, VEC(tree,gc) *argvec)
 {
   tree t = build_nt_call_vec (fn, argvec);
+  if (REFERENCE_REF_P (non_dep))
+    non_dep = TREE_OPERAND (non_dep, 0);
   TREE_TYPE (t) = TREE_TYPE (non_dep);
   TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
-  return t;
+  return convert_from_reference (t);
 }
 
 tree
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-template1.C b/gcc/testsuite/g++.dg/cpp0x/rv-template1.C
new file mode 100644
index 0000000..11f53bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-template1.C
@@ -0,0 +1,11 @@ 
+// PR c++/44870
+// { dg-options -std=c++0x }
+
+void foo(int&& data);
+
+template <typename T>
+void bar(T t)
+{ foo(int()); }
+
+void baz()
+{ bar(0); }