[clang] [C23][Parser] Diagnostic for attribute declaration where statement is required (PR #146224)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 8 06:23:10 PDT 2025
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/146224
>From 43e2dc670d7c9ed5e23b5d26dff1e273c84b5a53 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Thu, 3 Jul 2025 02:15:22 +0800
Subject: [PATCH 1/6] [C23][Parser] Diagnostic for attribute declaration where
statement is required
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
clang/docs/ReleaseNotes.rst | 4 ++
.../clang/Basic/DiagnosticParseKinds.td | 4 ++
clang/include/clang/Parse/Parser.h | 5 ++-
clang/lib/Parse/ParseStmt.cpp | 40 ++++++++++++++-----
clang/test/Parser/statements.c | 30 ++++++++++++++
clang/test/Sema/c2x-fallthrough.c | 15 ++++---
6 files changed, 82 insertions(+), 16 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3d893e0aa8e2c..60e7390c31e9b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -747,6 +747,10 @@ Bug Fixes in This Version
- Fixed an infinite recursion when checking constexpr destructors. (#GH141789)
- Fixed a crash when a malformed using declaration appears in a ``constexpr`` function. (#GH144264)
- Fixed a bug when use unicode character name in macro concatenation. (#GH145240)
+- 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 differs from C++, since C++ allows declaration statements.
+ Clang now warning this patterns. (#GH141659)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 6c30da376dafb..9115b60cb0ed0 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -276,6 +276,10 @@ 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_expected_stmt_before_semi_in_secondary_block : Warning<
+ "expected a statement before ';' but got an attribute declaration, "
+ "it is not allowed by the syntax in places where a statement is required">,
+ InGroup<CXXCompat>;
def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">;
def err_expected_semi_after_method_proto : Error<
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index a47e23ffbd357..cca4f14a2942a 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7168,13 +7168,16 @@ class Parser : public CodeCompletionHandler {
AllowStandaloneOpenMPDirectives = 0x2,
/// This context is at the top level of a GNU statement expression.
InStmtExpr = 0x4,
+ /// This context is the C99 secondary-block in selection or iteration
+ /// statement.
+ SecondaryBlockInC = 0x8,
/// The context of a regular substatement.
SubStmt = 0,
/// The context of a compound-statement.
Compound = AllowDeclarationsInC | AllowStandaloneOpenMPDirectives,
- LLVM_MARK_AS_BITMASK_ENUM(InStmtExpr)
+ LLVM_MARK_AS_BITMASK_ENUM(SecondaryBlockInC)
};
/// Act on an expression statement that might be the last statement in a
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 8217151a0259a..6080fb782dfbe 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,12 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
assert((CXX11Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
"attributes on empty statement");
+ if (HasStdAttr && getLangOpts().C23 &&
+ (StmtCtx & ParsedStmtContext::SecondaryBlockInC) != ParsedStmtContext{} &&
+ isa_and_present<NullStmt>(Res.get()))
+ Diag(Res.get()->getBeginLoc(),
+ diag::warn_expected_stmt_before_semi_in_secondary_block);
+
if (CXX11Attrs.empty() || Res.isInvalid())
return Res;
@@ -1491,6 +1498,10 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
SourceLocation InnerStatementTrailingElseLoc;
StmtResult ThenStmt;
+ ParsedStmtContext StmtCtx = getLangOpts().C99
+ ? ParsedStmtContext::SecondaryBlockInC
+ : ParsedStmtContext::SubStmt;
+
{
bool ShouldEnter = ConstexprCondition && !*ConstexprCondition;
Sema::ExpressionEvaluationContext Context =
@@ -1503,7 +1514,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
EnterExpressionEvaluationContext PotentiallyDiscarded(
Actions, Context, nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
- ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
+ ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc, StmtCtx);
}
if (Tok.isNot(tok::kw_else))
@@ -1548,7 +1559,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
EnterExpressionEvaluationContext PotentiallyDiscarded(
Actions, Context, nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
- ElseStmt = ParseStatement();
+ ElseStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
if (ElseStmt.isUsable())
MIChecker.Check();
@@ -1684,8 +1695,11 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
if (C99orCXX)
getCurScope()->decrementMSManglingNumber();
+ ParsedStmtContext StmtCtx = getLangOpts().C99
+ ? ParsedStmtContext::SecondaryBlockInC
+ : ParsedStmtContext::SubStmt;
// Read the body statement.
- StmtResult Body(ParseStatement(TrailingElseLoc));
+ StmtResult Body(ParseStatement(TrailingElseLoc, StmtCtx));
// Pop the scopes.
InnerScope.Exit();
@@ -1754,9 +1768,11 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
MisleadingIndentationChecker MIChecker(*this, MSK_while, WhileLoc);
-
+ ParsedStmtContext StmtCtx = getLangOpts().C99
+ ? ParsedStmtContext::SecondaryBlockInC
+ : ParsedStmtContext::SubStmt;
// Read the body statement.
- StmtResult Body(ParseStatement(TrailingElseLoc));
+ StmtResult Body(ParseStatement(TrailingElseLoc, StmtCtx));
if (Body.isUsable())
MIChecker.Check();
@@ -1799,9 +1815,11 @@ StmtResult Parser::ParseDoStatement() {
//
bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
-
+ ParsedStmtContext StmtCtx = getLangOpts().C99
+ ? ParsedStmtContext::SecondaryBlockInC
+ : ParsedStmtContext::SubStmt;
// Read the body statement.
- StmtResult Body(ParseStatement());
+ StmtResult Body(ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx));
// Pop the body scope if needed.
InnerScope.Exit();
@@ -2221,9 +2239,11 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
getCurScope()->decrementMSManglingNumber();
MisleadingIndentationChecker MIChecker(*this, MSK_for, ForLoc);
-
+ ParsedStmtContext StmtCtx = getLangOpts().C99
+ ? ParsedStmtContext::SecondaryBlockInC
+ : ParsedStmtContext::SubStmt;
// Read the body statement.
- StmtResult Body(ParseStatement(TrailingElseLoc));
+ StmtResult Body(ParseStatement(TrailingElseLoc, StmtCtx));
if (Body.isUsable())
MIChecker.Check();
diff --git a/clang/test/Parser/statements.c b/clang/test/Parser/statements.c
index 2566da83d7c53..ef331ac0448b0 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 {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+
+ if (1) {
+
+ } else
+ [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+
+
+ switch (n)
+ [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+}
+
+void attr_decl_in_iteration_statement(int n) {
+ int i;
+ for (i = 0; i < n; ++i)
+ [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+
+ while (i > 0)
+ [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+
+ do
+ [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ 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..d1d3b1e3727cc 100644
--- a/clang/test/Sema/c2x-fallthrough.c
+++ b/clang/test/Sema/c2x-fallthrough.c
@@ -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 {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
case 3:
while (1)
- [[fallthrough]]; // expected-error {{does not directly precede switch label}}
+ [[fallthrough]]; // expected-error {{does not directly precede switch label}} \
+ // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
case 4:
while (0)
- [[fallthrough]]; // expected-error {{does not directly precede switch label}}
+ [[fallthrough]]; // expected-error {{does not directly precede switch label}} \
+ // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
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 {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
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 {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
case 7:
switch (n) {
case 0:
>From a4923f71671c8dd17395120a8c6efce40c61df7d Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Thu, 3 Jul 2025 02:23:20 +0800
Subject: [PATCH 2/6] change c2x to c23
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
clang/test/Sema/c2x-fallthrough.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/Sema/c2x-fallthrough.c b/clang/test/Sema/c2x-fallthrough.c
index d1d3b1e3727cc..e37cbb7e2c35b 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);
>From a07b1a7d83572e54ffe754839e87493ce5b7447a Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Mon, 7 Jul 2025 22:21:14 +0800
Subject: [PATCH 3/6] Update clang/docs/ReleaseNotes.rst
Co-authored-by: Mariya Podchishchaeva <mariya.podchishchaeva at intel.com>
---
clang/docs/ReleaseNotes.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 60e7390c31e9b..5f907b800bef4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -750,7 +750,7 @@ Bug Fixes in This Version
- 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 differs from C++, since C++ allows declaration statements.
- Clang now warning this patterns. (#GH141659)
+ Clang now emits a warning for these patterns. (#GH141659)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>From 83ea0b7971197e993a467f24bc6b3bd42bdbce00 Mon Sep 17 00:00:00 2001
From: "Wang, Yihan" <yronglin777 at gmail.com>
Date: Tue, 8 Jul 2025 00:03:19 +0800
Subject: [PATCH 4/6] Add a diagnostic group
Signed-off-by: Wang, Yihan <yronglin777 at gmail.com>
---
clang/docs/ReleaseNotes.rst | 9 +++++----
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Basic/DiagnosticParseKinds.td | 7 +++----
clang/lib/Parse/ParseStmt.cpp | 5 +++--
clang/test/Parser/statements.c | 12 ++++++------
clang/test/Sema/c2x-fallthrough.c | 10 +++++-----
6 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5f907b800bef4..d0288d0c88421 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -747,10 +747,11 @@ Bug Fixes in This Version
- Fixed an infinite recursion when checking constexpr destructors. (#GH141789)
- Fixed a crash when a malformed using declaration appears in a ``constexpr`` function. (#GH144264)
- Fixed a bug when use unicode character name in macro concatenation. (#GH145240)
-- 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 differs from C++, since C++ allows declaration statements.
- Clang now emits a warning for these patterns. (#GH141659)
+- 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 differs 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/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 36fa3227fd6a6..341037282fa21 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -159,6 +159,7 @@ def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
def C99Compat : DiagGroup<"c99-compat">;
def C23Compat : DiagGroup<"c23-compat">;
def : DiagGroup<"c2x-compat", [C23Compat]>;
+def CAttributeExtensions : DiagGroup<"c-attribute-extension">;
def CppKeywordInC : DiagGroup<"c++-keyword">;
def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9115b60cb0ed0..9bbbbd4ed8186 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -276,10 +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_expected_stmt_before_semi_in_secondary_block : Warning<
- "expected a statement before ';' but got an attribute declaration, "
- "it is not allowed by the syntax in places where a statement is required">,
- InGroup<CXXCompat>;
+def warn_attr_in_secondary_block : ExtWarn<
+ "ISO C does not allow an attribute list to appear here">,
+ InGroup<CAttributeExtensions>;
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 6080fb782dfbe..fdf91edd3deb9 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Parse/LoopHint.h"
@@ -84,8 +85,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
if (HasStdAttr && getLangOpts().C23 &&
(StmtCtx & ParsedStmtContext::SecondaryBlockInC) != ParsedStmtContext{} &&
isa_and_present<NullStmt>(Res.get()))
- Diag(Res.get()->getBeginLoc(),
- diag::warn_expected_stmt_before_semi_in_secondary_block);
+ 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 ef331ac0448b0..22a6633bdf262 100644
--- a/clang/test/Parser/statements.c
+++ b/clang/test/Parser/statements.c
@@ -82,28 +82,28 @@ int test9(void) {
#if __STDC_VERSION__ >= 202311L
void attr_decl_in_selection_statement(int n) {
if (1)
- [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
if (1) {
} else
- [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
switch (n)
- [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ [[]]; // 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 {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
while (i > 0)
- [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ [[]]; // expected-warning {{ISO C does not allow an attribute list to appear here}}
do
- [[]]; // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ [[]]; // 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 e37cbb7e2c35b..7d2f25ed5187b 100644
--- a/clang/test/Sema/c2x-fallthrough.c
+++ b/clang/test/Sema/c2x-fallthrough.c
@@ -17,21 +17,21 @@ void f(int n) {
case 2:
for (int n = 0; n != 10; ++n)
[[fallthrough]]; // expected-error {{does not directly precede switch label}} \
- // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ // 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}} \
- // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ // 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}} \
- // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ // 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}} \
- // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ // 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}} \
- // expected-warning {{expected a statement before ';' but got an attribute declaration, it is not allowed by the syntax in places where a statement is required}}
+ // expected-warning {{ISO C does not allow an attribute list to appear here}}
case 7:
switch (n) {
case 0:
>From 6256229cac9832d0b34460e9e29a2f4bd3f308dc Mon Sep 17 00:00:00 2001
From: "Wang, Yihan" <yronglin777 at gmail.com>
Date: Tue, 8 Jul 2025 00:35:03 +0800
Subject: [PATCH 5/6] Avoid unused include
Signed-off-by: Wang, Yihan <yronglin777 at gmail.com>
---
clang/lib/Parse/ParseStmt.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index fdf91edd3deb9..fa7a1390c71f9 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -14,7 +14,6 @@
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/PrettyStackTrace.h"
-#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Parse/LoopHint.h"
>From 8415f60520e43cb2b6d137131564dbcf228fd1f9 Mon Sep 17 00:00:00 2001
From: "Wang, Yihan" <yronglin777 at gmail.com>
Date: Tue, 8 Jul 2025 21:21:41 +0800
Subject: [PATCH 6/6] Address review comments
Signed-off-by: Wang, Yihan <yronglin777 at gmail.com>
---
clang/include/clang/Basic/DiagnosticGroups.td | 1 -
.../clang/Basic/DiagnosticParseKinds.td | 2 +-
clang/include/clang/Parse/Parser.h | 5 +--
clang/lib/Parse/ParseStmt.cpp | 35 ++++++-------------
4 files changed, 13 insertions(+), 30 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 341037282fa21..36fa3227fd6a6 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -159,7 +159,6 @@ def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
def C99Compat : DiagGroup<"c99-compat">;
def C23Compat : DiagGroup<"c23-compat">;
def : DiagGroup<"c2x-compat", [C23Compat]>;
-def CAttributeExtensions : DiagGroup<"c-attribute-extension">;
def CppKeywordInC : DiagGroup<"c++-keyword">;
def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9bbbbd4ed8186..db79e214879b5 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -278,7 +278,7 @@ 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<CAttributeExtensions>;
+ 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/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index cca4f14a2942a..a47e23ffbd357 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7168,16 +7168,13 @@ class Parser : public CodeCompletionHandler {
AllowStandaloneOpenMPDirectives = 0x2,
/// This context is at the top level of a GNU statement expression.
InStmtExpr = 0x4,
- /// This context is the C99 secondary-block in selection or iteration
- /// statement.
- SecondaryBlockInC = 0x8,
/// The context of a regular substatement.
SubStmt = 0,
/// The context of a compound-statement.
Compound = AllowDeclarationsInC | AllowStandaloneOpenMPDirectives,
- LLVM_MARK_AS_BITMASK_ENUM(SecondaryBlockInC)
+ LLVM_MARK_AS_BITMASK_ENUM(InStmtExpr)
};
/// Act on an expression statement that might be the last statement in a
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index fa7a1390c71f9..af58599e1f705 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -81,8 +81,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
assert((CXX11Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
"attributes on empty statement");
- if (HasStdAttr && getLangOpts().C23 &&
- (StmtCtx & ParsedStmtContext::SecondaryBlockInC) != ParsedStmtContext{} &&
+ if (HasStdAttr && getLangOpts().C99 &&
+ (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == ParsedStmtContext{} &&
isa_and_present<NullStmt>(Res.get()))
Diag(CXX11Attrs.Range.getBegin(), diag::warn_attr_in_secondary_block)
<< CXX11Attrs.Range;
@@ -1498,10 +1498,6 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
SourceLocation InnerStatementTrailingElseLoc;
StmtResult ThenStmt;
- ParsedStmtContext StmtCtx = getLangOpts().C99
- ? ParsedStmtContext::SecondaryBlockInC
- : ParsedStmtContext::SubStmt;
-
{
bool ShouldEnter = ConstexprCondition && !*ConstexprCondition;
Sema::ExpressionEvaluationContext Context =
@@ -1514,7 +1510,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
EnterExpressionEvaluationContext PotentiallyDiscarded(
Actions, Context, nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
- ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc, StmtCtx);
+ ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
}
if (Tok.isNot(tok::kw_else))
@@ -1559,7 +1555,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
EnterExpressionEvaluationContext PotentiallyDiscarded(
Actions, Context, nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
- ElseStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
+ ElseStmt = ParseStatement();
if (ElseStmt.isUsable())
MIChecker.Check();
@@ -1695,11 +1691,8 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
if (C99orCXX)
getCurScope()->decrementMSManglingNumber();
- ParsedStmtContext StmtCtx = getLangOpts().C99
- ? ParsedStmtContext::SecondaryBlockInC
- : ParsedStmtContext::SubStmt;
// Read the body statement.
- StmtResult Body(ParseStatement(TrailingElseLoc, StmtCtx));
+ StmtResult Body(ParseStatement(TrailingElseLoc));
// Pop the scopes.
InnerScope.Exit();
@@ -1768,11 +1761,9 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
MisleadingIndentationChecker MIChecker(*this, MSK_while, WhileLoc);
- ParsedStmtContext StmtCtx = getLangOpts().C99
- ? ParsedStmtContext::SecondaryBlockInC
- : ParsedStmtContext::SubStmt;
+
// Read the body statement.
- StmtResult Body(ParseStatement(TrailingElseLoc, StmtCtx));
+ StmtResult Body(ParseStatement(TrailingElseLoc));
if (Body.isUsable())
MIChecker.Check();
@@ -1815,11 +1806,9 @@ StmtResult Parser::ParseDoStatement() {
//
bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
- ParsedStmtContext StmtCtx = getLangOpts().C99
- ? ParsedStmtContext::SecondaryBlockInC
- : ParsedStmtContext::SubStmt;
+
// Read the body statement.
- StmtResult Body(ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx));
+ StmtResult Body(ParseStatement());
// Pop the body scope if needed.
InnerScope.Exit();
@@ -2239,11 +2228,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
getCurScope()->decrementMSManglingNumber();
MisleadingIndentationChecker MIChecker(*this, MSK_for, ForLoc);
- ParsedStmtContext StmtCtx = getLangOpts().C99
- ? ParsedStmtContext::SecondaryBlockInC
- : ParsedStmtContext::SubStmt;
+
// Read the body statement.
- StmtResult Body(ParseStatement(TrailingElseLoc, StmtCtx));
+ StmtResult Body(ParseStatement(TrailingElseLoc));
if (Body.isUsable())
MIChecker.Check();
More information about the cfe-commits
mailing list