Skip to content

[C23][Parser] Diagnostic for attribute declaration where statement is required #146224

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

Merged
merged 9 commits into from
Jul 9, 2025

Conversation

yronglin
Copy link
Contributor

Fixes: #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:

int main(void) {
    if (1)
        [[]];
}

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jun 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 28, 2025

@llvm/pr-subscribers-clang

Author: None (yronglin)

Changes

Fixes: #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:

int main(void) {
    if (1)
        [[]];
}

Patch is 37.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146224.diff

8 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+3)
  • (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+1)
  • (modified) clang/include/clang/Parse/Parser.h (+336-332)
  • (modified) clang/lib/Parse/ParseStmt.cpp (+29-10)
  • (modified) clang/test/Parser/statements.c (+27)
  • (modified) clang/test/Sema/c2x-fallthrough.c (+7-6)
  • (added) clang/test/Sema/c2x-fallthrough2.c (+18)
  • (added) clang/test/Sema/fallthrough.cpp (+75)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 01f3b7a557a5c..78e20bd8900f8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -727,6 +727,9 @@ 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. Clang now reject this pattern and give a diagnostic. (#GH141659)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 6c30da376dafb..a8b77e0f4ebdf 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -276,6 +276,7 @@ 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 err_expected_stmt_before_semi : Error<"expected a statement before ';'">;
 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..7c85bbefe57a8 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7168,13 +7168,15 @@ 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-/iteration-statement.
+    SecondaryBlock = 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(SecondaryBlock)
   };
 
   /// Act on an expression statement that might be the last statement in a
