danix800 created this revision.
danix800 added a reviewer: aaron.ballman.
danix800 added a project: clang.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Fix https://github.com/llvm/llvm-project/issues/63863


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155396

Files:
  clang/include/clang/AST/ComputeDependence.h
  clang/include/clang/AST/Expr.h
  clang/lib/AST/ComputeDependence.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaObjC/crash-on-val-dep-block-expr.m


Index: clang/test/SemaObjC/crash-on-val-dep-block-expr.m
===================================================================
--- /dev/null
+++ 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'}}
+});
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ 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:
Index: clang/lib/AST/ComputeDependence.cpp
===================================================================
--- clang/lib/AST/ComputeDependence.cpp
+++ 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;
 }
 
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ 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.
Index: clang/include/clang/AST/ComputeDependence.h
===================================================================
--- clang/include/clang/AST/ComputeDependence.h
+++ 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);


Index: clang/test/SemaObjC/crash-on-val-dep-block-expr.m
===================================================================
--- /dev/null
+++ 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'}}
+});
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ 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:
Index: clang/lib/AST/ComputeDependence.cpp
===================================================================
--- clang/lib/AST/ComputeDependence.cpp
+++ 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;
 }
 
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ 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.
Index: clang/include/clang/AST/ComputeDependence.h
===================================================================
--- clang/include/clang/AST/ComputeDependence.h
+++ 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);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to