]> granicus.if.org Git - clang/commitdiff
Handle CK_DerivedToBase when emitting lvalue casts.
authorAnders Carlsson <andersca@mac.com>
Sat, 12 Sep 2009 16:16:49 +0000 (16:16 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 12 Sep 2009 16:16:49 +0000 (16:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81614 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
test/CodeGenCXX/derived-to-base.cpp [new file with mode: 0644]

index 1141dd6b028164df233164ca698f4a5cd7d1ed3f..92e87826a254271e6db91954d7dc1afdc8746805 100644 (file)
@@ -1153,30 +1153,51 @@ LValue CodeGenFunction::EmitConditionalOperator(const ConditionalOperator* E) {
 /// all the reasons that casts are permitted with aggregate result, including
 /// noop aggregate casts, and cast from scalar to union.
 LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
-  // If this is an aggregate-to-aggregate cast, just use the input's address as
-  // the lvalue.
-  if (E->getCastKind() == CastExpr::CK_NoOp ||
-      E->getCastKind() == CastExpr::CK_ConstructorConversion ||
-      E->getCastKind() == CastExpr::CK_UserDefinedConversion)
+  switch (E->getCastKind()) {
+  default:
+    // If this is an lvalue cast, treat it as a no-op.
+    // FIXME: We shouldn't need to check for this explicitly!
+    if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+      if (ICE->isLvalueCast())
+        return EmitLValue(E->getSubExpr());
+    
+    assert(0 && "Unhandled cast!");
+      
+  case CastExpr::CK_NoOp:
+  case CastExpr::CK_ConstructorConversion:
+  case CastExpr::CK_UserDefinedConversion:
     return EmitLValue(E->getSubExpr());
+  
+  case CastExpr::CK_DerivedToBase: {
+    const RecordType *DerivedClassTy = 
+      E->getSubExpr()->getType()->getAs<RecordType>();
+    CXXRecordDecl *DerivedClassDecl = 
+      cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+
+    const RecordType *BaseClassTy = E->getType()->getAs<RecordType>();
+    CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseClassTy->getDecl());
+    
+    LValue LV = EmitLValue(E->getSubExpr());
+    
+    // Perform the derived-to-base conversion
+    llvm::Value *Base = 
+      GetAddressCXXOfBaseClass(LV.getAddress(), DerivedClassDecl, 
+                               BaseClassDecl, /*NullCheckValue=*/false);
+    
+    return LValue::MakeAddr(Base, E->getType().getCVRQualifiers(),
+                            getContext().getObjCGCAttrKind(E->getType()),
+                            E->getType().getAddressSpace());
+  }
 
-  // If this is an lvalue cast, treat it as a no-op.
-  // FIXME: We shouldn't need to check for this explicitly!
-  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
-    if (ICE->isLvalueCast())
-      return EmitLValue(E->getSubExpr());
-
-  // Otherwise, we must have a cast from scalar to union.
-  assert(E->getCastKind() == CastExpr::CK_ToUnion &&
-         "Expected scalar-to-union cast");
-
-  // Casts are only lvalues when the source and destination types are the same.
-  llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
-  EmitAnyExpr(E->getSubExpr(), Temp, false);
+  case CastExpr::CK_ToUnion: {
+    llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
+    EmitAnyExpr(E->getSubExpr(), Temp, false);
 
-  return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
-                          getContext().getObjCGCAttrKind(E->getType()),
-                          E->getType().getAddressSpace());
+    return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
+                            getContext().getObjCGCAttrKind(E->getType()),
+                            E->getType().getAddressSpace());
+    }
+  }
 }
 
 //===--------------------------------------------------------------------===//
diff --git a/test/CodeGenCXX/derived-to-base.cpp b/test/CodeGenCXX/derived-to-base.cpp
new file mode 100644 (file)
index 0000000..63492d6
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: clang-cc -emit-llvm %s -o -
+struct A { 
+  void f(); 
+  
+  int a;
+};
+
+struct B : A { 
+  double b;
+};
+
+void f() {
+  B b;
+  
+  b.f();
+}