From: Richard Smith Date: Tue, 8 Jul 2014 17:25:14 +0000 (+0000) Subject: PR20227: materialize a temporary when dynamic_casting a class prvalue to a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0d54d89118a9afa3d6b64b0098a16ebe4a916215;p=clang PR20227: materialize a temporary when dynamic_casting a class prvalue to a reference type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212551 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 7fa30680f5..ae5436cf41 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -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, diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index 2a8cb3f408..37286c2b15 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -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{}); + // CHECK: @_ZGRN7PR202271aE_ = private global + + B &&b = dynamic_cast(dynamic_cast(C{})); + // CHECK: @_ZGRN7PR202271bE_ = private global + + B &&c = static_cast(static_cast(C{})); + // CHECK: @_ZGRN7PR202271cE_ = private global +} + struct A { A(); ~A();