diff mbox

[C++] PR 57599

Message ID 51B91718.2010900@oracle.com
State New
Headers show

Commit Message

Paolo Carlini June 13, 2013, 12:49 a.m. UTC
Hi,

this dynamic_cast bug, which just came in, notices that in the simple 
case of static conversion we forget to perform the cv-qualifier 
conversions. It seems to me that we are missing a build_nop.

I extended quite a bit the testcase, to references too, because at some 
point I got those wrong ;)

Tested x86_64-linux.

Thanks,
Paolo.

//////////////////////////
/cp
2013-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/57599
	* rtti.c (build_dynamic_cast_1): In case of static conversion,
	remember to perform the cv-qualifier conversions.

/testsuite
2013-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/57599
	* g++.dg/rtti/dyncast6.C: New.

Comments

Jason Merrill June 13, 2013, 1:51 p.m. UTC | #1
On 06/12/2013 08:49 PM, Paolo Carlini wrote:
> +	/* Add any qualifier conversions.  */
> +	return build_nop (type, expr);

For a cast to reference type, this will produce an rvalue rather than an 
lvalue.

Perhaps we should hand off to build_static_cast in the case described by 
the comment, rather than duplicate the logic.

Jason
Paolo Carlini June 13, 2013, 2:03 p.m. UTC | #2
Hi,

Jason Merrill <jason@redhat.com> ha scritto:

>On 06/12/2013 08:49 PM, Paolo Carlini wrote:
>> +	/* Add any qualifier conversions.  */
>> +	return build_nop (type, expr);
>
>For a cast to reference type, this will produce an rvalue rather than
>an lvalue.

Ah, thanks a lot for the clarification. Admittedly, I still find the whole area of nops rather obscure.

>Perhaps we should hand off to build_static_cast in the case described
>by
>the comment, rather than duplicate the logic.

Thanks for hint, I'll try to come up with another try over the next day or so.

Thanks again,
Paolo
diff mbox

Patch

Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 200041)
+++ cp/rtti.c	(working copy)
@@ -633,7 +633,8 @@  build_dynamic_cast_1 (tree type, tree expr, tsubst
 				binfo, 0, complain);
 	if (TYPE_PTR_P (exprtype))
 	  expr = rvalue (expr);
-	return expr;
+	/* Add any qualifier conversions.  */
+	return build_nop (type, expr);
       }
   }
 
Index: testsuite/g++.dg/rtti/dyncast6.C
===================================================================
--- testsuite/g++.dg/rtti/dyncast6.C	(revision 0)
+++ testsuite/g++.dg/rtti/dyncast6.C	(working copy)
@@ -0,0 +1,59 @@ 
+// PR c++/57599
+
+class A { };
+
+class B : public A { };
+
+void p()
+{
+  B* b;
+
+  A* a1;
+  a1 = dynamic_cast<A*>(b);
+  a1 = dynamic_cast<const A*>(b);          // { dg-error "invalid" }
+  a1 = dynamic_cast<volatile A*>(b);       // { dg-error "invalid" }
+  a1 = dynamic_cast<const volatile A*>(b); // { dg-error "invalid" }
+
+  const A* a2;
+  a2 = dynamic_cast<A*>(b);
+  a2 = dynamic_cast<const A*>(b);
+  a2 = dynamic_cast<volatile A*>(b);       // { dg-error "invalid" }
+  a2 = dynamic_cast<const volatile A*>(b); // { dg-error "invalid" }
+
+  volatile A* a3;
+  a3 = dynamic_cast<A*>(b);
+  a3 = dynamic_cast<const A*>(b);          // { dg-error "invalid" }
+  a3 = dynamic_cast<volatile A*>(b);
+  a3 = dynamic_cast<const volatile A*>(b); // { dg-error "invalid" }
+
+  const volatile A* a4;
+  a4 = dynamic_cast<A*>(b);
+  a4 = dynamic_cast<const A*>(b);
+  a4 = dynamic_cast<volatile A*>(b);
+  a4 = dynamic_cast<const volatile A*>(b);
+}
+
+void r()
+{
+  B b;
+
+  A& a1 = dynamic_cast<A&>(b);
+  A& a2 = dynamic_cast<const A&>(b);                // { dg-error "invalid" }
+  A& a3 = dynamic_cast<volatile A&>(b);             // { dg-error "invalid" }
+  A& a4 = dynamic_cast<const volatile A&>(b);       // { dg-error "invalid" }
+
+  const A& ca1 = dynamic_cast<A&>(b);
+  const A& ca2 = dynamic_cast<const A&>(b);
+  const A& ca3 = dynamic_cast<volatile A&>(b);       // { dg-error "invalid" }
+  const A& ca4 = dynamic_cast<const volatile A&>(b); // { dg-error "invalid" }
+
+  volatile A& va1 = dynamic_cast<A&>(b);
+  volatile A& va2 = dynamic_cast<const A&>(b);       // { dg-error "invalid" }
+  volatile A& va3 = dynamic_cast<volatile A&>(b);
+  volatile A& va4 = dynamic_cast<const volatile A&>(b);// { dg-error "invalid" }
+
+  const volatile A& cva1 = dynamic_cast<A&>(b);
+  const volatile A& cva2 = dynamic_cast<const A&>(b);
+  const volatile A& cva3 = dynamic_cast<volatile A&>(b);
+  const volatile A& cva4 = dynamic_cast<const volatile A&>(b);
+}