[clang] 191386f - [C23][Parser] Diagnostic for attribute declaration where statement is required (#146224)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 8 17:54:35 PDT 2025
Author: yronglin
Date: 2025-07-09T08:54:30+08:00
New Revision: 191386fcd3335c5b7194da209d71d16549a2bb2f
URL: https://github.com/llvm/llvm-project/commit/191386fcd3335c5b7194da209d71d16549a2bb2f
DIFF: https://github.com/llvm/llvm-project/commit/191386fcd3335c5b7194da209d71d16549a2bb2f.diff
LOG: [C23][Parser] Diagnostic for attribute declaration where statement is required (#146224)
Fixes: https://github.com/llvm/llvm-project/issues/141659
In C23, something like [[/*possible attributes*/]]; is an attribute
declaration, not a statement. So it is not allowed by the syntax in
places where a statement is required, specifically as the secondary
block of a selection or iteration statement.
Therefore, code like the following should give a diagnostic (at least
with -std=c23 -pedantic), but Clang currently does not produce one:
```cpp
int main(void) {
if (1)
[[]];
}
```
---------
Signed-off-by: yronglin <yronglin777 at gmail.com>
Signed-off-by: Wang, Yihan <yronglin777 at gmail.com>
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva at intel.com>
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/lib/Parse/ParseStmt.cpp
clang/test/Parser/statements.c
clang/test/Sema/c2x-fallthrough.c
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8b4f9229c4463..57a94242c9e61 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -767,6 +767,11 @@ Bug Fixes in This Version
flag and diagnostic because the macro injection was used to emit this warning.
Unfortunately there is no other good way to diagnose usage of ``static_assert``
macro without inclusion of ``<assert.h>``.
+- In C23, something like ``[[/*possible attributes*/]];`` is an attribute
+ declaration, not a statement. So it is not allowed by the syntax in places
+ where a statement is required, specifically as the secondary block of a
+ selection or iteration statement. This
diff ers from C++, since C++ allows
+ declaration statements. Clang now emits a warning for these patterns. (#GH141659)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 4636eaf2291ab..fd8e5c3c6ad87 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -276,6 +276,9 @@ def err_expected_while : Error<"expected 'while' in do/while loop">;
def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">;
def err_expected_semi_after_expr : Error<"expected ';' after expression">;
+def warn_attr_in_secondary_block : ExtWarn<
+ "ISO C does not allow an attribute list to appear here">,
+ InGroup<DiagGroup<"c-attribute-extension">>;
def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">;
def err_expected_semi_after_method_proto : Error<
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 8217151a0259a..31b84b6f2ede0 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -63,7 +63,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
// at the start of the statement. Thus, we're not using MaybeParseAttributes
// here because we don't want to allow arbitrary orderings.
ParsedAttributes CXX11Attrs(AttrFactory);
- MaybeParseCXX11Attributes(CXX11Attrs, /*MightBeObjCMessageSend*/ true);
+ bool HasStdAttr =
+ MaybeParseCXX11Attributes(CXX11Attrs, /*MightBeObjCMessageSend*/ true);
ParsedAttributes GNUOrMSAttrs(AttrFactory);
if (getLangOpts().OpenCL)
MaybeParseGNUAttributes(GNUOrMSAttrs);
@@ -80,6 +81,13 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
assert((CXX11Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
"attributes on empty statement");
+ if (HasStdAttr && getLangOpts().C23 &&
+ (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
+ ParsedStmtContext{} &&
+ isa_and_present<NullStmt>(Res.get()))
+ Diag(CXX11Attrs.Range.getBegin(), diag::warn_attr_in_secondary_block)
+ << CXX11Attrs.Range;
+
if (CXX11Attrs.empty() || Res.isInvalid())
return Res;
diff --git a/clang/test/Parser/statements.c b/clang/test/Parser/statements.c
index 2566da83d7c53..22a6633bdf262 100644
--- a/clang/test/Parser/statements.c
+++ b/clang/test/Parser/statements.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -Wno-unreachable-code
+// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s -Wno-unreachable-code
void test1(void) {
{ ; { ;;}} ;;
@@ -77,3 +78,32 @@ int test9(void) {
return 4, // expected-error {{expected ';' after return statement}}
}
+
+#if __STDC_VERSION__ >= 202311L
+void attr_decl_in_selection_statement(int n) {
+ if (1)
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
+
+ if (1) {
+
+ } else
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
+
+
+ switch (n)
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
+}
+
+void attr_decl_in_iteration_statement(int n) {
+ int i;
+ for (i = 0; i < n; ++i)
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
+
+ while (i > 0)
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
+
+ do
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
+ while (i > 0);
+}
+#endif // __STDC_VERSION__ >= 202311L
diff --git a/clang/test/Sema/c2x-fallthrough.c b/clang/test/Sema/c2x-fallthrough.c
index 092d5285f80ba..7d2f25ed5187b 100644
--- a/clang/test/Sema/c2x-fallthrough.c
+++ b/clang/test/Sema/c2x-fallthrough.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c2x -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c23 -verify %s
// This is the latest version of fallthrough that we support.
_Static_assert(__has_c_attribute(fallthrough) == 201910L);
@@ -16,17 +16,22 @@ void f(int n) {
}
case 2:
for (int n = 0; n != 10; ++n)
- [[fallthrough]]; // expected-error {{does not directly precede switch label}}
+ [[fallthrough]]; // expected-error {{does not directly precede switch label}} \
+ // expected-warning {{ISO C does not allow an attribute list to appear here}}
case 3:
while (1)
- [[fallthrough]]; // expected-error {{does not directly precede switch label}}
+ [[fallthrough]]; // expected-error {{does not directly precede switch label}} \
+ // expected-warning {{ISO C does not allow an attribute list to appear here}}
case 4:
while (0)
- [[fallthrough]]; // expected-error {{does not directly precede switch label}}
+ [[fallthrough]]; // expected-error {{does not directly precede switch label}} \
+ // expected-warning {{ISO C does not allow an attribute list to appear here}}
case 5:
- do [[fallthrough]]; while (1); // expected-error {{does not directly precede switch label}}
+ do [[fallthrough]]; while (1); // expected-error {{does not directly precede switch label}} \
+ // expected-warning {{ISO C does not allow an attribute list to appear here}}
case 6:
- do [[fallthrough]]; while (0); // expected-error {{does not directly precede switch label}}
+ do [[fallthrough]]; while (0); // expected-error {{does not directly precede switch label}} \
+ // expected-warning {{ISO C does not allow an attribute list to appear here}}
case 7:
switch (n) {
case 0:
More information about the cfe-commits
mailing list