[cfe-commits] r144268 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGBlocks.h lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprComplex.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CGObjC.cpp lib/CodeGen/CGTemporaries.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenObjC/arc-blocks.m test/CodeGenObjC/arc-foreach.m

Devang Patel dpatel at apple.com
Thu Nov 10 10:53:07 PST 2011


John,

This patch is causing block-5988451.c test failures from gccTestSuite. Please investigate or revert. r144271 has not addressed this.
Thanks!
-
Devang

$ clang -mmacosx-version-min=10.5 -ObjC -fblocks block-5988451.c  -o /tmp/b.o
Assertion failed: (head && *head), function findAndRemoveBlockInfo, file /Volumes/Lalgate/clean/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp, line 578.
0  clang             0x00000001021bea52 _ZL15PrintStackTracePv + 34
1  clang             0x00000001021bf049 _ZL13SignalHandleri + 777
2  libsystem_c.dylib 0x00007fff84106cfa _sigtramp + 26
3  libsystem_c.dylib 0x00007fff840cb5c3 szone_free_definite_size + 1815
4  clang             0x00000001021bec96 abort + 22
5  clang             0x00000001021bec57 __assert_rtn + 55
6  clang             0x0000000100f860c8 clang::CodeGen::CodeGenFunction::EmitBlockLiteral(clang::BlockExpr const*) + 456
7  clang             0x0000000101001b67 clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit(clang::Stmt*) + 14055
8  clang             0x0000000100ff9980 clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) + 96
9  clang             0x0000000100fd5899 clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) + 57
10 clang             0x0000000100fd6168 clang::CodeGen::CodeGenFunction::EmitAnyExprToTemp(clang::Expr const*) + 136
11 clang             0x0000000100fa8a12 clang::CodeGen::CodeGenFunction::EmitCallArg(clang::CodeGen::CallArgList&, clang::Expr const*, clang::QualType) + 2626
12 clang             0x0000000100fe3f48 void clang::CodeGen::CodeGenFunction::EmitCallArgs<clang::FunctionProtoType>(clang::CodeGen::CallArgList&, clang::FunctionProtoType const*, clang::ConstExprIterator, clang::ConstExprIterator) + 328
13 clang             0x0000000100fe1112 clang::CodeGen::CodeGenFunction::EmitCall(clang::QualType, llvm::Value*, clang::CodeGen::ReturnValueSlot, clang::ConstExprIterator, clang::ConstExprIterator, clang::Decl const*) + 242
14 clang             0x0000000100fe0fd2 clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) + 978
15 clang             0x0000000101005830 (anonymous namespace)::ScalarExprEmitter::VisitCallExpr(clang::CallExpr const*) + 208
16 clang             0x0000000101001da0 clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit(clang::Stmt*) + 14624
17 clang             0x0000000100ff9980 clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) + 96
18 clang             0x0000000100fd5899 clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) + 57
19 clang             0x0000000100fd5849 clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) + 41
20 clang             0x000000010104a877 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 391
21 clang             0x000000010104fe5b clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 267
22 clang             0x000000010104acad clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*) + 141
23 clang             0x000000010104a719 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 41
24 clang             0x000000010100a5aa clang::CodeGen::CodeGenFunction::GenerateObjCMethod(clang::ObjCMethodDecl const*) + 58
25 clang             0x00000001010674c5 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) + 693
26 clang             0x000000010108083f (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) + 127
27 clang             0x00000001010597ca clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) + 170
28 clang             0x000000010108aa92 clang::ParseAST(clang::Sema&, bool) + 306
29 clang             0x00000001010588f7 clang::CodeGenAction::ExecuteAction() + 1031
30 clang             0x0000000100e5ed9b clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 955
31 clang             0x0000000100e477c8 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 2792
32 clang             0x0000000100e3efe7 cc1_main(char const**, char const**, char const*, void*) + 5287
33 clang             0x0000000100e43b52 main + 706
34 clang             0x0000000100e3db34 start + 52
Stack dump:

-------------- next part --------------
A non-text attachment was scrubbed...
Name: block-5988451.c
Type: application/octet-stream
Size: 1080 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111110/c5c5cdd3/attachment.obj>
-------------- next part --------------


On Nov 10, 2011, at 12:15 AM, John McCall wrote:

