]> granicus.if.org Git - clang/commitdiff
When performing a glvalue-to-xvalue static_cast that involves a
authorDouglas Gregor <dgregor@apple.com>
Tue, 25 Jan 2011 16:13:26 +0000 (16:13 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 25 Jan 2011 16:13:26 +0000 (16:13 +0000)
derived-to-base conversion, set the cast kind and base path
appropriately.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124189 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaCXXCast.cpp
test/CodeGenCXX/rvalue-references.cpp [new file with mode: 0644]

index 075deda4dd9438a28ff82a44cabd19bca551a3b1..3a9ad5ff7f6d32a5a3b4f6c8e4712555f2284d64 100644 (file)
@@ -78,7 +78,9 @@ static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType);
 // %1: Source Type
 // %2: Destination Type
 static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
-                                           QualType DestType, unsigned &msg);
+                                           QualType DestType, CastKind &Kind,
+                                           CXXCastPath &BasePath,
+                                           unsigned &msg);
 static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
                                                QualType DestType, bool CStyle,
                                                const SourceRange &OpRange,
@@ -581,11 +583,9 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
   // C++0x [expr.static.cast]p3: 
   //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
   //   T2" if "cv2 T2" is reference-compatible with "cv1 T1".
-  tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg);
-  if (tcr != TC_NotApplicable) {
-    Kind = CK_NoOp;
+  tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, Kind, BasePath, msg);
+  if (tcr != TC_NotApplicable)
     return tcr;
-  }
 
   // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
   //   [...] if the declaration "T t(e);" is well-formed, [...].
@@ -695,7 +695,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
 /// Tests whether a conversion according to N2844 is valid.
 TryCastResult
 TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
-                      unsigned &msg) {
+                      CastKind &Kind, CXXCastPath &BasePath, unsigned &msg) {
   // C++0x [expr.static.cast]p3:
   //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to 
   //   cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
@@ -719,6 +719,17 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
     return TC_Failed;
   }
 
+  if (DerivedToBase) {
+    Kind = CK_DerivedToBase;
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/true);
+    if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths))
+      return TC_NotApplicable;
+  
+    Self.BuildBasePathArray(Paths, BasePath);
+  } else
+    Kind = CK_NoOp;
+  
   return TC_Success;
 }
 
diff --git a/test/CodeGenCXX/rvalue-references.cpp b/test/CodeGenCXX/rvalue-references.cpp
new file mode 100644 (file)
index 0000000..693e143
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
+
+
+struct Spacer { int x; };
+struct A { double array[2]; };
+struct B : Spacer, A { };
+
+B &getB();
+
+// CHECK: define %struct.A* @_Z4getAv()
+// CHECK: call %struct.B* @_Z4getBv()
+// CHECK-NEXT: bitcast %struct.B*
+// CHECK-NEXT: getelementptr i8*
+// CHECK-NEXT: bitcast i8* {{.*}} to %struct.A*
+// CHECK-NEXT: ret %struct.A*
+A &&getA() { return static_cast<A&&>(getB()); }
+
+int &getIntLValue();
+int &&getIntXValue();
+int getIntPRValue();
+
+// CHECK: define i32* @_Z2f0v()
+// CHECK: call i32* @_Z12getIntLValuev()
+// CHECK-NEXT: ret i32*
+int &&f0() { return static_cast<int&&>(getIntLValue()); }
+
+// CHECK: define i32* @_Z2f1v()
+// CHECK: call i32* @_Z12getIntXValuev()
+// CHECK-NEXT: ret i32*
+int &&f1() { return static_cast<int&&>(getIntXValue()); }
+
+// CHECK: define i32* @_Z2f2v
+// CHECK: call i32 @_Z13getIntPRValuev()
+// CHECK-NEXT: store i32 {{.*}}, i32*
+// CHECK-NEXT: ret i32*
+int &&f2() { return static_cast<int&&>(getIntPRValue()); }