[cfe-commits] r112916 - in /cfe/trunk: lib/CodeGen/CGCall.cpp lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/arm.cpp

John McCall rjmccall at apple.com
Thu Sep 2 17:01:57 PDT 2010


Author: rjmccall
Date: Thu Sep  2 19:01:57 2010
New Revision: 112916

URL: http://llvm.org/viewvc/llvm-project?rev=112916&view=rev
Log:
It's not safe to use the generic CXXMethodDecl overload of CGT::getFunctionInfo
to set up a destructor call, because ABIs can tweak these conventions.
Fixes rdar://problem/8386802.


Modified:
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/test/CodeGenCXX/arm.cpp

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=112916&r1=112915&r2=112916&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Sep  2 19:01:57 2010
@@ -117,6 +117,9 @@
 const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
   llvm::SmallVector<CanQualType, 16> ArgTys;
 
+  assert(!isa<CXXConstructorDecl>(MD) && "wrong method for contructors!");
+  assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
+
   // Add the 'this' pointer unless this is a static method.
   if (MD->isInstance())
     ArgTys.push_back(GetThisType(Context, MD->getParent()));

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=112916&r1=112915&r2=112916&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Sep  2 19:01:57 2010
@@ -93,14 +93,9 @@
     return EmitCall(getContext().getPointerType(MD->getType()), Callee,
                     ReturnValue, CE->arg_begin(), CE->arg_end());
   }
-  
-  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
 
-  const llvm::Type *Ty =
-    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
-                                   FPT->isVariadic());
+  // Compute the object pointer.
   llvm::Value *This;
-
   if (ME->isArrow())
     This = EmitScalarExpr(ME->getBase());
   else {
@@ -108,7 +103,10 @@
     This = BaseLV.getAddress();
   }
 
-  if (MD->isCopyAssignment() && MD->isTrivial()) {
+  if (MD->isTrivial()) {
+    if (isa<CXXDestructorDecl>(MD)) return RValue::get(0);
+
+    assert(MD->isCopyAssignment() && "unknown trivial member function");
     // We don't like to generate the trivial copy assignment operator when
     // it isn't necessary; just produce the proper effect here.
     llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
@@ -116,25 +114,34 @@
     return RValue::get(This);
   }
 
+  // Compute the function type we're calling.
+  const CGFunctionInfo &FInfo =
+    (isa<CXXDestructorDecl>(MD)
+     ? CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD),
+                                      Dtor_Complete)
+     : CGM.getTypes().getFunctionInfo(MD));
+
+  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+  const llvm::Type *Ty
+    = CGM.getTypes().GetFunctionType(FInfo, FPT->isVariadic());
+
   // C++ [class.virtual]p12:
   //   Explicit qualification with the scope operator (5.1) suppresses the
   //   virtual call mechanism.
   //
   // We also don't emit a virtual call if the base expression has a record type
   // because then we know what the type is.
+  bool UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
+                     && !canDevirtualizeMemberFunctionCalls(ME->getBase());
+
   llvm::Value *Callee;
-  if (const CXXDestructorDecl *Destructor
-             = dyn_cast<CXXDestructorDecl>(MD)) {
-    if (Destructor->isTrivial())
-      return RValue::get(0);
-    if (MD->isVirtual() && !ME->hasQualifier() && 
-        !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
-      Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty); 
+  if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
+    if (UseVirtualCall) {
+      Callee = BuildVirtualCall(Dtor, Dtor_Complete, This, Ty);
     } else {
-      Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty);
+      Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty);
     }
-  } else if (MD->isVirtual() && !ME->hasQualifier() && 
-             !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
+  } else if (UseVirtualCall) {
     Callee = BuildVirtualCall(MD, This, Ty); 
   } else {
     Callee = CGM.GetAddrOfFunction(MD, Ty);

Modified: cfe/trunk/test/CodeGenCXX/arm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=112916&r1=112915&r2=112916&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/arm.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/arm.cpp Thu Sep  2 19:01:57 2010
@@ -237,6 +237,23 @@
   }
 }
 
+// <rdar://problem/8386802>: don't crash
+namespace test5 {
+  struct A {
+    ~A();
+  };
+
+  // CHECK: define void @_ZN5test54testEPNS_1AE
+  void test(A *a) {
+    // CHECK:      [[PTR:%.*]] = alloca [[A:%.*]]*, align 4
+    // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[PTR]], align 4
+    // CHECK-NEXT: [[TMP:%.*]] = load [[A]]** [[PTR]], align 4
+    // CHECK-NEXT: call [[A]]* @_ZN5test51AD1Ev([[A]]* [[TMP]])
+    // CHECK-NEXT: ret void
+    a->~A();
+  }
+}
+
   // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
   // CHECK:   call [[C]]* @_ZN5test21CD1Ev(
   // CHECK:   ret [[C]]* undef





More information about the cfe-commits mailing list