@@ -7246,337 +7248,339 @@ class Parser : public CodeCompletionHandler {
   ParseStatementOrDeclaration(StmtVector &Stmts, ParsedStmtContext StmtCtx,
                               SourceLocation *TrailingElseLoc = nullptr);
 
-  StmtResult ParseStatementOrDeclarationAfterAttributes(
-      StmtVector &Stmts, ParsedStmtContext StmtCtx,
-      SourceLocation *TrailingElseLoc, ParsedAttributes &DeclAttrs,
-      ParsedAttributes &DeclSpecAttrs);
-
-  /// Parse an expression statement.
-  StmtResult ParseExprStatement(ParsedStmtContext StmtCtx);
-
-  /// ParseLabeledStatement - We have an identifier and a ':' after it.
-  ///
-  /// \verbatim
-  ///       label:
-  ///         identifier ':'
-  /// [GNU]   identifier ':' attributes[opt]
-  ///
-  ///       labeled-statement:
-  ///         label statement
-  /// \endverbatim
-  ///
-  StmtResult ParseLabeledStatement(ParsedAttributes &Attrs,
-                                   ParsedStmtContext StmtCtx);
-
-  /// ParseCaseStatement
-  /// \verbatim
-  ///       labeled-statement:
-  ///         'case' constant-expression ':' statement
-  /// [GNU]   'case' constant-expression '...' constant-expression ':' statement
-  /// \endverbatim
-  ///
-  StmtResult ParseCaseStatement(ParsedStmtContext StmtCtx,
-                                bool MissingCase = false,
-                                ExprResult Expr = ExprResult());
-
-  /// ParseDefaultStatement
-  /// \verbatim
-  ///       labeled-statement:
-  ///         'default' ':' statement
-  /// \endverbatim
-  /// Note that this does not parse the 'statement' at the end.
-  ///
-  StmtResult ParseDefaultStatement(ParsedStmtContext StmtCtx);
-
-  StmtResult ParseCompoundStatement(bool isStmtExpr = false);
-
-  /// ParseCompoundStatement - Parse a "{}" block.
-  ///
-  /// \verbatim
-  ///       compound-statement: [C99 6.8.2]
-  ///         { block-item-list[opt] }
-  /// [GNU]   { label-declarations block-item-list } [TODO]
-  ///
-  ///       block-item-list:
-  ///         block-item
-  ///         block-item-list block-item
-  ///
-  ///       block-item:
-  ///         declaration
-  /// [GNU]   '__extension__' declaration
-  ///         statement
-  ///
-  /// [GNU] label-declarations:
-  /// [GNU]   label-declaration
-  /// [GNU]   label-declarations label-declaration
-  ///
-  /// [GNU] label-declaration:
-  /// [GNU]   '__label__' identifier-list ';'
-  /// \endverbatim
-  ///
-  StmtResult ParseCompoundStatement(bool isStmtExpr, unsigned ScopeFlags);
-
-  /// Parse any pragmas at the start of the compound expression. We handle these
-  /// separately since some pragmas (FP_CONTRACT) must appear before any C
-  /// statement in the compound, but may be intermingled with other pragmas.
-  void ParseCompoundStatementLeadingPragmas();
-
-  void DiagnoseLabelAtEndOfCompoundStatement();
-
-  /// Consume any extra semi-colons resulting in null statements,
-  /// returning true if any tok::semi were consumed.
-  bool ConsumeNullStmt(StmtVector &Stmts);
-
-  /// ParseCompoundStatementBody - Parse a sequence of statements optionally
-  /// followed by a label and invoke the ActOnCompoundStmt action.  This expects
-  /// the '{' to be the current token, and consume the '}' at the end of the
-  /// block.  It does not manipulate the scope stack.
-  StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
-
-  /// ParseParenExprOrCondition:
-  /// \verbatim
-  /// [C  ]     '(' expression ')'
-  /// [C++]     '(' condition ')'
-  /// [C++1z]   '(' init-statement[opt] condition ')'
-  /// \endverbatim
-  ///
-  /// This function parses and performs error recovery on the specified
-  /// condition or expression (depending on whether we're in C++ or C mode).
-  /// This function goes out of its way to recover well.  It returns true if
-  /// there was a parser error (the right paren couldn't be found), which
-  /// indicates that the caller should try to recover harder.  It returns false
-  /// if the condition is successfully parsed.  Note that a successful parse can
-  /// still have semantic errors in the condition. Additionally, it will assign
-  /// the location of the outer-most '(' and ')', to LParenLoc and RParenLoc,
-  /// respectively.
-  bool ParseParenExprOrCondition(StmtResult *InitStmt,
-                                 Sema::ConditionResult &CondResult,
-                                 SourceLocation Loc, Sema::ConditionKind CK,
-                                 SourceLocation &LParenLoc,
-                                 SourceLocation &RParenLoc);
-
-  /// ParseIfStatement
-  /// \verbatim
-  ///       if-statement: [C99 6.8.4.1]
-  ///         'if' '(' expression ')' statement
-  ///         'if' '(' expression ')' statement 'else' statement
-  /// [C++]   'if' '(' condition ')' statement
-  /// [C++]   'if' '(' condition ')' statement 'else' statement
-  /// [C++23] 'if' '!' [opt] consteval compound-statement
-  /// [C++23] 'if' '!' [opt] consteval compound-statement 'else' statement
-  /// \endverbatim
-  ///
-  StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);
-
-  /// ParseSwitchStatement
-  /// \verbatim
-  ///       switch-statement:
-  ///         'switch' '(' expression ')' statement
-  /// [C++]   'switch' '(' condition ')' statement
-  /// \endverbatim
-  StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);
-
-  /// ParseWhileStatement
-  /// \verbatim
-  ///       while-statement: [C99 6.8.5.1]
-  ///         'while' '(' expression ')' statement
-  /// [C++]   'while' '(' condition ')' statement
-  /// \endverbatim
-  StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);
-
-  /// ParseDoStatement
-  /// \verbatim
-  ///       do-statement: [C99 6.8.5.2]
-  ///         'do' statement 'while' '(' expression ')' ';'
-  /// \endverbatim
-  /// Note: this lets the caller parse the end ';'.
-  StmtResult ParseDoStatement();
-
-  /// ParseForStatement
-  /// \verbatim
-  ///       for-statement: [C99 6.8.5.3]
-  ///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
-  ///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
-  /// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
-  /// [C++]       statement
-  /// [C++0x] 'for'
-  ///             'co_await'[opt]    [Coroutines]
-  ///             '(' for-range-declaration ':' for-range-initializer ')'
-  ///             statement
-  /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
-  /// [OBJC2] 'for' '(' expr 'in' expr ')' statement
-  ///
-  /// [C++] for-init-statement:
-  /// [C++]   expression-statement
-  /// [C++]   simple-declaration
-  /// [C++23] alias-declaration
-  ///
-  /// [C++0x] for-range-declaration:
-  /// [C++0x]   attribute-specifier-seq[opt] type-specifier-seq declarator
-  /// [C++0x] for-range-initializer:
-  /// [C++0x]   expression
-  /// [C++0x]   braced-init-list            [TODO]
-  /// \endverbatim
-  StmtResult ParseForStatement(SourceLocation *TrailingElseLoc);
-
-  /// ParseGotoStatement
-  /// \verbatim
-  ///       jump-statement:
-  ///         'goto' identifier ';'
-  /// [GNU]   'goto' '*' expression ';'
-  /// \endverbatim
-  ///
-  /// Note: this lets the caller parse the end ';'.
-  ///
-  StmtResult ParseGotoStatement();
-
-  /// ParseContinueStatement
-  /// \verbatim
-  ///       jump-statement:
-  ///         'continue' ';'
-  /// \endverbatim
-  ///
-  /// Note: this lets the caller parse the end ';'.
-  ///
-  StmtResult ParseContinueStatement();
-
-  /// ParseBreakStatement
-  /// \verbatim
-  ///       jump-statement:
-  ///         'break' ';'
-  /// \endverbatim
-  ///
-  /// Note: this lets the caller parse the end ';'.
-  ///
-  StmtResult ParseBreakStatement();
-
-  /// ParseReturnStatement
-  /// \verbatim
-  ///       jump-statement:
-  ///         'return' expression[opt] ';'
-  ///         'return' braced-init-list ';'
-  ///         'co_return' expression[opt] ';'
-  ///         'co_return' braced-init-list ';'
-  /// \endverbatim
-  StmtResult ParseReturnStatement();
-
-  StmtResult ParsePragmaLoopHint(StmtVector &Stmts, ParsedStmtContext StmtCtx,
-                                 SourceLocation *TrailingElseLoc,
-                                 ParsedAttributes &Attrs);
-
-  void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
-
-  //===--------------------------------------------------------------------===//
-  // C++ 6: Statements and Blocks
-
-  /// ParseCXXTryBlock - Parse a C++ try-block.
-  ///
-  /// \verbatim
-  ///       try-block:
-  ///         'try' compound-statement handler-seq
-  /// \endverbatim
-  ///
-  StmtResult ParseCXXTryBlock();
-
-  /// ParseCXXTryBlockCommon - Parse the common part of try-block and
-  /// function-try-block.
-  ///
-  /// \verbatim
-  ///       try-block:
-  ///         'try' compound-statement handler-seq
-  ///
-  ///       function-try-block:
-  ///         'try' ctor-initializer[opt] compound-statement handler-seq
-  ///
-  ///       handler-seq:
-  ///         handler handler-seq[opt]
-  ///
-  ///       [Borland] try-block:
-  ///         'try' compound-statement seh-except-block
-  ///         'try' compound-statement seh-finally-block
-  /// \endverbatim
-  ///
-  StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry = false);
-
-  /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the
-  /// standard
-  ///
-  /// \verbatim
-  ///   handler:
-  ///     'catch' '(' exception-declaration ')' compound-statement
-  ///
-  ///   exception-declaration:
-  ///     attribute-specifier-seq[opt] type-specifier-seq declarator
-  ///     attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt]
-  ///     '...'
-  /// \endverbatim
-  ///
-  StmtResult ParseCXXCatchBlock(bool FnCatch = false);
-
-  //===--------------------------------------------------------------------===//
-  // MS: SEH Statements and Blocks
-
-  /// ParseSEHTryBlockCommon
-  ///
-  /// \verbatim
-  /// seh-try-block:
-  ///   '__try' compound-statement seh-handler
-  ///
-  /// seh-handler:
-  ///   seh-except-block
-  ///   seh-finally-block
-  /// \endverbatim
-  ///
-  StmtResult ParseSEHTryBlock();
-
-  /// ParseSEHExceptBlock - Handle __except
-  ///
-  /// \verbatim
-  /// seh-except-block:
-  ///   '__except' '(' seh-filter-expression ')' compound-statement
-  /// \endverbatim
-  ///
-  StmtResult ParseSEHExceptBlock(SourceLocation Loc);
-
-  /// ParseSEHFinallyBlock - Handle __finally
-  ///
-  /// \verbatim
-  /// seh-finally-block:
-  ///   '__finally' compound-statement
-  /// \endverbatim
-  ///
-  StmtResult ParseSEHFinallyBlock(SourceLocation Loc);
-
-  StmtResult ParseSEHLeaveStatement();
-
-  Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope);
-
-  /// ParseFunctionTryBlock - Parse a C++ function-try-block.
-  ///
-  /// \verbatim
-  ///       function-try-block:
-  ///         'try' ctor-initializer[opt] compound-statement handler-seq
-  /// \endverbatim
-  ///
-  Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope);
-
-  /// When in code-completion, skip parsing of the function/method body
-  /// unless the body contains the code-completion point.
-  ///
-  /// \returns true if the function body was skipped.
-  bool trySkippingFunctionBody();
-
-  /// isDeclarationStatement - Disambiguates between a declaration or an
-  /// expression statement, when parsing function bodies.
-  ///
-  /// \param DisambiguatingWithExpression - True to indicate that the purpose of
-  /// this check is to disambiguate between an expression and a declaration.
-  /// Returns true for declaration, false for expression.
-  bool isDeclarationStatement(bool DisambiguatingWithExpression = false) {
-    if (getLangOpts().CPlusPlus)
-      return isCXXDeclarationStatement(DisambiguatingWithExpression);
-    return isDeclarationSpecifier(ImplicitTypenameContext::No, true);
-  }
+    StmtResult ParseStatementOrDeclarationAfterAttributes(
+        StmtVector &Stmts, ParsedStmtContext StmtCtx,
+        SourceLocation *TrailingElseLoc, ParsedAttributes &DeclAttrs,
+        ParsedAttributes &DeclSpecAttrs);
+
+    /// Parse an expression statement.
+    StmtResult ParseExprStatement(ParsedStmtContext StmtCtx);
+
+    /// ParseLabeledStatement - We have an identifier and a ':' after it.
+    ///
+    /// \verbatim
+    ///       label:
+    ///         identifier ':'
+    /// [GNU]   identifier ':' attributes[opt]
+    ///
+    ///       labeled-statement:
+    ///         label statement
+    /// \endverbatim
+    ///
+    StmtResult ParseLabeledStatement(ParsedAttributes &Attrs,
+                                     ParsedStmtContext StmtCtx);
+
+    /// ParseCaseStatement
+    /// \verbatim
+    ///       labeled-statement:
+    ///         'case' constant-expression ':' statement
+    /// [GNU]   'case' constant-expression '...' constant-expression ':'
+    /// statement
+    /// \endverbatim
+    ///
+    StmtResult ParseCaseStatement(ParsedStmtContext StmtCtx,
+                                  bool MissingCase = false,
+                                  ExprResult Expr = ExprResult());
+
+    /// ParseDefaultStatement
+    /// \verbatim
+    ///       labeled-statement:
+    ///         'default' ':' statement
+    /// \endverbatim
+    /// Note that this does not parse the 'statement' at the end.
+    ///
+    StmtResult ParseDefaultStatement(ParsedStmtContext StmtCtx);
+
+    StmtResult ParseCompoundStatement(bool isStmtExpr = false);
+
+    /// ParseCompoundStatement - Parse a "{}" block.
+    ///
+    /// \verbatim
+    ///       compound-statement: [C99 6.8.2]
+    ///         { block-item-list[opt] }
+    /// [GNU]   { label-declarations block-item-list } [TODO]
+    ///
+    ///       block-item-list:
+    ///         block-item
+    ///         block-item-list block-item
+    ///
+    ///       block-item:
+    ///         declaration
+    /// [GNU]   '__extension__' declaration
+    ///         statement
+    ///
+    /// [GNU] label-declarations:
+    /// [GNU]   label-declaration
+    /// [GNU]   label-declarations label-declaration
+    ///
+    /// [GNU] label-declaration:
+    /// [GNU]   '__label__' identifier-list ';'
+    /// \endverbatim
+    ///
+    StmtResult ParseCompoundStatement(bool isStmtExpr, unsigned ScopeFlags);
+
+    /// Parse any pragmas at the start of the compound expression. We handle
+    /// these separately since some pragmas (FP_CONTRACT) must appear before any
+    /// C statement in the compound, but may be intermingled with other pragmas.
+    void ParseCompoundStatementLeadingPragmas();
+
+    void DiagnoseLabelAtEndOfCompoundStatement();
+
+    /// Consume any extra semi-colons resulting in null statements,
+    /// returning true if any tok::semi were consumed.
+    bool ConsumeNullStmt(StmtVector &Stmts);
+
+    /// ParseCompoundStatementBody - Parse a sequence of statements optionally
+    /// followed by a label and invoke the ActOnCompoundStmt action.  This
+    /// expects the '{' to be the current token, and consume the '}' at the end
+    /// of the block.  It does not manipulate the scope stack.
+    StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+
+    /// ParseParenExprOrCondition:
+    /// \verbatim
+    /// [C  ]     '(' expression ')'
+    /// [C++]     '(' condition ')'
+    /// [C++1z]   '(' init-statement[opt] condition ')'
+    /// \endverbatim
+    ///
+    /// This function parses and performs error recovery on the specified
+    /// condition or expression (depending on whether we're in C++ or C mode).
+    /// This function goes out of its way to recover well.  It returns true if
+    /// there was a parser error (the right paren couldn't be found), which
+    /// indicates that the caller should try to recover harder.  It returns
+    /// false if the condition is successfully parsed.  Note that a successful
+    /// parse can still have semantic errors in the condition. Additionally, it
+    /// will assign the location of the outer-most '(' and ')', to LParenLoc and
+    /// RParenLoc, respectively.
+    bool ParseParenExprOrCondition(StmtResult *InitStmt,
+                                   Sema::ConditionResult &CondResult,
+                                   SourceLocation Loc, Sema::ConditionKind CK,
+                                   SourceLocation &LParenLoc,
+                                   SourceLocation &RParenLoc);
+
+    /// ParseIfStatement
+    /// \verbatim
+    ///       if-statement: [C99 6.8.4.1]
+    ///         'if' '(' expression ')' statement
+    ///         'if' '(' expression ')' statement 'else' statement
+    /// [C++]   'if' '(' condition ')' statement
+    /// [C++]   'if' '(' condition ')' statement 'else' statement
+    /// [C++23] 'if' '!' [opt] consteval compound-statement
+    /// [C++23] 'if' '!' [opt] consteval compound-statement 'else' statement
+    /// \endverbatim
+    ///
+    StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);
+
+    /// ParseSwitchStatement
+    /// \verbatim
+    ///       switch-statement:
+    ///         'switch' '(' expression ')' statement
+    /// [C++]   'switch' '(' condition ')' statement
+    /// \endverbatim
+    StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);
+
+    /// ParseWhileStatement
+    /// \verbatim
+    ///       while-statement: [C99 6.8.5.1]
+    ///         'while' '(' expression ')' statement
+    /// [C++]   'while' '(' condition ')' statement
+    /// \endverbatim
+    StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);
+
+    /// ParseDoStatement
+    /// \verbatim
+    ///       do-statement: [C99 6.8.5.2]
+    ///         'do' statement 'while' '(' expression ')' ';'
+    /// \endverbatim
+    /// Note: this lets the caller parse the end ';'.
+    StmtResult ParseDoStatement();
+
+    /// ParseForStatement
+    /// \verbatim
+    ///       for-statement: [C99 6.8.5.3]
+    ///         'for' '(' expr[opt] ';' e...
[truncated]

