[clang] [Clang] Improve __block attribute coverage for ivars and static variables (PR #198167)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 18 10:04:17 PDT 2026
https://github.com/TPPPP72 updated https://github.com/llvm/llvm-project/pull/198167
>From 5c90fe214c8b017faefbabe6b3a7a9463e1e6f86 Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Mon, 18 May 2026 13:46:11 +0800
Subject: [PATCH 1/4] [Clang] Improve __block attribute coverage for ivars and
static variables
---
.../clang/Basic/DiagnosticSemaKinds.td | 13 +++++++---
clang/lib/Sema/SemaDecl.cpp | 10 ++++---
clang/lib/Sema/SemaDeclObjC.cpp | 7 +++--
clang/lib/Sema/SemaObjC.cpp | 26 ++++++++++++++++---
clang/test/Sema/block-misc.c | 16 +++++++-----
clang/test/Sema/block-on-objc-ivars.m | 11 --------
clang/test/Sema/block.m | 11 ++++++++
clang/test/Sema/gh183974.c | 2 +-
clang/test/SemaCXX/blocks.cpp | 6 +++++
9 files changed, 71 insertions(+), 31 deletions(-)
delete mode 100644 clang/test/Sema/block-on-objc-ivars.m
create mode 100644 clang/test/Sema/block.m
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d7dd20d6a45e4..c1f2dc21df15c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11379,10 +11379,15 @@ def note_carries_dependency_missing_first_decl : Note<
def err_carries_dependency_param_not_function_decl : Error<
"'[[carries_dependency]]' attribute only allowed on parameter in a function "
"declaration or lambda">;
-def err_block_on_nonlocal : Error<
- "__block attribute not allowed, only allowed on local variables">;
-def err_block_on_vm : Error<
- "__block attribute not allowed on declaration with a variably modified type">;
+def err_block_not_allowed_on : Error<
+ "'__block' is not allowed on %enum_select<NotAllowedBlockVarReason>{"
+ "%NonlocalVariable{a nonlocal variable}|"
+ "%StaticLocalVariable{a static local variable}|"
+ "%CppStaticDataMember{a C++ static data member}|"
+ "%ObjCInstanceVariable{an Objective-C instance variable}|"
+ "%RegisterVariable{a 'register' variable}|"
+ "%VariablyModifiedType{a declaration with a variably modified type}|"
+ "}0">;
def err_sizeless_nonlocal : Error<
"non-local variable with sizeless type %0">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4b9576479e29e..12288abb26d0d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -31,6 +31,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticComment.h"
+#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/HLSLRuntime.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
@@ -9161,7 +9162,8 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
if (isVM && NewVD->hasAttr<BlocksAttr>()) {
- Diag(NewVD->getLocation(), diag::err_block_on_vm);
+ Diag(NewVD->getLocation(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::VariablyModifiedType;
NewVD->setInvalidDecl();
return;
}
@@ -15795,9 +15797,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D,
<< 1 << New << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
- if (New->hasAttr<BlocksAttr>()) {
- Diag(New->getLocation(), diag::err_block_on_nonlocal);
- }
+ if (New->hasAttr<BlocksAttr>())
+ Diag(New->getLocation(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::NonlocalVariable;
New->deduceParmAddressSpace(Context);
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 53ff818a2af53..5ceccc3777409 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
@@ -4769,7 +4770,8 @@ ParmVarDecl *SemaObjC::ActOnMethodParmDeclaration(Scope *S,
SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param, ArgInfo.ArgAttrs);
SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param);
if (Param->hasAttr<BlocksAttr>()) {
- Diag(Param->getLocation(), diag::err_block_on_nonlocal);
+ Diag(Param->getLocation(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::NonlocalVariable;
Param->setInvalidDecl();
}
@@ -5254,7 +5256,8 @@ Decl *SemaObjC::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
SemaRef.ProcessDeclAttributes(S, New, D);
if (New->hasAttr<BlocksAttr>())
- Diag(New->getLocation(), diag::err_block_on_nonlocal);
+ Diag(New->getLocation(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::NonlocalVariable;
return New;
}
diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp
index c351e1e2079c1..32c58bf1e6641 100644
--- a/clang/lib/Sema/SemaObjC.cpp
+++ b/clang/lib/Sema/SemaObjC.cpp
@@ -1711,9 +1711,29 @@ void SemaObjC::handleBlocksAttr(Decl *D, const ParsedAttr &AL) {
return;
}
- VarDecl *VD = dyn_cast<VarDecl>(D);
- if (VD && !VD->hasLocalStorage()) {
- Diag(AL.getLoc(), diag::err_block_on_nonlocal) << AL;
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->getStorageClass() == SC_Register) {
+ Diag(AL.getLoc(), diag::err_block_not_allowed_on) << diag::NotAllowedBlockVarReason::RegisterVariable;
+ return;
+ }
+
+ if (!VD->hasLocalStorage()) {
+ if (VD->isStaticLocal())
+ Diag(AL.getLoc(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::StaticLocalVariable;
+ else if (VD->isStaticDataMember())
+ Diag(AL.getLoc(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::CppStaticDataMember;
+ else
+ Diag(AL.getLoc(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::NonlocalVariable;
+ return;
+ }
+ }
+
+ if (isa<ObjCIvarDecl>(D)) {
+ Diag(AL.getLoc(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::ObjCInstanceVariable;
return;
}
diff --git a/clang/test/Sema/block-misc.c b/clang/test/Sema/block-misc.c
index c8a34b7f3c9fd..6cea409cb684d 100644
--- a/clang/test/Sema/block-misc.c
+++ b/clang/test/Sema/block-misc.c
@@ -144,14 +144,14 @@ void test15(void) {
foo(^{ return LESS; }); // expected-error {{incompatible block pointer types passing 'int (^)(void)' to parameter of type 'long (^)()'}}
}
-__block int test16i; // expected-error {{__block attribute not allowed, only allowed on local variables}}
+__block int test16i; // expected-error {{'__block' is not allowed on a nonlocal variable}}
-void test16(__block int i) { // expected-error {{__block attribute not allowed, only allowed on local variables}}
+void test16(__block int i) { // expected-error {{'__block' is not allowed on a nonlocal variable}}
int size = 5;
- extern __block double extern_var; // expected-error {{__block attribute not allowed, only allowed on local variables}}
- static __block char * pch; // expected-error {{__block attribute not allowed, only allowed on local variables}}
- __block int a[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}}
- __block int (*ap)[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}}
+ extern __block double extern_var; // expected-error {{'__block' is not allowed on a nonlocal variable}}
+ static __block char * pch; // expected-error {{'__block' is not allowed on a static local variable}}
+ __block int a[size]; // expected-error {{'__block' is not allowed on a declaration with a variably modified type}}
+ __block int (*ap)[size]; // expected-error {{'__block' is not allowed on a declaration with a variably modified type}}
}
void f();
@@ -219,3 +219,7 @@ void test21(void) {
const char * (^func)(void) = ^{ return __func__; };
const char * (^function)(void) = ^{ return __FUNCTION__; };
const char * (^pretty)(void) = ^{ return __PRETTY_FUNCTION__; };
+
+void test22(void){
+ register __block int x; // expected-error {{'__block' is not allowed on a 'register' variable}}
+}
diff --git a/clang/test/Sema/block-on-objc-ivars.m b/clang/test/Sema/block-on-objc-ivars.m
deleted file mode 100644
index f37dc12fc109c..0000000000000
--- a/clang/test/Sema/block-on-objc-ivars.m
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %clang_cc1 -fblocks -fsyntax-only -verify %s
-
- at interface MyClass {
- // expected-warning at -1 {{class 'MyClass' defined without specifying a base class}}
- // expected-note at -2 {{add a super class to fix this problem}}
- __block int _myIvar;
-}
- at end
-
- at implementation MyClass
- at end
diff --git a/clang/test/Sema/block.m b/clang/test/Sema/block.m
new file mode 100644
index 0000000000000..3e828a44375af
--- /dev/null
+++ b/clang/test/Sema/block.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
+
+ at interface X {
+ // expected-warning at -1 {{class 'X' defined without specifying a base class}}
+ // expected-note at -2 {{add a super class to fix this problem}}
+ __block int x; // expected-error {{'__block' is not allowed on an Objective-C instance variable}}
+}
+ at end
+
+ at implementation X
+ at end
diff --git a/clang/test/Sema/gh183974.c b/clang/test/Sema/gh183974.c
index 642a622761f69..0e1c519c5ec90 100644
--- a/clang/test/Sema/gh183974.c
+++ b/clang/test/Sema/gh183974.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify %s
-__block int x; // expected-error {{__block attribute not allowed, only allowed on local variables}}
+__block int x; // expected-error {{'__block' is not allowed on a nonlocal variable}}
int x;
diff --git a/clang/test/SemaCXX/blocks.cpp b/clang/test/SemaCXX/blocks.cpp
index 67ac7d42f52c9..e91751ac43e7e 100644
--- a/clang/test/SemaCXX/blocks.cpp
+++ b/clang/test/SemaCXX/blocks.cpp
@@ -164,6 +164,12 @@ void static_data_member() {
};
}
+namespace test8{
+ class X{
+ __block static int x; // expected-error {{'__block' is not allowed on a C++ static data member}}
+ };
+}
+
namespace gh189247 {
template<void (^)()> struct A; // expected-error {{a non-type template parameter cannot have type 'void (^)()'}}
}
>From 234a699b7668d36b1607d2610bfc0e9f611e3fce Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Mon, 18 May 2026 13:47:44 +0800
Subject: [PATCH 2/4] remove uncessnary header
---
clang/lib/Sema/SemaDecl.cpp | 1 -
clang/lib/Sema/SemaDeclObjC.cpp | 1 -
2 files changed, 2 deletions(-)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 12288abb26d0d..0059516649a86 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -31,7 +31,6 @@
#include "clang/AST/Type.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticComment.h"
-#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/HLSLRuntime.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 5ceccc3777409..04ba528098af4 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -18,7 +18,6 @@
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
>From 3cbef2dc70132b3e96fddf90fd814c34ad2f54cf Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Mon, 18 May 2026 15:46:20 +0800
Subject: [PATCH 3/4] fix ci
---
clang/lib/Sema/SemaObjC.cpp | 3 ++-
clang/test/{Sema/block.m => SemaObjC/block-on-ivar.m} | 0
clang/test/SemaObjC/block-on-method-param.m | 4 ++--
3 files changed, 4 insertions(+), 3 deletions(-)
rename clang/test/{Sema/block.m => SemaObjC/block-on-ivar.m} (100%)
diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp
index 32c58bf1e6641..9adba1943cf2a 100644
--- a/clang/lib/Sema/SemaObjC.cpp
+++ b/clang/lib/Sema/SemaObjC.cpp
@@ -1713,7 +1713,8 @@ void SemaObjC::handleBlocksAttr(Decl *D, const ParsedAttr &AL) {
if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->getStorageClass() == SC_Register) {
- Diag(AL.getLoc(), diag::err_block_not_allowed_on) << diag::NotAllowedBlockVarReason::RegisterVariable;
+ Diag(AL.getLoc(), diag::err_block_not_allowed_on)
+ << diag::NotAllowedBlockVarReason::RegisterVariable;
return;
}
diff --git a/clang/test/Sema/block.m b/clang/test/SemaObjC/block-on-ivar.m
similarity index 100%
rename from clang/test/Sema/block.m
rename to clang/test/SemaObjC/block-on-ivar.m
diff --git a/clang/test/SemaObjC/block-on-method-param.m b/clang/test/SemaObjC/block-on-method-param.m
index 2ef44abc5d85a..e5cec086cc06a 100644
--- a/clang/test/SemaObjC/block-on-method-param.m
+++ b/clang/test/SemaObjC/block-on-method-param.m
@@ -2,10 +2,10 @@
// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s
@interface I
-- (void) compileSandboxProfileAndReturnError:(__attribute__((__blocks__(byref))) id)errorp; // expected-error {{__block attribute not allowed, only allowed on local variables}}
+- (void) compileSandboxProfileAndReturnError:(__attribute__((__blocks__(byref))) id)errorp; // expected-error {{'__block' is not allowed on a nonlocal variable}}
@end
@implementation I
-- (void) compileSandboxProfileAndReturnError:(__attribute__((__blocks__(byref))) id)errorp {} // expected-error {{__block attribute not allowed, only allowed on local variables}}
+- (void) compileSandboxProfileAndReturnError:(__attribute__((__blocks__(byref))) id)errorp {} // expected-error {{'__block' is not allowed on a nonlocal variable}}
@end
>From 435f9f4afa8401488d83ebfd3ff4e15faa5c802c Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Tue, 19 May 2026 01:02:59 +0800
Subject: [PATCH 4/4] add releasenote
---
clang/docs/ReleaseNotes.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f5660f9670eae..d644da8f49c16 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -506,6 +506,8 @@ Improvements to Clang's diagnostics
- Added ``-Wattribute-alias`` to diagnose type mismatches between an alias and its aliased function. (#GH195550)
+- Improved ``__block`` attribute coverage for ivars, static variables and register variables. (#GH197213)
+
Improvements to Clang's time-trace
----------------------------------
More information about the cfe-commits
mailing list