| //===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This contains code dealing with C++ code generation of temporaries |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "CodeGenFunction.h" |
| using namespace clang; |
| using namespace CodeGen; |
| |
| static void EmitTemporaryCleanup(CodeGenFunction &CGF, |
| const CXXTemporary *Temporary, |
| llvm::Value *Addr, |
| llvm::Value *CondPtr) { |
| llvm::BasicBlock *CondEnd = 0; |
| |
| // If this is a conditional temporary, we need to check the condition |
| // boolean and only call the destructor if it's true. |
| if (CondPtr) { |
| llvm::BasicBlock *CondBlock = CGF.createBasicBlock("temp.cond-dtor.call"); |
| CondEnd = CGF.createBasicBlock("temp.cond-dtor.cont"); |
| |
| llvm::Value *Cond = CGF.Builder.CreateLoad(CondPtr); |
| CGF.Builder.CreateCondBr(Cond, CondBlock, CondEnd); |
| CGF.EmitBlock(CondBlock); |
| } |
| |
| CGF.EmitCXXDestructorCall(Temporary->getDestructor(), |
| Dtor_Complete, /*ForVirtualBase=*/false, |
| Addr); |
| |
| if (CondPtr) { |
| // Reset the condition to false. |
| CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()), |
| CondPtr); |
| CGF.EmitBlock(CondEnd); |
| } |
| } |
| |
| /// Emits all the code to cause the given temporary to be cleaned up. |
| void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, |
| llvm::Value *Ptr) { |
| llvm::AllocaInst *CondPtr = 0; |
| |
| // Check if temporaries need to be conditional. If so, we'll create a |
| // condition boolean, initialize it to 0 and |
| if (ConditionalBranchLevel != 0) { |
| CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond"); |
| |
| // Initialize it to false. This initialization takes place right after |
| // the alloca insert point. |
| InitTempAlloca(CondPtr, llvm::ConstantInt::getFalse(VMContext)); |
| |
| // Now set it to true. |
| Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr); |
| } |
| |
| CleanupBlock Cleanup(*this, NormalCleanup); |
| EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr); |
| |
| if (Exceptions) { |
| Cleanup.beginEHCleanup(); |
| EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr); |
| } |
| } |
| |
| RValue |
| CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, |
| llvm::Value *AggLoc, |
| bool IsAggLocVolatile, |
| bool IsInitializer) { |
| RValue RV; |
| { |
| RunCleanupsScope Scope(*this); |
| |
| RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, |
| /*IgnoreResult=*/false, IsInitializer); |
| } |
| return RV; |
| } |
| |
| LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue( |
| const CXXExprWithTemporaries *E) { |
| LValue LV; |
| { |
| RunCleanupsScope Scope(*this); |
| |
| LV = EmitLValue(E->getSubExpr()); |
| } |
| return LV; |
| } |