forked from OSchip/llvm-project
Re-commit r112916 with an additional fix for the self-host failures.
I've audited the remaining getFunctionInfo call sites. llvm-svn: 112936
This commit is contained in:
parent
0389df4a45
commit
0d635f53a8
|
@ -117,6 +117,9 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,
|
||||||
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
|
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
|
||||||
llvm::SmallVector<CanQualType, 16> ArgTys;
|
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.
|
// Add the 'this' pointer unless this is a static method.
|
||||||
if (MD->isInstance())
|
if (MD->isInstance())
|
||||||
ArgTys.push_back(GetThisType(Context, MD->getParent()));
|
ArgTys.push_back(GetThisType(Context, MD->getParent()));
|
||||||
|
|
|
@ -93,14 +93,9 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
|
||||||
return EmitCall(getContext().getPointerType(MD->getType()), Callee,
|
return EmitCall(getContext().getPointerType(MD->getType()), Callee,
|
||||||
ReturnValue, CE->arg_begin(), CE->arg_end());
|
ReturnValue, CE->arg_begin(), CE->arg_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
|
|
||||||
|
|
||||||
const llvm::Type *Ty =
|
// Compute the object pointer.
|
||||||
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
|
|
||||||
FPT->isVariadic());
|
|
||||||
llvm::Value *This;
|
llvm::Value *This;
|
||||||
|
|
||||||
if (ME->isArrow())
|
if (ME->isArrow())
|
||||||
This = EmitScalarExpr(ME->getBase());
|
This = EmitScalarExpr(ME->getBase());
|
||||||
else {
|
else {
|
||||||
|
@ -108,7 +103,10 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
|
||||||
This = BaseLV.getAddress();
|
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
|
// We don't like to generate the trivial copy assignment operator when
|
||||||
// it isn't necessary; just produce the proper effect here.
|
// it isn't necessary; just produce the proper effect here.
|
||||||
llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
|
llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
|
||||||
|
@ -116,25 +114,34 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
|
||||||
return RValue::get(This);
|
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:
|
// C++ [class.virtual]p12:
|
||||||
// Explicit qualification with the scope operator (5.1) suppresses the
|
// Explicit qualification with the scope operator (5.1) suppresses the
|
||||||
// virtual call mechanism.
|
// virtual call mechanism.
|
||||||
//
|
//
|
||||||
// We also don't emit a virtual call if the base expression has a record type
|
// We also don't emit a virtual call if the base expression has a record type
|
||||||
// because then we know what the type is.
|
// because then we know what the type is.
|
||||||
|
bool UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
|
||||||
|
&& !canDevirtualizeMemberFunctionCalls(ME->getBase());
|
||||||
|
|
||||||
llvm::Value *Callee;
|
llvm::Value *Callee;
|
||||||
if (const CXXDestructorDecl *Destructor
|
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
|
||||||
= dyn_cast<CXXDestructorDecl>(MD)) {
|
if (UseVirtualCall) {
|
||||||
if (Destructor->isTrivial())
|
Callee = BuildVirtualCall(Dtor, Dtor_Complete, This, Ty);
|
||||||
return RValue::get(0);
|
|
||||||
if (MD->isVirtual() && !ME->hasQualifier() &&
|
|
||||||
!canDevirtualizeMemberFunctionCalls(ME->getBase())) {
|
|
||||||
Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty);
|
|
||||||
} else {
|
} else {
|
||||||
Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty);
|
Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty);
|
||||||
}
|
}
|
||||||
} else if (MD->isVirtual() && !ME->hasQualifier() &&
|
} else if (UseVirtualCall) {
|
||||||
!canDevirtualizeMemberFunctionCalls(ME->getBase())) {
|
|
||||||
Callee = BuildVirtualCall(MD, This, Ty);
|
Callee = BuildVirtualCall(MD, This, Ty);
|
||||||
} else {
|
} else {
|
||||||
Callee = CGM.GetAddrOfFunction(MD, Ty);
|
Callee = CGM.GetAddrOfFunction(MD, Ty);
|
||||||
|
@ -853,7 +860,8 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
|
||||||
|
|
||||||
if (Dtor->isVirtual()) {
|
if (Dtor->isVirtual()) {
|
||||||
const llvm::Type *Ty =
|
const llvm::Type *Ty =
|
||||||
CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor),
|
CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor,
|
||||||
|
Dtor_Complete),
|
||||||
/*isVariadic=*/false);
|
/*isVariadic=*/false);
|
||||||
|
|
||||||
llvm::Value *Callee
|
llvm::Value *Callee
|
||||||
|
|
|
@ -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: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
|
||||||
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
|
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
|
||||||
// CHECK: ret [[C]]* undef
|
// CHECK: ret [[C]]* undef
|
||||||
|
|
Loading…
Reference in New Issue