diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 441c54dc358..f5ba87f635d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11826,8 +11826,37 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { QualType type = var->getType(); if (type->isDependentType()) return; - if (var->hasAttr<BlocksAttr>()) - getCurFunction()->addByrefBlockVar(var); + // __block variables might require us to capture a copy-initializer. + if (var->hasAttr<BlocksAttr>()) { + // It's currently invalid to ever have a __block variable with an + // array type; should we diagnose that here? + + // Regardless, we don't want to ignore array nesting when + // constructing this copy. + if (type->isStructureOrClassType()) { + EnterExpressionEvaluationContext scope( + *this, ExpressionEvaluationContext::PotentiallyEvaluated); + SourceLocation poi = var->getLocation(); + Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi); + ExprResult result + = PerformMoveOrCopyInitialization( + InitializedEntity::InitializeBlock(poi, type, false), + var, var->getType(), varRef, /*AllowNRVO=*/true); + if (!result.isInvalid()) { + result = MaybeCreateExprWithCleanups(result); + Expr *init = result.getAs<Expr>(); + Context.setBlockVarCopyInit(var, init, canThrow(init)); + } + + // The destructor's exception spefication is needed when IRGen generates + // block copy/destroy functions. Resolve it here. + if (const CXXRecordDecl *RD = type->getAsCXXRecordDecl()) + if (CXXDestructorDecl *DD = RD->getDestructor()) { + auto *FPT = DD->getType()->getAs<FunctionProtoType>(); + FPT = ResolveExceptionSpec(poi, FPT); + } + } + } Expr *Init = var->getInit(); bool IsGlobal = GlobalStorage && !var->isStaticLocal(); |