PR20227: materialize a temporary when dynamic_casting a class prvalue to a

reference type.

llvm-svn: 212551
This commit is contained in:
Richard Smith 2014-07-08 17:25:14 +00:00
parent 91e4ba2f88
commit 1133085461
2 changed files with 24 additions and 1 deletions

View File

@ -600,6 +600,11 @@ void CastOperation::CheckDynamicCast() {
}
SrcPointee = SrcType;
} else {
// If we're dynamic_casting from a prvalue to an rvalue reference, we need
// to materialize the prvalue before we bind the reference to it.
if (SrcExpr.get()->isRValue())
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
SrcType, SrcExpr.get(), /*IsLValueReference*/false);
SrcPointee = SrcType;
}
@ -648,7 +653,7 @@ void CastOperation::CheckDynamicCast() {
SrcExpr = ExprError();
return;
}
Kind = CK_DerivedToBase;
// If we are casting to or through a virtual base class, we need a
@ -1156,6 +1161,9 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
QualType DestPointee = DestReference->getPointeeType();
// FIXME: If the source is a prvalue, we should issue a warning (because the
// cast always has undefined behavior), and for AST consistency, we should
// materialize a temporary.
return TryStaticDowncast(Self,
Self.Context.getCanonicalType(SrcExpr->getType()),
Self.Context.getCanonicalType(DestPointee), CStyle,

View File

@ -27,6 +27,21 @@ namespace PR16263 {
// CHECK: @_ZN7PR162631uE = constant i32* {{.*}} @_ZGRN7PR162631uE_ {{.*}} 12
}
namespace PR20227 {
struct A { ~A(); };
struct B { virtual ~B(); };
struct C : B {};
A &&a = dynamic_cast<A&&>(A{});
// CHECK: @_ZGRN7PR202271aE_ = private global
B &&b = dynamic_cast<C&&>(dynamic_cast<B&&>(C{}));
// CHECK: @_ZGRN7PR202271bE_ = private global
B &&c = static_cast<C&&>(static_cast<B&&>(C{}));
// CHECK: @_ZGRN7PR202271cE_ = private global
}
struct A {
A();
~A();