diff --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h --- a/clang/include/clang/AST/ComputeDependence.h +++ b/clang/include/clang/AST/ComputeDependence.h @@ -131,7 +131,7 @@ ExprDependence computeDependence(ImplicitValueInitExpr *E); ExprDependence computeDependence(InitListExpr *E); ExprDependence computeDependence(ExtVectorElementExpr *E); -ExprDependence computeDependence(BlockExpr *E); +ExprDependence computeDependence(BlockExpr *E, bool ContainsError); ExprDependence computeDependence(AsTypeExpr *E); ExprDependence computeDependence(DeclRefExpr *E, const ASTContext &Ctx); ExprDependence computeDependence(RecoveryExpr *E); diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -5974,9 +5974,9 @@ protected: BlockDecl *TheBlock; public: - BlockExpr(BlockDecl *BD, QualType ty) + BlockExpr(BlockDecl *BD, QualType ty, bool ContainsError = false) : Expr(BlockExprClass, ty, VK_PRValue, OK_Ordinary), TheBlock(BD) { - setDependence(computeDependence(this)); + setDependence(computeDependence(this, ContainsError)); } /// Build an empty block expression. diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -252,10 +252,12 @@ return E->getBase()->getDependence(); } -ExprDependence clang::computeDependence(BlockExpr *E) { +ExprDependence clang::computeDependence(BlockExpr *E, bool ContainsError) { auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); if (E->getBlockDecl()->isDependentContext()) D |= ExprDependence::Instantiation; + if ((D & ExprDependence::Value) && ContainsError) + D |= ExprDependence::Error; return D; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16746,7 +16746,11 @@ AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy); - BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy); + bool ContainsError = llvm::any_of(BSI->Returns, [](const ReturnStmt *Return) { + const auto *RetValExpr = Return->getRetValue(); + return RetValExpr && RetValExpr->containsErrors(); + }); + BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy, ContainsError); // If the block isn't obviously global, i.e. it captures anything at // all, then we need to do a few things in the surrounding context: diff --git a/clang/test/SemaObjC/crash-on-val-dep-block-expr.m b/clang/test/SemaObjC/crash-on-val-dep-block-expr.m new file mode 100644 --- /dev/null +++ b/clang/test/SemaObjC/crash-on-val-dep-block-expr.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fblocks -fsyntax-only -verify %s +// no crash + +int (^a)() = ^() { + return c; // expected-error {{use of undeclared identifier 'c'}} +}; + +int (^b)() = (^() { + return c; // expected-error {{use of undeclared identifier 'c'}} +});