-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang Author: None (yronglin) ChangesFixes: #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:
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]
|
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions h,c,cpp -- clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseStmt.cpp clang/test/Parser/statements.c clang/test/Sema/c2x-fallthrough.c View the diff from clang-format here.diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index cca4f14a2..d4dba1d46 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7160,426 +7160,428 @@ public:
private:
/// Flags describing a context in which we're parsing a statement.
- enum class ParsedStmtContext {
- /// This context permits declarations in language modes where declarations
- /// are not statements.
- AllowDeclarationsInC = 0x1,
- /// This context permits standalone OpenMP directives.
- 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)
- };
-
- /// Act on an expression statement that might be the last statement in a
- /// GNU statement expression. Checks whether we are actually at the end of
- /// a statement expression and builds a suitable expression statement.
- StmtResult handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx);
-
- //===--------------------------------------------------------------------===//
- // C99 6.8: Statements and Blocks.
-
- /// Parse a standalone statement (for instance, as the body of an 'if',
- /// 'while', or 'for').
- StmtResult
- ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
- ParsedStmtContext StmtCtx = ParsedStmtContext::SubStmt);
-
- /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
- /// \verbatim
- /// StatementOrDeclaration:
- /// statement
- /// declaration
- ///
- /// statement:
- /// labeled-statement
- /// compound-statement
- /// expression-statement
- /// selection-statement
- /// iteration-statement
- /// jump-statement
- /// [C++] declaration-statement
- /// [C++] try-block
- /// [MS] seh-try-block
- /// [OBC] objc-throw-statement
- /// [OBC] objc-try-catch-statement
- /// [OBC] objc-synchronized-statement
- /// [GNU] asm-statement
- /// [OMP] openmp-construct [TODO]
- ///
- /// labeled-statement:
- /// identifier ':' statement
- /// 'case' constant-expression ':' statement
- /// 'default' ':' statement
- ///
- /// selection-statement:
- /// if-statement
- /// switch-statement
- ///
- /// iteration-statement:
- /// while-statement
- /// do-statement
- /// for-statement
- ///
- /// expression-statement:
- /// expression[opt] ';'
- ///
- /// jump-statement:
- /// 'goto' identifier ';'
- /// 'continue' ';'
- /// 'break' ';'
- /// 'return' expression[opt] ';'
- /// [GNU] 'goto' '*' expression ';'
- ///
- /// [OBC] objc-throw-statement:
- /// [OBC] '@' 'throw' expression ';'
- /// [OBC] '@' 'throw' ';'
- /// \endverbatim
- ///
- StmtResult
- 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();
+ enum class ParsedStmtContext {
+ /// This context permits declarations in language modes where declarations
+ /// are not statements.
+ AllowDeclarationsInC = 0x1,
+ /// This context permits standalone OpenMP directives.
+ 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)
+ };
- /// 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);
- }
+ /// Act on an expression statement that might be the last statement in a
+ /// GNU statement expression. Checks whether we are actually at the end of
+ /// a statement expression and builds a suitable expression statement.
+ StmtResult handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx);
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.8: Statements and Blocks.
+
+ /// Parse a standalone statement (for instance, as the body of an 'if',
+ /// 'while', or 'for').
+ StmtResult
+ ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
+ ParsedStmtContext StmtCtx = ParsedStmtContext::SubStmt);
+
+ /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
+ /// \verbatim
+ /// StatementOrDeclaration:
+ /// statement
+ /// declaration
+ ///
+ /// statement:
+ /// labeled-statement
+ /// compound-statement
+ /// expression-statement
+ /// selection-statement
+ /// iteration-statement
+ /// jump-statement
+ /// [C++] declaration-statement
+ /// [C++] try-block
+ /// [MS] seh-try-block
+ /// [OBC] objc-throw-statement
+ /// [OBC] objc-try-catch-statement
+ /// [OBC] objc-synchronized-statement
+ /// [GNU] asm-statement
+ /// [OMP] openmp-construct [TODO]
+ ///
+ /// labeled-statement:
+ /// identifier ':' statement
+ /// 'case' constant-expression ':' statement
+ /// 'default' ':' statement
+ ///
+ /// selection-statement:
+ /// if-statement
+ /// switch-statement
+ ///
+ /// iteration-statement:
+ /// while-statement
+ /// do-statement
+ /// for-statement
+ ///
+ /// expression-statement:
+ /// expression[opt] ';'
+ ///
+ /// jump-statement:
+ /// 'goto' identifier ';'
+ /// 'continue' ';'
+ /// 'break' ';'
+ /// 'return' expression[opt] ';'
+ /// [GNU] 'goto' '*' expression ';'
+ ///
+ /// [OBC] objc-throw-statement:
+ /// [OBC] '@' 'throw' expression ';'
+ /// [OBC] '@' 'throw' ';'
+ /// \endverbatim
+ ///
+ StmtResult
+ 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);
+ }
/// isForInitDeclaration - Disambiguates between a declaration or an
/// expression in the context of the C 'clause-1' or the C++
|
The code format issue looks very strange, should we add an |
clang/lib/Parse/ParseStmt.cpp
Outdated
@@ -80,6 +81,11 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, | |||
assert((CXX11Attrs.empty() || Res.isInvalid() || Res.isUsable()) && | |||
"attributes on empty statement"); | |||
|
|||
if (HasStdAttr && getLangOpts().C99 && |
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.
Why are all the checks predicated on C99?
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.
I originally want to emit this warning in C99 mode, but now I have changed the condition here to C23.
clang/test/Sema/c2x-fallthrough.c
Outdated
@@ -15,18 +15,19 @@ void f(int n) { | |||
return; | |||
} | |||
case 2: | |||
// FIXME: Should we emit an error {{fallthrough annotation does not directly precede switch label}}? |
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.
Yeah that seems like a regression in behavior.
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.
Hmm, this because I originally set the new diagnostic's severity to Error
, which will interrupt the warning static analysis based warnings.
llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
Lines 2632 to 2633 in da01257
if (S.hasUncompilableErrorOccurred() || Diags.getIgnoreAllWarnings()) | |
// exit if having uncompilable errors or ignoring all warnings: |
I have changed the severity to Warning
now.
clang/test/Sema/c2x-fallthrough2.c
Outdated
@@ -0,0 +1,18 @@ | |||
// RUN: %clang_cc1 -fsyntax-only -std=c2x -verify %s |
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.
// RUN: %clang_cc1 -fsyntax-only -std=c2x -verify %s | |
// RUN: %clang_cc1 -fsyntax-only -std=c23 -verify %s |
Maybe rename the file to be c23
instead of c2x
as well?
… required Signed-off-by: yronglin <yronglin777@gmail.com>
d46ebd6
to
43e2dc6
Compare
Signed-off-by: yronglin <yronglin777@gmail.com>
Thanks for your review! |
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: