diff options
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
| -rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 147 | 
1 files changed, 90 insertions, 57 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 81fee677f61a..4396f567f2f9 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -379,19 +379,11 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,      }    } -  const ConstantArrayType *Array  -    = getContext().getAsConstantArrayType(E->getType()); -  if (Array) { -    QualType BaseElementTy = getContext().getBaseElementType(Array); -    const llvm::Type *BasePtr = ConvertType(BaseElementTy); -    BasePtr = llvm::PointerType::getUnqual(BasePtr); -    llvm::Value *BaseAddrPtr = -      Builder.CreateBitCast(Dest.getAddr(), BasePtr); -     -    EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr,  +  if (const ConstantArrayType *arrayType  +        = getContext().getAsConstantArrayType(E->getType())) { +    EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddr(),                                  E->arg_begin(), E->arg_end()); -  } -  else { +  } else {      CXXCtorType Type = Ctor_Complete;      bool ForVirtualBase = false; @@ -619,10 +611,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,      // can be ignored because the result shouldn't be used if      // allocation fails.      if (typeSizeMultiplier != 1) { -      const llvm::Type *intrinsicTypes[] = { CGF.SizeTy };        llvm::Value *umul_with_overflow -        = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, -                               intrinsicTypes, 1); +        = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, CGF.SizeTy);        llvm::Value *tsmV =          llvm::ConstantInt::get(CGF.SizeTy, typeSizeMultiplier); @@ -661,10 +651,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,      if (cookieSize != 0) {        sizeWithoutCookie = size; -      const llvm::Type *intrinsicTypes[] = { CGF.SizeTy };        llvm::Value *uadd_with_overflow -        = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, -                               intrinsicTypes, 1); +        = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, CGF.SizeTy);        llvm::Value *cookieSizeV = llvm::ConstantInt::get(CGF.SizeTy, cookieSize);        llvm::Value *result = @@ -707,16 +695,15 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,    unsigned Alignment =      CGF.getContext().getTypeAlignInChars(AllocType).getQuantity(); -  if (!CGF.hasAggregateLLVMType(AllocType))  -    CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr, -                          AllocType.isVolatileQualified(), Alignment, -                          AllocType); +  if (!CGF.hasAggregateLLVMType(AllocType)) +    CGF.EmitScalarInit(Init, 0, CGF.MakeAddrLValue(NewPtr, AllocType, Alignment), +                       false);    else if (AllocType->isAnyComplexType())      CGF.EmitComplexExprIntoAddr(Init, NewPtr,                                   AllocType.isVolatileQualified());    else {      AggValueSlot Slot -      = AggValueSlot::forAddr(NewPtr, AllocType.isVolatileQualified(), true); +      = AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(), true);      CGF.EmitAggExpr(Init, Slot);    }  } @@ -806,7 +793,7 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,          RequiresZeroInitialization = true;        } -       +        CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,                                        E->constructor_arg_begin(),                                        E->constructor_arg_end(), @@ -875,7 +862,7 @@ namespace {        getPlacementArgs()[I] = Arg;      } -    void Emit(CodeGenFunction &CGF, bool IsForEH) { +    void Emit(CodeGenFunction &CGF, Flags flags) {        const FunctionProtoType *FPT          = OperatorDelete->getType()->getAs<FunctionProtoType>();        assert(FPT->getNumArgs() == NumPlacementArgs + 1 || @@ -932,7 +919,7 @@ namespace {        getPlacementArgs()[I] = Arg;      } -    void Emit(CodeGenFunction &CGF, bool IsForEH) { +    void Emit(CodeGenFunction &CGF, Flags flags) {        const FunctionProtoType *FPT          = OperatorDelete->getType()->getAs<FunctionProtoType>();        assert(FPT->getNumArgs() == NumPlacementArgs + 1 || @@ -1075,7 +1062,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {    // CXXNewExpr::shouldNullCheckAllocation()) and we have an    // interesting initializer.    bool nullCheck = allocatorType->isNothrow(getContext()) && -    !(allocType->isPODType() && !E->hasInitializer()); +    !(allocType.isPODType(getContext()) && !E->hasInitializer());    llvm::BasicBlock *nullCheckBB = 0;    llvm::BasicBlock *contBB = 0; @@ -1202,7 +1189,7 @@ namespace {                       QualType ElementType)        : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {} -    void Emit(CodeGenFunction &CGF, bool IsForEH) { +    void Emit(CodeGenFunction &CGF, Flags flags) {        CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType);      }    }; @@ -1212,7 +1199,8 @@ namespace {  static void EmitObjectDelete(CodeGenFunction &CGF,                               const FunctionDecl *OperatorDelete,                               llvm::Value *Ptr, -                             QualType ElementType) { +                             QualType ElementType, +                             bool UseGlobalDelete) {    // Find the destructor for the type, if applicable.  If the    // destructor is virtual, we'll just emit the vcall and return.    const CXXDestructorDecl *Dtor = 0; @@ -1222,17 +1210,30 @@ static void EmitObjectDelete(CodeGenFunction &CGF,        Dtor = RD->getDestructor();        if (Dtor->isVirtual()) { +        if (UseGlobalDelete) { +          // If we're supposed to call the global delete, make sure we do so +          // even if the destructor throws. +          CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, +                                                    Ptr, OperatorDelete,  +                                                    ElementType); +        } +                  const llvm::Type *Ty =            CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor,                                                                 Dtor_Complete),                                           /*isVariadic=*/false);          llvm::Value *Callee -          = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty); +          = CGF.BuildVirtualCall(Dtor,  +                                 UseGlobalDelete? Dtor_Complete : Dtor_Deleting, +                                 Ptr, Ty);          CGF.EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0,                                0, 0); -        // The dtor took care of deleting the object. +        if (UseGlobalDelete) { +          CGF.PopCleanupBlock(); +        } +                  return;        }      } @@ -1247,7 +1248,29 @@ static void EmitObjectDelete(CodeGenFunction &CGF,    if (Dtor)      CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,                                /*ForVirtualBase=*/false, Ptr); +  else if (CGF.getLangOptions().ObjCAutoRefCount && +           ElementType->isObjCLifetimeType()) { +    switch (ElementType.getObjCLifetime()) { +    case Qualifiers::OCL_None: +    case Qualifiers::OCL_ExplicitNone: +    case Qualifiers::OCL_Autoreleasing: +      break; +    case Qualifiers::OCL_Strong: { +      // Load the pointer value. +      llvm::Value *PtrValue = CGF.Builder.CreateLoad(Ptr,  +                                             ElementType.isVolatileQualified()); +         +      CGF.EmitARCRelease(PtrValue, /*precise*/ true); +      break; +    } +         +    case Qualifiers::OCL_Weak: +      CGF.EmitARCDestroyWeak(Ptr); +      break; +    } +  } +               CGF.PopCleanupBlock();  } @@ -1268,7 +1291,7 @@ namespace {        : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),          ElementType(ElementType), CookieSize(CookieSize) {} -    void Emit(CodeGenFunction &CGF, bool IsForEH) { +    void Emit(CodeGenFunction &CGF, Flags flags) {        const FunctionProtoType *DeleteFTy =          OperatorDelete->getType()->getAs<FunctionProtoType>();        assert(DeleteFTy->getNumArgs() == 1 || DeleteFTy->getNumArgs() == 2); @@ -1316,31 +1339,40 @@ namespace {  /// Emit the code for deleting an array of objects.  static void EmitArrayDelete(CodeGenFunction &CGF,                              const CXXDeleteExpr *E, -                            llvm::Value *Ptr, -                            QualType ElementType) { -  llvm::Value *NumElements = 0; -  llvm::Value *AllocatedPtr = 0; -  CharUnits CookieSize; -  CGF.CGM.getCXXABI().ReadArrayCookie(CGF, Ptr, E, ElementType, -                                      NumElements, AllocatedPtr, CookieSize); +                            llvm::Value *deletedPtr, +                            QualType elementType) { +  llvm::Value *numElements = 0; +  llvm::Value *allocatedPtr = 0; +  CharUnits cookieSize; +  CGF.CGM.getCXXABI().ReadArrayCookie(CGF, deletedPtr, E, elementType, +                                      numElements, allocatedPtr, cookieSize); -  assert(AllocatedPtr && "ReadArrayCookie didn't set AllocatedPtr"); +  assert(allocatedPtr && "ReadArrayCookie didn't set allocated pointer");    // Make sure that we call delete even if one of the dtors throws. -  const FunctionDecl *OperatorDelete = E->getOperatorDelete(); +  const FunctionDecl *operatorDelete = E->getOperatorDelete();    CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, -                                           AllocatedPtr, OperatorDelete, -                                           NumElements, ElementType, -                                           CookieSize); - -  if (const CXXRecordDecl *RD = ElementType->getAsCXXRecordDecl()) { -    if (!RD->hasTrivialDestructor()) { -      assert(NumElements && "ReadArrayCookie didn't find element count" -                            " for a class with destructor"); -      CGF.EmitCXXAggrDestructorCall(RD->getDestructor(), NumElements, Ptr); -    } +                                           allocatedPtr, operatorDelete, +                                           numElements, elementType, +                                           cookieSize); + +  // Destroy the elements. +  if (QualType::DestructionKind dtorKind = elementType.isDestructedType()) { +    assert(numElements && "no element count for a type with a destructor!"); + +    llvm::Value *arrayEnd = +      CGF.Builder.CreateInBoundsGEP(deletedPtr, numElements, "delete.end"); + +    // Note that it is legal to allocate a zero-length array, and we +    // can never fold the check away because the length should always +    // come from a cookie. +    CGF.emitArrayDestroy(deletedPtr, arrayEnd, elementType, +                         CGF.getDestroyer(dtorKind), +                         /*checkZeroLength*/ true, +                         CGF.needsEHCleanup(dtorKind));    } +  // Pop the cleanup block.    CGF.PopCleanupBlock();  } @@ -1397,7 +1429,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {    if (E->isArrayForm()) {      EmitArrayDelete(*this, E, Ptr, DeleteTy);    } else { -    EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy); +    EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy, +                     E->isGlobalDelete());    }    EmitBlock(DeleteEnd); @@ -1415,7 +1448,7 @@ static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) {  static void EmitBadTypeidCall(CodeGenFunction &CGF) {    llvm::Value *Fn = getBadTypeidFn(CGF); -  CGF.EmitCallOrInvoke(Fn, 0, 0).setDoesNotReturn(); +  CGF.EmitCallOrInvoke(Fn).setDoesNotReturn();    CGF.Builder.CreateUnreachable();  } @@ -1489,11 +1522,11 @@ static llvm::Constant *getDynamicCastFn(CodeGenFunction &CGF) {    //                      const abi::__class_type_info *dst,    //                      std::ptrdiff_t src2dst_offset); -  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); -  const llvm::Type *PtrDiffTy =  +  llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); +  llvm::Type *PtrDiffTy =       CGF.ConvertType(CGF.getContext().getPointerDiffType()); -  const llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy }; +  llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };    const llvm::FunctionType *FTy =      llvm::FunctionType::get(Int8PtrTy, Args, false); @@ -1513,7 +1546,7 @@ static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {  static void EmitBadCastCall(CodeGenFunction &CGF) {    llvm::Value *Fn = getBadCastFn(CGF); -  CGF.EmitCallOrInvoke(Fn, 0, 0).setDoesNotReturn(); +  CGF.EmitCallOrInvoke(Fn).setDoesNotReturn();    CGF.Builder.CreateUnreachable();  }  | 
