PR20227: materialize a temporary when dynamic_casting a class prvalue to a
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 8 Jul 2014 17:25:14 +0000 (17:25 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 8 Jul 2014 17:25:14 +0000 (17:25 +0000)
reference type.

llvm-svn: 212551

clang/lib/Sema/SemaCast.cpp
clang/test/CodeGenCXX/temporaries.cpp

index 7fa3068..ae5436c 100644 (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,
index 2a8cb3f..37286c2 100644 (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();