summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGCXX.cpp')
-rw-r--r--lib/CodeGen/CGCXX.cpp30
1 files changed, 28 insertions, 2 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 3e854ca..cf172b1 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -291,7 +291,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E) {
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(MPT->getClass())->getDecl());
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
const llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
@@ -810,8 +810,32 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
Callee, CallArgs, MD);
if (nv_r || v_r) {
+ bool CanBeZero = !(ResultType->isReferenceType()
+ // FIXME: attr nonnull can't be zero either
+ /* || ResultType->hasAttr<NonNullAttr>() */ );
// Do the return result adjustment.
- RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
+ if (CanBeZero) {
+ llvm::BasicBlock *NonZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ContBlock = createBasicBlock();
+
+ const llvm::Type *Ty = RV.getScalarVal()->getType();
+ llvm::Value *Zero = llvm::Constant::getNullValue(Ty);
+ Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
+ NonZeroBlock, ZeroBlock);
+ EmitBlock(NonZeroBlock);
+ llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r);
+ EmitBranch(ContBlock);
+ EmitBlock(ZeroBlock);
+ llvm::Value *Z = RV.getScalarVal();
+ EmitBlock(ContBlock);
+ llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty);
+ RVOrZero->reserveOperandSpace(2);
+ RVOrZero->addIncoming(NZ, NonZeroBlock);
+ RVOrZero->addIncoming(Z, ZeroBlock);
+ RV = RValue::get(RVOrZero);
+ } else
+ RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
}
if (!ResultType->isVoidType())
@@ -1421,6 +1445,8 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
if (FieldType->isReferenceType())
RHS = EmitReferenceBindingToExpr(RhsExpr, FieldType,
/*IsInitializer=*/true);
+ else if (FieldType->isMemberFunctionPointerType())
+ RHS = RValue::get(CGM.EmitConstantExpr(RhsExpr, FieldType, this));
else
RHS = RValue::get(EmitScalarExpr(RhsExpr, true));
EmitStoreThroughLValue(RHS, LHS, FieldType);
OpenPOWER on IntegriCloud