Instantiation of block literal expressions. wip.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108000 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 1f948b6..01fc1c1 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -158,7 +158,7 @@
   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 6636967..dfa472c 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -7074,7 +7074,10 @@
   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 @@
     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 95e304e..db5e2d1 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -4198,6 +4198,10 @@
   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 @@
 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);
 }
 
 //===----------------------------------------------------------------------===//