]> granicus.if.org Git - clang/commitdiff
Assert during instantiation of blocks that we've captured everything that
authorJohn McCall <rjmccall@apple.com>
Fri, 4 Feb 2011 18:33:18 +0000 (18:33 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 4 Feb 2011 18:33:18 +0000 (18:33 +0000)
we captured in the dependent case.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124887 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/TreeTransform.h

index 3f8d3e5ec4044039e8ce5c174f1d31961463b356..472e281553886d407a0faedd642eb81fe1e28858 100644 (file)
@@ -7136,70 +7136,92 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
-  SourceLocation CaretLoc(E->getExprLoc());
+  BlockDecl *oldBlock = E->getBlockDecl();
   
-  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;
+  SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/0);
+  BlockScopeInfo *blockScope = SemaRef.getCurBlock();
+
+  blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic());
+  llvm::SmallVector<ParmVarDecl*, 4> params;
+  llvm::SmallVector<QualType, 4> paramTypes;
   
   // Parameter substitution.
-  BlockDecl *BD = E->getBlockDecl();
-  if (getDerived().TransformFunctionTypeParams(E->getLocStart(), 
-                                               BD->param_begin(),
-                                               BD->param_size(), 0, ParamTypes,
-                                               &Params))
+  if (getDerived().TransformFunctionTypeParams(E->getCaretLocation(),
+                                               oldBlock->param_begin(),
+                                               oldBlock->param_size(),
+                                               0, paramTypes, &params))
     return true;
-  
-  
-  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);
+
+  const FunctionType *exprFunctionType = E->getFunctionType();
+  QualType exprResultType = exprFunctionType->getResultType();
+  if (!exprResultType.isNull()) {
+    if (!exprResultType->isDependentType())
+      blockScope->ReturnType = exprResultType;
+    else if (exprResultType != getSema().Context.DependentTy)
+      blockScope->ReturnType = getDerived().TransformType(exprResultType);
   }
   
   // If the return type has not been determined yet, leave it as a dependent
   // type; it'll get set when we process the body.
-  if (CurBlock->ReturnType.isNull())
-    CurBlock->ReturnType = getSema().Context.DependentTy;
+  if (blockScope->ReturnType.isNull())
+    blockScope->ReturnType = getSema().Context.DependentTy;
 
   // Don't allow returning a objc interface by value.
-  if (CurBlock->ReturnType->isObjCObjectType()) {
-    getSema().Diag(E->getLocStart(), 
+  if (blockScope->ReturnType->isObjCObjectType()) {
+    getSema().Diag(E->getCaretLocation(), 
                    diag::err_object_cannot_be_passed_returned_by_value) 
-      << 0 << CurBlock->ReturnType;
+      << 0 << blockScope->ReturnType;
     return ExprError();
   }
 
-  QualType FunctionType = getDerived().RebuildFunctionProtoType(
-                                                        CurBlock->ReturnType,
-                                                        ParamTypes.data(),
-                                                        ParamTypes.size(),
-                                                        BD->isVariadic(),
+  QualType functionType = getDerived().RebuildFunctionProtoType(
+                                                        blockScope->ReturnType,
+                                                        paramTypes.data(),
+                                                        paramTypes.size(),
+                                                        oldBlock->isVariadic(),
                                                         0, RQ_None,
-                                               BExprFunctionType->getExtInfo());
-  CurBlock->FunctionType = FunctionType;
+                                               exprFunctionType->getExtInfo());
+  blockScope->FunctionType = functionType;
 
   // Set the parameters on the block decl.
-  if (!Params.empty())
-    CurBlock->TheDecl->setParams(Params.data(), Params.size());
+  if (!params.empty())
+    blockScope->TheDecl->setParams(params.data(), params.size());
   
   // If the return type wasn't explicitly set, it will have been marked as a 
   // dependent type (DependentTy); clear out the return type setting so 
   // we will deduce the return type when type-checking the block's body.
-  if (CurBlock->ReturnType == getSema().Context.DependentTy)
-    CurBlock->ReturnType = QualType();
+  if (blockScope->ReturnType == getSema().Context.DependentTy)
+    blockScope->ReturnType = QualType();
   
   // Transform the body
-  StmtResult Body = getDerived().TransformStmt(E->getBody());
-  if (Body.isInvalid())
+  StmtResult body = getDerived().TransformStmt(E->getBody());
+  if (body.isInvalid())
     return ExprError();
 
-  return SemaRef.ActOnBlockStmtExpr(CaretLoc, Body.get(), /*Scope=*/0);
+#ifndef NDEBUG
+  // In builds with assertions, make sure that we captured everything we
+  // captured before.
+
+  if (oldBlock->capturesCXXThis()) assert(blockScope->CapturesCXXThis);
+
+  for (BlockDecl::capture_iterator i = oldBlock->capture_begin(),
+         e = oldBlock->capture_end(); i != e; ++i) {
+    VarDecl *oldCapture = *i;
+
+    // Ignore parameter packs.
+    if (isa<ParmVarDecl>(oldCapture) &&
+        cast<ParmVarDecl>(oldCapture)->isParameterPack())
+      continue;
+
+    VarDecl *newCapture =
+      cast<VarDecl>(getDerived().TransformDecl(E->getCaretLocation(),
+                                               oldCapture));
+    assert(blockScope->Captures.count(newCapture));
+  }
+#endif
+
+  return SemaRef.ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
+                                    /*Scope=*/0);
 }
 
 template<typename Derived>