Patchwork C++ PATCH for c++/47851 (type mismatch between decltype and not)

login
register
mail settings
Submitter Jason Merrill
Date March 1, 2011, 10:42 p.m.
Message ID <4D6D7664.5080508@redhat.com>
Download mbox | patch
Permalink /patch/84997/
State New
Headers show

Comments

Jason Merrill - March 1, 2011, 10:42 p.m.
standard_conversion, when asked for a conversion from Type& to const 
Type, was returning a conversion to non-const Type.  So when fold 
stripped the COND_EXPR, operand 1 had a different type from the 
COND_EXPR as a whole, and so we got surprising results.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit e8f22a9b647de51facd637a4b9798fb76ad527d1
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Mar 1 17:02:50 2011 -0500

    	PR c++/47851
    	* call.c (standard_conversion): Provide requested cv-quals on
    	class rvalue conversion.

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8dccbbe..a297f53 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -850,6 +850,7 @@  standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
   enum tree_code fcode, tcode;
   conversion *conv;
   bool fromref = false;
+  tree qualified_to;
 
   to = non_reference (to);
   if (TREE_CODE (from) == REFERENCE_TYPE)
@@ -857,6 +858,7 @@  standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
       fromref = true;
       from = TREE_TYPE (from);
     }
+  qualified_to = to;
   to = strip_top_quals (to);
   from = strip_top_quals (from);
 
@@ -918,7 +920,11 @@  standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
     }
 
   if (same_type_p (from, to))
-    return conv;
+    {
+      if (CLASS_TYPE_P (to) && conv->kind == ck_rvalue)
+	conv->type = qualified_to;
+      return conv;
+    }
 
   /* [conv.ptr]
      A null pointer constant can be converted to a pointer type; ... A
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype25.C b/gcc/testsuite/g++.dg/cpp0x/decltype25.C
new file mode 100644
index 0000000..c9559f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype25.C
@@ -0,0 +1,20 @@ 
+// PR c++/47851
+// { dg-options -std=c++0x }
+
+struct Type {
+  void display_type();
+  void display_type() const { }
+};
+
+typedef Type const ConstType;
+
+struct ConvertibleToType {
+    operator Type&() { return *reinterpret_cast<Type*>(this); }
+};
+
+int main ()
+{
+  // Both lines should call the const variant.
+  (true ? ConvertibleToType() : ConstType()).display_type();
+  decltype((true ? ConvertibleToType() : ConstType()))().display_type();
+}