diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -663,6 +663,10 @@ - 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 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17159,6 +17159,9 @@ 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 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3730,6 +3730,11 @@ 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 --- 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 @@ // 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 (^a)() = ^() { + return c; +};