> Author: rjmccall
> Date: Thu Nov 10 02:15:53 2011
> New Revision: 144268
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=144268&view=rev
> Log:
> Enter the cleanups for a block outside the enclosing
> full-expression.  Naturally they're inactive before we enter
> the block literal expression.  This restores the intended
> behavior that blocks belong to their enclosing scope.
> 
> There's a useful -O0 / compile-time optimization that we're
> missing here with activating cleanups following straight-line
> code from their inactive beginnings.
> 
> 
> Modified:
>    cfe/trunk/lib/CodeGen/CGBlocks.cpp
>    cfe/trunk/lib/CodeGen/CGBlocks.h
>    cfe/trunk/lib/CodeGen/CGDecl.cpp
>    cfe/trunk/lib/CodeGen/CGExpr.cpp
>    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
>    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
>    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>    cfe/trunk/lib/CodeGen/CGObjC.cpp
>    cfe/trunk/lib/CodeGen/CGTemporaries.cpp
>    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>    cfe/trunk/lib/CodeGen/CodeGenFunction.h
>    cfe/trunk/test/CodeGenObjC/arc-blocks.m
>    cfe/trunk/test/CodeGenObjC/arc-foreach.m
> 
> Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Nov 10 02:15:53 2011
> @@ -25,13 +25,14 @@
> using namespace clang;
> using namespace CodeGen;
> 
> -CGBlockInfo::CGBlockInfo(const BlockExpr *blockExpr, const char *N)
> -  : Name(N), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
> -    HasCXXObject(false), UsesStret(false), StructureType(0), Block(blockExpr) {
> +CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
> +  : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
> +    HasCXXObject(false), UsesStret(false), StructureType(0), Block(block) {
> 
> -  // Skip asm prefix, if any.
> -  if (Name && Name[0] == '\01')
> -    ++Name;
> +  // Skip asm prefix, if any.  'name' is usually taken directly from
> +  // the mangled name of the enclosing function.
> +  if (!name.empty() && name[0] == '\01')
> +    name = name.substr(1);
> }
> 
> // Anchor the vtable to this translation unit.
> @@ -483,15 +484,137 @@
>     llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
> }
> 
> +/// Enter the scope of a block.  This should be run at the entrance to
> +/// a full-expression so that the block's cleanups are pushed at the
> +/// right place in the stack.
> +static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
> +  // Allocate the block info and place it at the head of the list.
> +  CGBlockInfo &blockInfo =
> +    *new CGBlockInfo(block, CGF.CurFn->getName());
> +  blockInfo.NextBlockInfo = CGF.FirstBlockInfo;
> +  CGF.FirstBlockInfo = &blockInfo;
> +
> +  // Compute information about the layout, etc., of this block,
> +  // pushing cleanups as necessary.
> +  computeBlockInfo(CGF.CGM, blockInfo);
> +
> +  // Nothing else to do if it can be global.
> +  if (blockInfo.CanBeGlobal) return;
> +
> +  // Make the allocation for the block.
> +  blockInfo.Address =
> +    CGF.CreateTempAlloca(blockInfo.StructureType, "block");
> +  blockInfo.Address->setAlignment(blockInfo.BlockAlign.getQuantity());
> +
> +  // If there are cleanups to emit, enter them (but inactive).
> +  if (!blockInfo.NeedsCopyDispose) return;
> +
> +  // Walk through the captures (in order) and find the ones not
> +  // captured by constant.
> +  for (BlockDecl::capture_const_iterator ci = block->capture_begin(),
> +         ce = block->capture_end(); ci != ce; ++ci) {
> +    // Ignore __block captures; there's nothing special in the
> +    // on-stack block that we need to do for them.
> +    if (ci->isByRef()) continue;
> +
> +    // Ignore variables that are constant-captured.
> +    const VarDecl *variable = ci->getVariable();
> +    CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
> +    if (capture.isConstant()) continue;
> +
> +    // Ignore objects that aren't destructed.
> +    QualType::DestructionKind dtorKind =
> +      variable->getType().isDestructedType();
> +    if (dtorKind == QualType::DK_none) continue;
> +
> +    CodeGenFunction::Destroyer *destroyer;
> +
> +    // Block captures count as local values and have imprecise semantics.
> +    // They also can't be arrays, so need to worry about that.
> +    if (dtorKind == QualType::DK_objc_strong_lifetime) {
> +      destroyer = &CodeGenFunction::destroyARCStrongImprecise;
> +    } else {
> +      destroyer = &CGF.getDestroyer(dtorKind);
> +    }
> +
> +    // GEP down to the address.
> +    llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address,
> +                                                    capture.getIndex());
> +
> +    CleanupKind cleanupKind = InactiveNormalCleanup;
> +    bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind);
> +    if (useArrayEHCleanup) 
> +      cleanupKind = InactiveNormalAndEHCleanup;
> +
> +    CGF.pushDestroy(cleanupKind, addr, variable->getType(),
> +                    *destroyer, useArrayEHCleanup);
> +
> +    // Remember where that cleanup was.
> +    capture.setCleanup(CGF.EHStack.stable_begin());
> +  }
> +}
> +
> +/// Enter a full-expression with a non-trivial number of objects to
> +/// clean up.  This is in this file because, at the moment, the only
> +/// kind of cleanup object is a BlockDecl*.
> +void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) {
> +  assert(E->getNumObjects() != 0);
> +  ArrayRef<ExprWithCleanups::CleanupObject> cleanups = E->getObjects();
> +  for (ArrayRef<ExprWithCleanups::CleanupObject>::iterator
> +         i = cleanups.begin(), e = cleanups.end(); i != e; ++i) {
> +    enterBlockScope(*this, *i);
> +  }
> +}
> +
> +/// Find the layout for the given block in a linked list and remove it.
> +static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head,
> +                                           const BlockDecl *block) {
> +  while (true) {
> +    assert(head && *head);
> +    CGBlockInfo *cur = *head;
> +
> +    // If this is the block we're looking for, splice it out of the list.
> +    if (cur->getBlockDecl() == block) {
> +      *head = cur->NextBlockInfo;
> +      return cur;
> +    }
> +
> +    head = &cur->NextBlockInfo;
> +  }
> +}
> +
> +/// Destroy a chain of block layouts.
> +void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) {
> +  assert(head && "destroying an empty chain");
> +  do {
> +    CGBlockInfo *cur = head;
> +    head = cur->NextBlockInfo;
> +    delete cur;
> +  } while (head != 0);
> +}
> +
> /// Emit a block literal expression in the current function.
> llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
> -  std::string Name = CurFn->getName();
> -  CGBlockInfo blockInfo(blockExpr, Name.c_str());
> +  // If the block has no captures, we won't have a pre-computed
> +  // layout for it.
> +  if (!blockExpr->getBlockDecl()->hasCaptures()) {
> +    CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
> +    computeBlockInfo(CGM, blockInfo);
> +    blockInfo.BlockExpression = blockExpr;
> +    return EmitBlockLiteral(blockInfo);
> +  }
> +
> +  // Find the block info for this block and take ownership of it.
> +  llvm::OwningPtr<CGBlockInfo> blockInfo;
> +  blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo,
> +                                         blockExpr->getBlockDecl()));
> 
> -  // Compute information about the layout, etc., of this block.
> -  computeBlockInfo(CGM, blockInfo);
> +  blockInfo->BlockExpression = blockExpr;
> +  return EmitBlockLiteral(*blockInfo);
> +}
> 
> -  // Using that metadata, generate the actual block function.
> +llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
> +  // Using the computed layout, generate the actual block function.
>   llvm::Constant *blockFn
>     = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo,
>                                                  CurFuncDecl, LocalDeclMap);
> @@ -509,11 +632,8 @@
>   // Build the block descriptor.
>   llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
> 
> -  llvm::Type *intTy = ConvertType(getContext().IntTy);
> -
> -  llvm::AllocaInst *blockAddr =
> -    CreateTempAlloca(blockInfo.StructureType, "block");
> -  blockAddr->setAlignment(blockInfo.BlockAlign.getQuantity());
> +  llvm::AllocaInst *blockAddr = blockInfo.Address;
> +  assert(blockAddr && "block has no address!");
> 
>   // Compute the initial on-stack block flags.
>   BlockFlags flags = BLOCK_HAS_SIGNATURE;
> @@ -523,9 +643,9 @@
> 
>   // Initialize the block literal.
>   Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa"));
> -  Builder.CreateStore(llvm::ConstantInt::get(intTy, flags.getBitMask()),
> +  Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
>                       Builder.CreateStructGEP(blockAddr, 1, "block.flags"));
> -  Builder.CreateStore(llvm::ConstantInt::get(intTy, 0),
> +  Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0),
>                       Builder.CreateStructGEP(blockAddr, 2, "block.reserved"));
>   Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3,
>                                                        "block.invoke"));
> @@ -625,28 +745,11 @@
>                      /*captured by init*/ false);
>     }
> 
> -    // Push a destructor if necessary.  The semantics for when this
> -    // actually gets run are really obscure.
> +    // Activate the cleanup if layout pushed one.
>     if (!ci->isByRef()) {
> -      switch (QualType::DestructionKind dtorKind = type.isDestructedType()) {
> -      case QualType::DK_none:
> -        break;
> -
> -      // Block captures count as local values and have imprecise semantics.
> -      // They also can't be arrays, so need to worry about that.
> -      case QualType::DK_objc_strong_lifetime: {
> -        // This local is a GCC and MSVC compiler workaround.
> -        Destroyer *destroyer = &destroyARCStrongImprecise;
> -        pushDestroy(getCleanupKind(dtorKind), blockField, type,
> -                    *destroyer, /*useEHCleanupForArray*/ false);
> -        break;
> -      }
> -
> -      case QualType::DK_objc_weak_lifetime:
> -      case QualType::DK_cxx_destructor:
> -        pushDestroy(dtorKind, blockField, type);
> -        break;
> -      }
> +      EHScopeStack::stable_iterator cleanup = capture.getCleanup();
> +      if (cleanup.isValid())
> +        ActivateCleanupBlock(cleanup);
>     }
>   }
> 
> @@ -800,7 +903,8 @@
> llvm::Constant *
> CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr,
>                                     const char *name) {
> -  CGBlockInfo blockInfo(blockExpr, name);
> +  CGBlockInfo blockInfo(blockExpr->getBlockDecl(), name);
> +  blockInfo.BlockExpression = blockExpr;
> 
>   // Compute information about the layout, etc., of this block.
>   computeBlockInfo(*this, blockInfo);
> 
> Modified: cfe/trunk/lib/CodeGen/CGBlocks.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.h?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBlocks.h (original)
> +++ cfe/trunk/lib/CodeGen/CGBlocks.h Thu Nov 10 02:15:53 2011
> @@ -23,6 +23,7 @@
> #include "clang/AST/ExprCXX.h"
> #include "clang/AST/ExprObjC.h"
> 
> +#include "CodeGenFunction.h"
> #include "CGBuilder.h"
> #include "CGCall.h"
> #include "CGValue.h"
> @@ -128,13 +129,14 @@
> class CGBlockInfo {
> public:
>   /// Name - The name of the block, kindof.
> -  const char *Name;
> +  llvm::StringRef Name;
> 
>   /// The field index of 'this' within the block, if there is one.
>   unsigned CXXThisIndex;
> 
>   class Capture {
>     uintptr_t Data;
> +    EHScopeStack::stable_iterator Cleanup;
> 
>   public:
>     bool isIndex() const { return (Data & 1) != 0; }
> @@ -144,6 +146,14 @@
>       assert(isConstant());
>       return reinterpret_cast<llvm::Value*>(Data);
>     }
> +    EHScopeStack::stable_iterator getCleanup() const {
> +      assert(isIndex());
> +      return Cleanup;
> +    }
> +    void setCleanup(EHScopeStack::stable_iterator cleanup) {
> +      assert(isIndex());
> +      Cleanup = cleanup;
> +    }
> 
>     static Capture makeIndex(unsigned index) {
>       Capture v;
> @@ -158,9 +168,6 @@
>     }    
>   };
> 
> -  /// The mapping of allocated indexes within the block.
> -  llvm::DenseMap<const VarDecl*, Capture> Captures;  
> -
>   /// CanBeGlobal - True if the block can be global, i.e. it has
>   /// no non-constant captures.
>   bool CanBeGlobal : 1;
> @@ -176,22 +183,35 @@
>   /// because it gets set later in the block-creation process.
>   mutable bool UsesStret : 1;
> 
> +  /// The mapping of allocated indexes within the block.
> +  llvm::DenseMap<const VarDecl*, Capture> Captures;  
> +
> +  llvm::AllocaInst *Address;
>   llvm::StructType *StructureType;
> -  const BlockExpr *Block;
> +  const BlockDecl *Block;
> +  const BlockExpr *BlockExpression;
>   CharUnits BlockSize;
>   CharUnits BlockAlign;
> +  CGBlockInfo *NextBlockInfo;
> 
>   const Capture &getCapture(const VarDecl *var) const {
> -    llvm::DenseMap<const VarDecl*, Capture>::const_iterator
> +    return const_cast<CGBlockInfo*>(this)->getCapture(var);
> +  }
> +  Capture &getCapture(const VarDecl *var) {
> +    llvm::DenseMap<const VarDecl*, Capture>::iterator
>       it = Captures.find(var);
>     assert(it != Captures.end() && "no entry for variable!");
>     return it->second;
>   }
> 
> -  const BlockDecl *getBlockDecl() const { return Block->getBlockDecl(); }
> -  const BlockExpr *getBlockExpr() const { return Block; }
> +  const BlockDecl *getBlockDecl() const { return Block; }
> +  const BlockExpr *getBlockExpr() const {
> +    assert(BlockExpression);
> +    assert(BlockExpression->getBlockDecl() == Block);
> +    return BlockExpression;
> +  }
> 
> -  CGBlockInfo(const BlockExpr *blockExpr, const char *Name);
> +  CGBlockInfo(const BlockDecl *blockDecl, llvm::StringRef Name);
> };
> 
> }  // end namespace CodeGen
> 
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Nov 10 02:15:53 2011
> @@ -496,9 +496,11 @@
> 
>   // If we're emitting a value with lifetime, we have to do the
>   // initialization *before* we leave the cleanup scopes.
> -  CodeGenFunction::RunCleanupsScope Scope(*this);
> -  if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init))
> +  if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init)) {
> +    enterFullExpression(ewc);
>     init = ewc->getSubExpr();
> +  }
> +  CodeGenFunction::RunCleanupsScope Scope(*this);
> 
>   // We have to maintain the illusion that the variable is
>   // zero-initialized.  If the variable might be accessed in its
> 
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Nov 10 02:15:53 2011
> @@ -229,10 +229,11 @@
>   if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
>     E = DAE->getExpr();
> 
> -  if (const ExprWithCleanups *TE = dyn_cast<ExprWithCleanups>(E)) {
> +  if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E)) {
> +    CGF.enterFullExpression(EWC);
>     CodeGenFunction::RunCleanupsScope Scope(CGF);
> 
> -    return EmitExprForReferenceBinding(CGF, TE->getSubExpr(), 
> +    return EmitExprForReferenceBinding(CGF, EWC->getSubExpr(), 
>                                        ReferenceTemporary, 
>                                        ReferenceTemporaryDtor,
>                                        ObjCARCReferenceLifetimeType,
> @@ -677,8 +678,14 @@
>     return EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
>   case Expr::CXXBindTemporaryExprClass:
>     return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
> -  case Expr::ExprWithCleanupsClass:
> -    return EmitExprWithCleanupsLValue(cast<ExprWithCleanups>(E));
> +
> +  case Expr::ExprWithCleanupsClass: {
> +    const ExprWithCleanups *cleanups = cast<ExprWithCleanups>(E);
> +    enterFullExpression(cleanups);
> +    RunCleanupsScope Scope(*this);
> +    return EmitLValue(cleanups->getSubExpr());
> +  }
> +
>   case Expr::CXXScalarValueInitExprClass:
>     return EmitNullInitializationLValue(cast<CXXScalarValueInitExpr>(E));
>   case Expr::CXXDefaultArgExprClass:
> 
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Nov 10 02:15:53 2011
> @@ -536,7 +536,9 @@
> }
> 
> void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
> -  CGF.EmitExprWithCleanups(E, Dest);
> +  CGF.enterFullExpression(E);
> +  CodeGenFunction::RunCleanupsScope cleanups(CGF);
> +  Visit(E->getSubExpr());
> }
> 
> void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
> 
> Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Thu Nov 10 02:15:53 2011
> @@ -179,7 +179,9 @@
>     return Visit(DAE->getExpr());
>   }
>   ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
> -    return CGF.EmitExprWithCleanups(E).getComplexVal();
> +    CGF.enterFullExpression(E);
> +    CodeGenFunction::RunCleanupsScope Scope(CGF);
> +    return Visit(E->getSubExpr());
>   }
>   ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
>     assert(E->getType()->isAnyComplexType() && "Expected complex type!");
> 
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Nov 10 02:15:53 2011
> @@ -353,7 +353,9 @@
>   }
> 
>   Value *VisitExprWithCleanups(ExprWithCleanups *E) {
> -    return CGF.EmitExprWithCleanups(E).getScalarVal();
> +    CGF.enterFullExpression(E);
> +    CodeGenFunction::RunCleanupsScope Scope(CGF);
> +    return Visit(E->getSubExpr());
>   }
>   Value *VisitCXXNewExpr(const CXXNewExpr *E) {
>     return CGF.EmitCXXNewExpr(E);
> 
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Thu Nov 10 02:15:53 2011
> @@ -2177,6 +2177,7 @@
> tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) {
>   // Look through cleanups.
>   if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
> +    CGF.enterFullExpression(cleanups);
>     CodeGenFunction::RunCleanupsScope scope(CGF);
>     return tryEmitARCRetainScalarExpr(CGF, cleanups->getSubExpr());
>   }
> @@ -2376,10 +2377,12 @@
>     //   @throw A().foo;
>     // where a full retain+autorelease is required and would
>     // otherwise happen after the destructor for the temporary.
> -    CodeGenFunction::RunCleanupsScope cleanups(*this);
> -    if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(expr))
> +    if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(expr)) {
> +      enterFullExpression(ewc);
>       expr = ewc->getSubExpr();
> +    }
> 
> +    CodeGenFunction::RunCleanupsScope cleanups(*this);
>     return EmitARCRetainAutoreleaseScalarExpr(expr);
>   }
> 
> 
> Modified: cfe/trunk/lib/CodeGen/CGTemporaries.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGTemporaries.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGTemporaries.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGTemporaries.cpp Thu Nov 10 02:15:53 2011
> @@ -35,15 +35,3 @@
>                                         Temporary->getDestructor(),
>                                         Ptr);
> }
> -
> -RValue
> -CodeGenFunction::EmitExprWithCleanups(const ExprWithCleanups *E,
> -                                      AggValueSlot Slot) {
> -  RunCleanupsScope Scope(*this);
> -  return EmitAnyExpr(E->getSubExpr(), Slot);
> -}
> -
> -LValue CodeGenFunction::EmitExprWithCleanupsLValue(const ExprWithCleanups *E) {
> -  RunCleanupsScope Scope(*this);
> -  return EmitLValue(E->getSubExpr());
> -}
> 
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Nov 10 02:15:53 2011
> @@ -33,7 +33,7 @@
>   : CodeGenTypeCache(cgm), CGM(cgm),
>     Target(CGM.getContext().getTargetInfo()), Builder(cgm.getModule().getContext()),
>     AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),
> -    NormalCleanupDest(0), NextCleanupDestIndex(1),
> +    NormalCleanupDest(0), NextCleanupDestIndex(1), FirstBlockInfo(0), 
>     EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),
>     DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),
>     IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
> @@ -45,6 +45,14 @@
>   CGM.getCXXABI().getMangleContext().startNewFunction();
> }
> 
> +CodeGenFunction::~CodeGenFunction() {
> +  // If there are any unclaimed block infos, go ahead and destroy them
> +  // now.  This can happen if IR-gen gets clever and skips evaluating
> +  // something.
> +  if (FirstBlockInfo)
> +    destroyBlockInfos(FirstBlockInfo);
> +}
> +
> 
> llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
>   return CGM.getTypes().ConvertTypeForMem(T);
> 
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Nov 10 02:15:53 2011
> @@ -45,6 +45,7 @@
> namespace clang {
>   class APValue;
>   class ASTContext;
> +  class BlockDecl;
>   class CXXDestructorDecl;
>   class CXXForRangeStmt;
>   class CXXTryStmt;
> @@ -610,6 +611,9 @@
> 
>   unsigned NextCleanupDestIndex;
> 
> +  /// FirstBlockInfo - The head of a singly-linked-list of block layouts.
> +  CGBlockInfo *FirstBlockInfo;
> +
>   /// EHResumeBlock - Unified block containing a call to llvm.eh.resume.
>   llvm::BasicBlock *EHResumeBlock;
> 
> @@ -1169,6 +1173,7 @@
> 
> public:
>   CodeGenFunction(CodeGenModule &cgm);
> +  ~CodeGenFunction();
> 
>   CodeGenTypes &getTypes() const { return CGM.getTypes(); }
>   ASTContext &getContext() const { return CGM.getContext(); }
> @@ -1297,6 +1302,8 @@
>   //===--------------------------------------------------------------------===//
> 
>   llvm::Value *EmitBlockLiteral(const BlockExpr *);
> +  llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
> +  static void destroyBlockInfos(CGBlockInfo *info);
>   llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
>                                            const CGBlockInfo &Info,
>                                            llvm::StructType *,
> @@ -2074,7 +2081,6 @@
> 
>   LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
>   LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
> -  LValue EmitExprWithCleanupsLValue(const ExprWithCleanups *E);
>   LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E);
> 
>   LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E);
> @@ -2348,8 +2354,11 @@
>   void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src,
>                                   const Expr *Exp);
> 
> -  RValue EmitExprWithCleanups(const ExprWithCleanups *E,
> -                              AggValueSlot Slot =AggValueSlot::ignored());
> +  void enterFullExpression(const ExprWithCleanups *E) {
> +    if (E->getNumObjects() == 0) return;
> +    enterNonTrivialFullExpression(E);
> +  }
> +  void enterNonTrivialFullExpression(const ExprWithCleanups *E);
> 
>   void EmitCXXThrowExpr(const CXXThrowExpr *E);
> 
> 
> Modified: cfe/trunk/test/CodeGenObjC/arc-blocks.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-blocks.m?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/arc-blocks.m (original)
> +++ cfe/trunk/test/CodeGenObjC/arc-blocks.m Thu Nov 10 02:15:53 2011
> @@ -25,15 +25,19 @@
> // CHECK:    define void @test2(
> // CHECK:      [[X:%.*]] = alloca i8*,
> // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
> +// CHECK-NEXT: alloca i1
> +// CHECK-NEXT: store i1 false
> // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
> // CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
> +// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]],
> // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
> // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]],
> +// CHECK-NEXT: store i1 true
> // CHECK-NEXT: bitcast
> // CHECK-NEXT: call void @test2_helper(
> -// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]]
> +// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOTREL]]
> // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
> // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
> // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
> @@ -233,8 +237,8 @@
>   // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[VAR]])
>   // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]])
>   // CHECK:      call void @test7_helper(
> -  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
> -  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])
> +  // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}})
> +  // CHECK:      call void @objc_destroyWeak(i8** [[VAR]])
>   // CHECK-NEXT: ret void
> 
>   // CHECK:    define internal void @__test7_block_invoke_
> @@ -262,15 +266,17 @@
> // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
> // CHECK: store
> // CHECK-NEXT: store
> +// CHECK:      [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[SELF]],
> // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
> // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
> // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]*
> // CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]]
> +// CHECK-NEXT: store i1 true,
> // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
> // CHECK: call void @test8_helper(
> -// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[T0]]
> +// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]]
> // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
> // CHECK-NEXT: call void @objc_release(i8* [[T2]])
> // CHECK-NEXT: ret void
> 
> Modified: cfe/trunk/test/CodeGenObjC/arc-foreach.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-foreach.m?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/arc-foreach.m (original)
> +++ cfe/trunk/test/CodeGenObjC/arc-foreach.m Thu Nov 10 02:15:53 2011
> @@ -29,6 +29,9 @@
> // CHECK-LP64-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8
> // CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
> 
> +// CHECK-LP64-NEXT: [[CAP_ACTIVE:%.*]] = alloca i1
> +// CHECK-LP64-NEXT: store i1 false, i1* [[CAP_ACTIVE]]
> +
> // Initialize 'array'.
> // CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[ARRAY_T:%.*]]* {{%.*}} to i8*
> // CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
> @@ -60,13 +63,15 @@
> // CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]]
> // CHECK-LP64-NEXT: store i8* [[T3]], i8** [[X]]
> 
> +// CHECK-LP64:      [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[X]]
> // CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
> // CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]]
> +// CHECK-LP64-NEXT: store i1 true, i1* [[CAP_ACTIVE]]
> // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] 
> // CHECK-LP64: call void @use_block(
> -// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[T0]]
> +// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[D0]]
> // CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]])
> 
> // CHECK-LP64:      [[T0:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_
> @@ -108,13 +113,15 @@
> // CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]]
> // CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T3]])
> 
> +// CHECK-LP64:      [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[X]])
> // CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]])
> +// CHECK-LP64-NEXT: store i1 true,
> // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
> // CHECK-LP64: call void @use_block
> -// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[T0]])
> -// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[X]])
> +// CHECK-LP64:      call void @objc_destroyWeak(i8** [[D0]])
> +// CHECK-LP64:      call void @objc_destroyWeak(i8** [[X]])
> 
> // rdar://problem/9817306
> @interface Test2
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list