diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-07-15 17:07:12 +0000 | 
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-07-15 17:07:12 +0000 | 
| commit | 4e58654b47e89efbb1a8ca032c08fd354c3b0b61 (patch) | |
| tree | 5e946d69177464379cb1a38ac18206180d763639 /lib/CodeGen/CGDecl.cpp | |
| parent | 4ba675006b5a8edfc48b6a9bd3dcf54a70cc08f2 (diff) | |
Notes
Diffstat (limited to 'lib/CodeGen/CGDecl.cpp')
| -rw-r--r-- | lib/CodeGen/CGDecl.cpp | 102 | 
1 files changed, 56 insertions, 46 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 959a9ae483b0..1a62ea95555d 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -388,6 +388,58 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {    return Info.first;  } +namespace { +  struct CallArrayDtor : EHScopeStack::LazyCleanup { +    CallArrayDtor(const CXXDestructorDecl *Dtor,  +                  const ConstantArrayType *Type, +                  llvm::Value *Loc) +      : Dtor(Dtor), Type(Type), Loc(Loc) {} + +    const CXXDestructorDecl *Dtor; +    const ConstantArrayType *Type; +    llvm::Value *Loc; + +    void Emit(CodeGenFunction &CGF, bool IsForEH) { +      QualType BaseElementTy = CGF.getContext().getBaseElementType(Type); +      const llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy); +      BasePtr = llvm::PointerType::getUnqual(BasePtr); +      llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(Loc, BasePtr); +      CGF.EmitCXXAggrDestructorCall(Dtor, Type, BaseAddrPtr); +    } +  }; + +  struct CallVarDtor : EHScopeStack::LazyCleanup { +    CallVarDtor(const CXXDestructorDecl *Dtor, +                llvm::Value *NRVOFlag, +                llvm::Value *Loc) +      : Dtor(Dtor), NRVOFlag(NRVOFlag), Loc(Loc) {} + +    const CXXDestructorDecl *Dtor; +    llvm::Value *NRVOFlag; +    llvm::Value *Loc; + +    void Emit(CodeGenFunction &CGF, bool IsForEH) { +      // Along the exceptions path we always execute the dtor. +      bool NRVO = !IsForEH && NRVOFlag; + +      llvm::BasicBlock *SkipDtorBB = 0; +      if (NRVO) { +        // If we exited via NRVO, we skip the destructor call. +        llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused"); +        SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor"); +        llvm::Value *DidNRVO = CGF.Builder.CreateLoad(NRVOFlag, "nrvo.val"); +        CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB); +        CGF.EmitBlock(RunDtorBB); +      } +           +      CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, +                                /*ForVirtualBase=*/false, Loc); + +      if (NRVO) CGF.EmitBlock(SkipDtorBB); +    } +  }; +} +  /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a  /// variable declaration with auto, register, or no storage class specifier.  /// These turn into simple stack objects, or GlobalValues depending on target. @@ -686,53 +738,11 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,          if (const ConstantArrayType *Array =                 getContext().getAsConstantArrayType(Ty)) { -          CleanupBlock Scope(*this, NormalCleanup); - -          QualType BaseElementTy = getContext().getBaseElementType(Array); -          const llvm::Type *BasePtr = ConvertType(BaseElementTy); -          BasePtr = llvm::PointerType::getUnqual(BasePtr); -          llvm::Value *BaseAddrPtr = -            Builder.CreateBitCast(Loc, BasePtr); -          EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); - -          if (Exceptions) { -            Scope.beginEHCleanup(); - -            QualType BaseElementTy = getContext().getBaseElementType(Array); -            const llvm::Type *BasePtr = ConvertType(BaseElementTy); -            BasePtr = llvm::PointerType::getUnqual(BasePtr); -            llvm::Value *BaseAddrPtr = -              Builder.CreateBitCast(Loc, BasePtr); -            EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); -          } +          EHStack.pushLazyCleanup<CallArrayDtor>(NormalAndEHCleanup, +                                                 D, Array, Loc);          } else { -          // Normal destruction.  -          CleanupBlock Scope(*this, NormalCleanup); - -          llvm::BasicBlock *SkipDtor = 0; -          if (NRVO) { -            // If we exited via NRVO, we skip the destructor call. -            llvm::BasicBlock *NoNRVO = createBasicBlock("nrvo.unused"); -            SkipDtor = createBasicBlock("nrvo.skipdtor"); -            Builder.CreateCondBr(Builder.CreateLoad(NRVOFlag, "nrvo.val"), -                                 SkipDtor, -                                 NoNRVO); -            EmitBlock(NoNRVO); -          } -           -          // We don't call the destructor along the normal edge if we're -          // applying the NRVO. -          EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, -                                Loc); - -          if (NRVO) EmitBlock(SkipDtor); - -          // Along the exceptions path we always execute the dtor. -          if (Exceptions) { -            Scope.beginEHCleanup(); -            EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, -                                  Loc); -          } +          EHStack.pushLazyCleanup<CallVarDtor>(NormalAndEHCleanup, +                                               D, NRVOFlag, Loc);          }        }    }  | 
