[clang] [Clang] allow GNU attrs before bit-field width in member declarators (PR #185322)

Oleksandr Tarasiuk via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 27 07:35:35 PDT 2026


https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/185322

>From 48a54d77e1d3685063fc4748d46d7c93adcb8445 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Sun, 8 Mar 2026 23:24:55 +0200
Subject: [PATCH 1/2] [Clang] allow GNU attrs before bit-field width in member
 declarators

---
 clang/docs/ReleaseNotes.rst          | 2 ++
 clang/lib/Parse/ParseDeclCXX.cpp     | 6 +++++-
 clang/test/Parser/cxx-attributes.cpp | 7 +++++++
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5d07bfc210e05..d1583f9f89ac0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -207,6 +207,8 @@ Attribute Changes in Clang
   type-level control over overflow behavior. There is also an accompanying type
   specifier for each behavior kind via `__ob_wrap` and `__ob_trap`.
 
+- Clang now allows GNU attributes between a member declarator and bit-field width. (#GH184954)
+
 Improvements to Clang's diagnostics
 -----------------------------------
 - Added ``-Wlifetime-safety`` to enable lifetime safety analysis,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 274c354d59808..8c324e0768c71 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2512,11 +2512,15 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
   else
     DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation());
 
+  const bool IsFunctionDeclarator = DeclaratorInfo.isFunctionDeclarator();
+  if (!IsFunctionDeclarator)
+    MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
+
   if (getLangOpts().HLSL)
     MaybeParseHLSLAnnotations(DeclaratorInfo, nullptr,
                               /*CouldBeBitField*/ true);
 
-  if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
+  if (!IsFunctionDeclarator && TryConsumeToken(tok::colon)) {
     assert(DeclaratorInfo.isPastIdentifier() &&
            "don't know where identifier would go yet?");
     BitfieldSize = ParseConstantExpression();
diff --git a/clang/test/Parser/cxx-attributes.cpp b/clang/test/Parser/cxx-attributes.cpp
index cd09f8d11f1a6..d108535ea9b98 100644
--- a/clang/test/Parser/cxx-attributes.cpp
+++ b/clang/test/Parser/cxx-attributes.cpp
@@ -41,6 +41,13 @@ void fn() {
   pi = &i[0];
 }
 
+namespace GH184954 {
+  struct S {
+    int a __attribute__((packed)) : 4;
+    int b __attribute__((aligned(16))) : 4;
+  };
+}
+
 [[deprecated([""])]] int WrongArgs; // expected-error {{expected string literal as argument of 'deprecated' attribute}}
 [[,,,,,]] int Commas1; // ok
 [[,, maybe_unused]] int Commas2; // ok

>From 21b1d5ff4d3b35091676ef35e855757f0fbd8cd2 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Mon, 27 Apr 2026 17:34:22 +0300
Subject: [PATCH 2/2] disallow gnu attrs before bit-field width in msvc

---
 clang/lib/Parse/ParseDeclCXX.cpp     | 2 +-
 clang/test/Parser/cxx-attributes.cpp | 9 ++++++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 8c324e0768c71..636ffae52d673 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2513,7 +2513,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
     DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation());
 
   const bool IsFunctionDeclarator = DeclaratorInfo.isFunctionDeclarator();
-  if (!IsFunctionDeclarator)
+  if (!IsFunctionDeclarator && !getLangOpts().MSVCCompat)
     MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
 
   if (getLangOpts().HLSL)
diff --git a/clang/test/Parser/cxx-attributes.cpp b/clang/test/Parser/cxx-attributes.cpp
index d108535ea9b98..56b3df4ae78c2 100644
--- a/clang/test/Parser/cxx-attributes.cpp
+++ b/clang/test/Parser/cxx-attributes.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,msvc %s -triple x86_64-pc-windows-msvc -fms-compatibility
 
 // GH#58229 - rejects-valid
 __attribute__((__visibility__("default"))) [[nodiscard]] int f();
@@ -43,8 +44,10 @@ void fn() {
 
 namespace GH184954 {
   struct S {
-    int a __attribute__((packed)) : 4;
-    int b __attribute__((aligned(16))) : 4;
+    int a __attribute__((packed)) : 4;       // msvc-error {{expected ';' at end of declaration list}} \
+                                             // msvc-error {{expected member name or ';' after declaration specifiers}}
+    int b __attribute__((aligned(16))) : 4;  // msvc-error {{expected ';' at end of declaration list}} \
+                                             // msvc-error {{expected member name or ';' after declaration specifiers}}
   };
 }
 



More information about the cfe-commits mailing list