summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-09-03 01:26:39 +0000
committerJohn McCall <rjmccall@apple.com>2010-09-03 01:26:39 +0000
commitfc4002872864e3c29c896000519ae989b6fdb7dd (patch)
treeddf8870c2823af83c9bb4a2a582dae37e943f76f
parentbe74740cc246ce08d42804a684385a42eb814edb (diff)
Re-commit r112916 with an additional fix for the self-host failures.
I've audited the remaining getFunctionInfo call sites. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112936 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGCall.cpp3
-rw-r--r--lib/CodeGen/CGExprCXX.cpp44
-rw-r--r--test/CodeGenCXX/arm.cpp40
3 files changed, 69 insertions, 18 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 6072c1c499..f698d146f1 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -117,6 +117,9 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,
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()));
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index a5c1691307..9a98281771 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -93,14 +93,9 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
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 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
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 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
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);
@@ -853,7 +860,8 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
if (Dtor->isVirtual()) {
const llvm::Type *Ty =
- CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor),
+ CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor,
+ Dtor_Complete),
/*isVariadic=*/false);
llvm::Value *Callee
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index 05ed603acf..44c0affa5a 100644
--- a/test/CodeGenCXX/arm.cpp
+++ b/test/CodeGenCXX/arm.cpp
@@ -237,6 +237,46 @@ namespace test4 {
}
}
+// <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();
+ }
+}
+
+namespace test6 {
+ struct A {
+ virtual ~A();
+ };
+
+ // CHECK: define void @_ZN5test64testEPNS_1AE
+ void test(A *a) {
+ // CHECK: [[AVAR:%.*]] = alloca [[A:%.*]]*, align 4
+ // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[AVAR]], align 4
+ // CHECK-NEXT: [[V:%.*]] = load [[A]]** [[AVAR]], align 4
+ // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq [[A]]* [[V]], null
+ // CHECK-NEXT: br i1 [[ISNULL]]
+ // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to [[A]]* ([[A]]*)***
+ // CHECK-NEXT: [[T1:%.*]] = load [[A]]* ([[A]]*)*** [[T0]]
+ // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* ([[A]]*)** [[T1]], i64 1
+ // CHECK-NEXT: [[T3:%.*]] = load [[A]]* ([[A]]*)** [[T2]]
+ // CHECK-NEXT: call [[A]]* [[T3]]([[A]]* [[V]])
+ // CHECK-NEXT: br label
+ // CHECK: ret void
+ delete a;
+ }
+}
+
// CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
// CHECK: ret [[C]]* undef