diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2010-07-09 18:44:02 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2010-07-09 18:44:02 +0000 |
commit | a729da2c29e7df26319acf2675d51e377287a139 (patch) | |
tree | 30b30dd974b6cb972cb06ef3424f63c424ce62df | |
parent | 52ddc5df59a26570fbca47d269f82954ae3397d1 (diff) |
Instantiation of block literal expressions. wip.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108000 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 74 | ||||
-rw-r--r-- | test/CodeGenCXX/instantiate-blocks.cpp | 29 |
4 files changed, 103 insertions, 9 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 1f948b6624..01fc1c1f12 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -158,7 +158,7 @@ struct BlockScopeInfo : FunctionScopeInfo { bool hasBlockDeclRefExprs; BlockDecl *TheDecl; - + /// TheScope - This is the scope for the block itself, which contains /// arguments etc. Scope *TheScope; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 66369674f2..dfa472cc26 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7074,7 +7074,10 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); PushBlockScope(BlockScope, Block); CurContext->addDecl(Block); - PushDeclContext(BlockScope, Block); + if (BlockScope) + PushDeclContext(BlockScope, Block); + else + CurContext = Block; } void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { @@ -7199,7 +7202,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Diag(CaretLoc, diag::err_blocks_disable); BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back()); - + PopDeclContext(); QualType RetTy = Context.VoidTy; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 95e304eb44..db5e2d10f4 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -4198,6 +4198,10 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { if (!ND) return SemaRef.ExprError(); + // Set DeclContext if inside a Block. + if (BlockScopeInfo *CurBlock = SemaRef.getCurBlock()) + ND->setDeclContext(CurBlock->TheDecl); + if (!getDerived().AlwaysRebuild() && Qualifier == E->getQualifier() && ND == E->getDecl() && @@ -6217,17 +6221,75 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { - // FIXME: Implement this! - assert(false && "Cannot transform block expressions yet"); - return SemaRef.Owned(E->Retain()); + SourceLocation CaretLoc(E->getExprLoc()); + + SemaRef.ActOnBlockStart(CaretLoc, /*Scope=*/0); + BlockScopeInfo *CurBlock = SemaRef.getCurBlock(); + CurBlock->TheDecl->setIsVariadic(E->getBlockDecl()->isVariadic()); + llvm::SmallVector<ParmVarDecl*, 4> Params; + llvm::SmallVector<QualType, 4> ParamTypes; + + // Parameter substitution. + const BlockDecl *BD = E->getBlockDecl(); + for (BlockDecl::param_const_iterator P = BD->param_begin(), + EN = BD->param_end(); P != EN; ++P) { + ParmVarDecl *OldParm = (*P); + ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm); + QualType NewType = NewParm->getType(); + Params.push_back(NewParm); + ParamTypes.push_back(NewParm->getType()); + } + + const FunctionType *BExprFunctionType = E->getFunctionType(); + QualType BExprResultType = BExprFunctionType->getResultType(); + if (!BExprResultType.isNull()) { + if (!BExprResultType->isDependentType()) + CurBlock->ReturnType = BExprResultType; + else if (BExprResultType != SemaRef.Context.DependentTy) + CurBlock->ReturnType = getDerived().TransformType(BExprResultType); + } + + // Transform the body + OwningStmtResult Body = getDerived().TransformStmt(E->getBody()); + if (Body.isInvalid()) + return SemaRef.ExprError(); + // Set the parameters on the block decl. + if (!Params.empty()) + CurBlock->TheDecl->setParams(Params.data(), Params.size()); + + QualType FunctionType = getDerived().RebuildFunctionProtoType( + CurBlock->ReturnType, + ParamTypes.data(), + ParamTypes.size(), + BD->isVariadic(), + 0); + + CurBlock->FunctionType = FunctionType; + return SemaRef.ActOnBlockStmtExpr(CaretLoc, move(Body), /*Scope=*/0); } template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { - // FIXME: Implement this! - assert(false && "Cannot transform block-related expressions yet"); - return SemaRef.Owned(E->Retain()); + NestedNameSpecifier *Qualifier = 0; + + ValueDecl *ND + = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(), + E->getDecl())); + if (!ND) + return SemaRef.ExprError(); + + if (!getDerived().AlwaysRebuild() && + ND == E->getDecl()) { + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); + + return SemaRef.Owned(E->Retain()); + } + + return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(), + ND, E->getLocation(), 0); } //===----------------------------------------------------------------------===// diff --git a/test/CodeGenCXX/instantiate-blocks.cpp b/test/CodeGenCXX/instantiate-blocks.cpp new file mode 100644 index 0000000000..8c1c8dd234 --- /dev/null +++ b/test/CodeGenCXX/instantiate-blocks.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fblocks -emit-llvm -o - %s +// rdar : // 6182276 + +template <typename T> T foo(T t) +{ + void (^block)(int); + return 1; +} + +int test1(void) +{ + int i = 1; + int b = 2; + i = foo(b); + return 0; +} + +template <typename T, typename T1> void foo(T t, T1 r) +{ + T block_arg; + T1 (^block)(char, T, T1, double) = ^ T1 (char ch, T arg, T1 arg2, double d1) { return block_arg+arg; }; + + void (^block2)() = ^{}; +} + +void test2(void) +{ + foo(100, 'a'); +} |