Skip to content

Commit 2e79133

Browse files
authored
[clang] Improve _Alignas on a struct declaration diagnostic (#65638)
Fixes #58637. Adds `isAlignas()` method on `AttributeCommonInfo` which accounts for C++ `alignas` as well as C11 `_Alignas`. The method is used to improve diagnostic in C when `_Alignas` is used in C at the wrong location. This corrects the previously suggested move of `_Alignas` past the declaration specifier, now warns attribute `_Alignas` is ignored. Based on https://reviews.llvm.org/D141177.
1 parent a0303d8 commit 2e79133

File tree

7 files changed

+43
-14
lines changed

7 files changed

+43
-14
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ Attribute Changes in Clang
292292
When viewing ``S::FruitKind`` in a debugger, it will behave as if the member
293293
was declared as type ``E`` rather than ``unsigned``.
294294

295+
- Clang now warns you that the ``_Alignas`` attribute on declaration specifiers
296+
is ignored, changed from the former incorrect suggestion to move it past
297+
declaration specifiers. (`#58637 <https://github.com/llvm/llvm-project/issues/58637>`_)
298+
299+
295300
Improvements to Clang's diagnostics
296301
-----------------------------------
297302
- Clang constexpr evaluator now prints template arguments when displaying

clang/include/clang/Basic/AttributeCommonInfo.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,15 @@ class AttributeCommonInfo {
200200

201201
bool isC23Attribute() const { return SyntaxUsed == AS_C23; }
202202

203+
bool isAlignas() const {
204+
// FIXME: In the current state, the IsAlignas member variable is only true
205+
// with the C++ `alignas` keyword but not `_Alignas`. The following
206+
// expression works around the otherwise lost information so it will return
207+
// true for `alignas` or `_Alignas` while still returning false for things
208+
// like `__attribute__((aligned))`.
209+
return (getParsedKind() == AT_Aligned && isKeywordAttribute());
210+
}
211+
203212
/// The attribute is spelled [[]] in either C or C++ mode, including standard
204213
/// attributes spelled with a keyword, like alignas.
205214
bool isStandardAttributeSyntax() const {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5346,16 +5346,21 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
53465346
TypeSpecType == DeclSpec::TST_interface ||
53475347
TypeSpecType == DeclSpec::TST_union ||
53485348
TypeSpecType == DeclSpec::TST_enum) {
5349-
for (const ParsedAttr &AL : DS.getAttributes())
5350-
Diag(AL.getLoc(), AL.isRegularKeywordAttribute()
5351-
? diag::err_declspec_keyword_has_no_effect
5352-
: diag::warn_declspec_attribute_ignored)
5353-
<< AL << GetDiagnosticTypeSpecifierID(DS);
5354-
for (const ParsedAttr &AL : DeclAttrs)
5355-
Diag(AL.getLoc(), AL.isRegularKeywordAttribute()
5356-
? diag::err_declspec_keyword_has_no_effect
5357-
: diag::warn_declspec_attribute_ignored)
5349+
5350+
auto EmitAttributeDiagnostic = [this, &DS](const ParsedAttr &AL) {
5351+
unsigned DiagnosticId = diag::warn_declspec_attribute_ignored;
5352+
if (AL.isAlignas() && !getLangOpts().CPlusPlus)
5353+
DiagnosticId = diag::warn_attribute_ignored;
5354+
else if (AL.isRegularKeywordAttribute())
5355+
DiagnosticId = diag::err_declspec_keyword_has_no_effect;
5356+
else
5357+
DiagnosticId = diag::warn_declspec_attribute_ignored;
5358+
Diag(AL.getLoc(), DiagnosticId)
53585359
<< AL << GetDiagnosticTypeSpecifierID(DS);
5360+
};
5361+
5362+
llvm::for_each(DS.getAttributes(), EmitAttributeDiagnostic);
5363+
llvm::for_each(DeclAttrs, EmitAttributeDiagnostic);
53595364
}
53605365
}
53615366

clang/test/C/drs/dr4xx.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,7 @@ void dr444(void) {
164164
/* FIXME: This should be accepted as per this DR. */
165165
int j = (_Alignas(int) int){12}; /* expected-error {{expected expression}} */
166166

167-
/* FIXME: The diagnostic in this case is really bad; moving the specifier to
168-
* where the diagnostic recommends causes a different, more inscrutable error
169-
* about anonymous structures.
170-
*/
171-
_Alignas(int) struct T { /* expected-warning {{attribute '_Alignas' is ignored, place it after "struct" to apply attribute to type declaration}} */
167+
_Alignas(int) struct T { /* expected-warning {{'_Alignas' attribute ignored}} */
172168
int i;
173169
};
174170

clang/test/Parser/c1x-alignas.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ char c4 _Alignas(32); // expected-error {{expected ';' after top level declarato
99

1010
char _Alignas(_Alignof(int)) c5;
1111

12+
_Alignas(int) struct c6; // expected-warning {{'_Alignas' attribute ignored}}
1213
// CHECK-EXT: '_Alignas' is a C11 extension
1314
// CHECK-EXT: '_Alignof' is a C11 extension

clang/test/Parser/c2x-alignas.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s
2+
3+
_Alignas(int) struct c1; // expected-warning {{'_Alignas' attribute ignored}}
4+
5+
// FIXME: `alignas` enters into C++ parsing code and never reaches the
6+
// declaration specifier attribute diagnostic infrastructure.
7+
//
8+
// Fixing this will require the C23 notions of `alignas` being a keyword and
9+
// `_Alignas` being an alternate spelling integrated into the parsing
10+
// infrastructure.
11+
alignas(int) struct c1; // expected-error {{misplaced attributes; expected attributes here}}

clang/test/Parser/cxx0x-attributes.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,3 +451,5 @@ namespace P2361 {
451451
// expected-warning {{use of the 'deprecated' attribute is a C++14 extension}}
452452
[[nodiscard("\123")]] int b(); // expected-error{{invalid escape sequence '\123' in an unevaluated string literal}}
453453
}
454+
455+
alignas(int) struct AlignAsAttribute {}; // expected-error {{misplaced attributes; expected attributes here}}

0 commit comments

Comments
 (0)