Copy link

github-actions bot commented Jun 28, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@erichkeane erichkeane requested a review from cor3ntin June 30, 2025 14:03
@yronglin yronglin changed the title [C][Parser] Diagnostic for attribute declaration where statement is required [C23][Parser] Diagnostic for attribute declaration where statement is required Jun 30, 2025
@yronglin yronglin self-assigned this Jun 30, 2025
@yronglin yronglin added the c23 label Jun 30, 2025
@yronglin
Copy link
Contributor Author

The code format issue looks very strange, should we add an // clang-format off here?

@yronglin yronglin force-pushed the fix_missing_stmt_before_semi branch from d46ebd6 to 43e2dc6 Compare July 2, 2025 18:15
Signed-off-by: yronglin <[email protected]>
@yronglin
Copy link
Contributor Author

yronglin commented Jul 2, 2025

Thanks for your review!

@yronglin
Copy link
Contributor Author

yronglin commented Jul 7, 2025

friendly ping~

Co-authored-by: Mariya Podchishchaeva <[email protected]>
yronglin added 2 commits July 8, 2025 00:32
Signed-off-by: Wang, Yihan <[email protected]>
Signed-off-by: Wang, Yihan <[email protected]>
@@ -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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does AllowDeclarationsInC not suffice? I would expect that bit to not be set in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. We can just reuse AllowDeclarationsInC . I have removed SecondaryBlockInC .

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@yronglin yronglin merged commit 191386f into llvm:main Jul 9, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c23 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Clang][C23] No diagnostic for attribute declaration where statement is required
4 participants