diff options
Diffstat (limited to 'lib/CodeGen/CGCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 30 |
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); |