diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 28bb83a1c9d60..9b4ffbacbdfde 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -443,6 +443,7 @@ Bug Fixes in This Version - The warning emitted for an unsupported register variable type now points to the unsupported type instead of the ``register`` keyword (#GH109776). - Fixed a crash when emit ctor for global variant with flexible array init (#GH113187). +- Fixed a crash when GNU statement expression contains invalid statement (#GH113468). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 60d647da48f05..6d0de38095b99 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1243,6 +1243,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ParsedStmtContext::Compound | (isStmtExpr ? ParsedStmtContext::InStmtExpr : ParsedStmtContext()); + bool LastIsError = false; while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { if (Tok.is(tok::annot_pragma_unused)) { @@ -1299,7 +1300,15 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { if (R.isUsable()) Stmts.push_back(R.get()); + LastIsError = R.isInvalid(); } + // StmtExpr needs to do copy initialization for last statement. + // If last statement is invalid, the last statement in `Stmts` will be + // incorrect. Then the whole compound statement should also be marked as + // invalid to prevent subsequent errors. + if (isStmtExpr && LastIsError && !Stmts.empty()) + return StmtError(); + // Warn the user that using option `-ffp-eval-method=source` on a // 32-bit target and feature `sse` disabled, or using // `pragma clang fp eval_method=source` and feature `sse` disabled, is not diff --git a/clang/test/SemaCXX/gh113468.cpp b/clang/test/SemaCXX/gh113468.cpp new file mode 100644 index 0000000000000..94551986b0efa --- /dev/null +++ b/clang/test/SemaCXX/gh113468.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +constexpr int expr() { + if (({ + int f; + f = 0; + if (f) + break; // expected-error {{'break' statement not in loop or switch statement}} + })) + return 2; + return 1; +}