OSDN Git Service

PR c++/50835
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 Nov 2011 17:10:09 +0000 (17:10 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 Nov 2011 17:10:09 +0000 (17:10 +0000)
* typeck.c (build_x_conditional_expr): Preserve lvalue/xvalueness.
* tree.c (lvalue_kind) [NON_DEPENDENT_EXPR]: Return clk_ordinary
in C++98.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181174 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/lvalue2.C [new file with mode: 0644]

index 2f3bf21..58241a8 100644 (file)
@@ -1,3 +1,10 @@
+2011-11-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50835
+       * typeck.c (build_x_conditional_expr): Preserve lvalue/xvalueness.
+       * tree.c (lvalue_kind) [NON_DEPENDENT_EXPR]: Return clk_ordinary
+       in C++98.
+
 2011-11-08  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/51010
index dc9fc95..841029f 100644 (file)
@@ -203,10 +203,13 @@ lvalue_kind (const_tree ref)
       return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
 
     case NON_DEPENDENT_EXPR:
-      /* 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));
+      /* We just return clk_ordinary for NON_DEPENDENT_EXPR in C++98, but
+        in C++11 lvalues don't bind to rvalue references, so we need to
+        work harder to avoid bogus errors (c++/44870).  */
+      if (cxx_dialect < cxx0x)
+       return clk_ordinary;
+      else
+       return lvalue_kind (TREE_OPERAND (ref, 0));
 
     default:
       if (!TREE_TYPE (ref))
index 386f3b8..aed2891 100644 (file)
@@ -5498,8 +5498,16 @@ build_x_conditional_expr (tree ifexp, tree op1, tree op2,
 
   expr = build_conditional_expr (ifexp, op1, op2, complain);
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep (COND_EXPR, expr,
-                             orig_ifexp, orig_op1, orig_op2);
+    {
+      tree min = build_min_non_dep (COND_EXPR, expr,
+                                   orig_ifexp, orig_op1, orig_op2);
+      /* Remember that the result is an lvalue or xvalue.  */
+      if (lvalue_or_rvalue_with_address_p (expr)
+         && !lvalue_or_rvalue_with_address_p (min))
+       TREE_TYPE (min) = cp_build_reference_type (TREE_TYPE (min),
+                                                  !real_lvalue_p (expr));
+      expr = convert_from_reference (min);
+    }
   return expr;
 }
 \f
index 0cc8b6e..b0cbbb6 100644 (file)
@@ -1,3 +1,8 @@
+2011-10-23  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50835
+       * g++.dg/template/lvalue2.C: New.
+
 2011-11-08  Michael Matz  <matz@suse.de>
 
        * gcc.dg/tree-ssa/20031015-1.c: Adjust.
diff --git a/gcc/testsuite/g++.dg/template/lvalue2.C b/gcc/testsuite/g++.dg/template/lvalue2.C
new file mode 100644 (file)
index 0000000..e9074aa
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/50835
+
+struct A {};
+
+struct B
+{
+  explicit B(A &);
+  operator A&() const;
+};
+
+void should_be_lvalue(A&);
+
+template <typename>
+void f()
+{
+    A v;
+    should_be_lvalue(true ? B(v) : v);
+}