-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Fix a regression with alignas on structure members in C #98642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix a regression with alignas on structure members in C #98642
Conversation
This was a 19.x regression and thus has no release note. Fixes llvm#95032
@llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesThis was a 19.x regression and thus has no release note. Fixes #95032 Full diff: https://github.com/llvm/llvm-project/pull/98642.diff 5 Files Affected:
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 9c22c35535ede..1dd9781bba5ea 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -2042,7 +2042,8 @@ class Declarator {
assert(llvm::all_of(DeclarationAttrs,
[](const ParsedAttr &AL) {
return (AL.isStandardAttributeSyntax() ||
- AL.isRegularKeywordAttribute());
+ AL.isRegularKeywordAttribute() ||
+ AL.isAlignas());
}) &&
"DeclarationAttrs may only contain [[]] and keyword attributes");
}
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 7ce9a9cea1c7a..ae1801f8a572a 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4919,6 +4919,16 @@ void Parser::ParseStructDeclaration(
// Parse the common specifier-qualifiers-list piece.
ParseSpecifierQualifierList(DS);
+ // FIXME: _Alignas has special handling that really shouldn't be necessary.
+ // Loop over all the attributes on the specifier qualifier, find any that
+ // are alignment attributes, and shift those off the specifier qualifier and
+ // onto the declarator.
+ ParsedAttributes &DSAttrs = DS.getAttributes();
+ for (auto &PAttr : DSAttrs) {
+ if (PAttr.isAlignas())
+ Attrs.takeOneFrom(DSAttrs, &PAttr);
+ }
+
// If there are no declarators, this is a free-standing declaration
// specifier. Let the actions module cope with it.
if (Tok.is(tok::semi)) {
diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp
index 6abc90336c994..2109494aa5889 100644
--- a/clang/lib/Sema/ParsedAttr.cpp
+++ b/clang/lib/Sema/ParsedAttr.cpp
@@ -225,7 +225,7 @@ bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
// atributes.
return false;
- assert(isStandardAttributeSyntax());
+ assert(isStandardAttributeSyntax() || isAlignas());
// We have historically allowed some type attributes with standard attribute
// syntax to slide to the decl-specifier-seq, so we have to keep supporting
diff --git a/clang/test/C/C2y/n3254.c b/clang/test/C/C2y/n3254.c
index e08659cf377aa..347360a87faed 100644
--- a/clang/test/C/C2y/n3254.c
+++ b/clang/test/C/C2y/n3254.c
@@ -80,9 +80,9 @@ struct T {
// CHECK-LABEL: define dso_local signext i8 @quux(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_T:%.*]], align 1
+// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_T:%.*]], align 4
// CHECK-NEXT: [[S_PTR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[T]], i8 0, i64 12, i1 false)
+// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[T]], i8 0, i64 12, i1 false)
// CHECK-NEXT: [[BUFFER:%.*]] = getelementptr inbounds [[STRUCT_T]], ptr [[T]], i32 0, i32 0
// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [12 x i8], ptr [[BUFFER]], i64 0, i64 0
// CHECK-NEXT: store ptr [[ARRAYDECAY]], ptr [[S_PTR]], align 8
diff --git a/clang/test/Sema/alignas.c b/clang/test/Sema/alignas.c
index 020eff6a141c0..391553bc540ec 100644
--- a/clang/test/Sema/alignas.c
+++ b/clang/test/Sema/alignas.c
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -Dalignof=__alignof %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -Dalignof=_Alignof -DUSING_C11_SYNTAX %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 -DUSING_C11_SYNTAX %s
_Alignas(3) int align_illegal; //expected-error {{requested alignment is not a power of 2}}
_Alignas(int) char align_big;
@@ -18,12 +19,24 @@ void f(_Alignas(1) char c) { // expected-error {{'_Alignas' attribute cannot be
}
#ifdef USING_C11_SYNTAX
-// expected-warning@+4{{'_Alignof' applied to an expression is a GNU extension}}
-// expected-warning@+4{{'_Alignof' applied to an expression is a GNU extension}}
-// expected-warning@+4{{'_Alignof' applied to an expression is a GNU extension}}
+// expected-warning-re@+4{{'{{(_A|a)}}lignof' applied to an expression is a GNU extension}}
+// expected-warning-re@+4{{'{{(_A|a)}}lignof' applied to an expression is a GNU extension}}
+// expected-warning-re@+4{{'{{(_A|a)}}lignof' applied to an expression is a GNU extension}}
#endif
_Static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong");
_Static_assert(alignof(align_small) == 1, "j's alignment is wrong");
_Static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
_Static_assert(alignof(struct align_member) == 8, "quuux's alignment is wrong");
_Static_assert(sizeof(struct align_member) == 8, "quuux's size is wrong");
+
+struct GH95032_1 {
+ _Alignas(16) char bytes[16];
+};
+_Static_assert(_Alignof(struct GH95032_1) == 16, "");
+
+#if __STDC_VERSION__ >= 202311L
+struct GH95032_2 {
+ alignas(16) char bytes[16];
+};
+static_assert(alignof(struct GH95032_2) == 16);
+#endif
|
I'm not sure I understand what happened here, since |
|
The part I'm confused about is that this commit doesn't appear to simply be adding "or That is, in clang trunk, this test does still pass when parsed as -std=c23:
So why does this PR need to add new code to move Or, are |
Ah, thank you for the further details! The issue boils down to the fact that
but when the attribute is on the declaration itself, we allow C++11 attributes:
So there is a better way to address this and I think it actually fixes a bug that I didn't notice until now with non-structure use. The changes look a bit odd because I also had to make an adjustment to ensure that |
This needed some extra help to ensure that matrix_type continues to work and that we don't introduce failing assertions in the process. It also fixes an issue with the alignment tests in n3254.c.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM. I like this version.
Did this change also fix any other bugs? Since it looks like we were previously not skipping ProcessDeclAttribute for [[]]
attributes in C23 mode, when IncludeCXX11Attributes == false, and we were supposed to have been?
Thank you for the excellent review, I think we came to a better approach in the end!
Theoretically yes, but practically no. We don't have any attributes in C23 that I think would be impacted by this except for |
Summary: This was a 19.x regression and thus has no release note. Fixes #95032 Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251249
This was a 19.x regression and thus has no release note.
Fixes #95032