From 106bde9ab2bdffb2409311ef2d4f2c3c9ca77d3f Mon Sep 17 00:00:00 2001 From: dingfei Date: Mon, 24 Jul 2023 18:21:14 +0800 Subject: [PATCH] [Sema][ObjC] Invalidate BlockDecl with invalid return expr & its parent BlockExpr Invalidate BlockDecl with implicit return type, in case any of the return value exprs is invalid. Propagating the error info up by replacing BlockExpr with a RecoveryExpr. The idea of this fix is given by @hokein(Haojian Wu) Fix https://github.com/llvm/llvm-project/issues/63863. Differential Revision: https://reviews.llvm.org/D155396 --- clang/docs/ReleaseNotes.rst | 4 ++++ clang/lib/Sema/SemaExpr.cpp | 3 +++ clang/lib/Sema/SemaStmt.cpp | 5 +++++ clang/test/AST/ast-dump-recovery.m | 10 +++++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8e19b3695ef49e..e686e83583919f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -670,6 +670,10 @@ Bug Fixes in This Version - Correcly diagnose jumps into statement expressions. This ensures the behavior of Clang is consistent with GCC. (`#63682 `_) +- Invalidate BlockDecl with implicit return type, in case any of the return + value exprs is invalid. Propagating the error info up by replacing BlockExpr + with a RecoveryExpr. This fixes: + (`#63863 _`) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 240f1520efad2b..3c9d0efca8a1ee 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17159,6 +17159,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (getCurFunction()) getCurFunction()->addBlock(BD); + if (BD->isInvalidDecl()) + return CreateRecoveryExpr(Result->getBeginLoc(), Result->getEndLoc(), + {Result}, Result->getType()); return Result; } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 5657771a145189..70a549938d080d 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3730,6 +3730,11 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, if (FunctionScopes.back()->FirstReturnLoc.isInvalid()) FunctionScopes.back()->FirstReturnLoc = ReturnLoc; + if (auto *CurBlock = dyn_cast(CurCap); + CurBlock && CurCap->HasImplicitReturnType && RetValExp && + RetValExp->containsErrors()) + CurBlock->TheDecl->setInvalidDecl(); + return Result; } diff --git a/clang/test/AST/ast-dump-recovery.m b/clang/test/AST/ast-dump-recovery.m index 5ca866a0282fdf..c2bd078959aba1 100644 --- a/clang/test/AST/ast-dump-recovery.m +++ b/clang/test/AST/ast-dump-recovery.m @@ -1,4 +1,4 @@ -// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -frecovery-ast -frecovery-ast-type -ast-dump %s | FileCheck -strict-whitespace %s +// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -frecovery-ast -frecovery-ast-type -fblocks -ast-dump %s | FileCheck -strict-whitespace %s @interface Foo - (void)method:(int)n; @@ -16,3 +16,11 @@ void k(Foo *foo) { // CHECK-NEXT: `-DeclRefExpr {{.*}} 'foo' foo.undef; } + +// CHECK: |-VarDecl {{.*}} 'int (^)()' cinit +// CHECK-NEXT: | `-RecoveryExpr {{.*}} ' (^)(void)' contains-errors lvalue +// CHECK-NEXT: | `-BlockExpr {{.*}} ' (^)(void)' +// CHECK-NEXT: | `-BlockDecl {{.*}} invalid +int (^gh63863)() = ^() { + return undef; +};