https://github.com/yasster created https://github.com/llvm/llvm-project/pull/223499
Recognize _except as an SEH handler when Microsoft compatibility is enabled, matching the existing _try, _finally and _leave aliases. Keep _except usable as an ordinary identifier outside the handler position. Add C and C++ parser coverage for mixed spellings, malformed handlers, ordinary identifier uses and rejection without Microsoft compatibility. >From 02789db5e1b8f41fb3421df3ffdeb563b5444e19 Mon Sep 17 00:00:00 2001 From: Yassine Missoum <[email protected]> Date: Mon, 14 Sep 2026 11:55:01 -0700 Subject: [PATCH] [Clang][Parser] Accept contextual _except in MS compatibility mode Recognize _except as an SEH handler when Microsoft compatibility is enabled, matching the existing _try, _finally and _leave aliases. Keep _except usable as an ordinary identifier outside the handler position. Add C and C++ parser coverage for mixed spellings, malformed handlers, ordinary identifier uses and rejection without Microsoft compatibility. Co-authored-by: Adam Glass <[email protected]> --- clang/include/clang/Parse/Parser.h | 3 ++ clang/lib/Parse/ParseStmt.cpp | 9 ++-- clang/lib/Parse/Parser.cpp | 19 ++++++++ .../Parser/ms-seh-single-underscore-strict.c | 20 +++++++++ clang/test/Parser/ms-seh-single-underscore.c | 44 +++++++++++++++++++ 5 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 clang/test/Parser/ms-seh-single-underscore-strict.c create mode 100644 clang/test/Parser/ms-seh-single-underscore.c diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 6913c42884a36..b3f6be017523c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -661,6 +661,7 @@ class Parser : public CodeCompletionHandler { /// Contextual keywords for Microsoft extensions. IdentifierInfo *Ident__except; + IdentifierInfo *Ident__except_single; std::unique_ptr<CommentHandler> CommentSemaHandler; @@ -671,6 +672,8 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *getSEHExceptKeyword(); + bool isTokenSEHExcept(); + /// Whether to skip parsing of function bodies. /// /// This option can be used, for example, to speed up searches for diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 5e67cd551bff8..4e88710eac19c 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -611,8 +611,7 @@ StmtResult Parser::ParseSEHTryBlock() { return TryBlock; StmtResult Handler; - if (Tok.is(tok::identifier) && - Tok.getIdentifierInfo() == getSEHExceptKeyword()) { + if (isTokenSEHExcept()) { SourceLocation Loc = ConsumeToken(); Handler = ParseSEHExceptBlock(Loc); } else if (Tok.is(tok::kw___finally)) { @@ -2680,12 +2679,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { // Borland allows SEH-handlers with 'try' - if ((Tok.is(tok::identifier) && - Tok.getIdentifierInfo() == getSEHExceptKeyword()) || - Tok.is(tok::kw___finally)) { + if (isTokenSEHExcept() || Tok.is(tok::kw___finally)) { // TODO: Factor into common return ParseSEHHandlerCommon(...) StmtResult Handler; - if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) { + if (isTokenSEHExcept()) { SourceLocation Loc = ConsumeToken(); Handler = ParseSEHExceptBlock(Loc); } diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index da5f23c4ca30e..a9454b19b167b 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -56,6 +56,24 @@ IdentifierInfo *Parser::getSEHExceptKeyword() { return Ident__except; } +bool Parser::isTokenSEHExcept() { + if (!Tok.is(tok::identifier)) + return false; + + const IdentifierInfo *Identifier = Tok.getIdentifierInfo(); + if (Identifier == getSEHExceptKeyword()) + return true; + + if (getLangOpts().MSVCCompat) { + if (!Ident__except_single) + Ident__except_single = PP.getIdentifierInfo("_except"); + if (Identifier == Ident__except_single) + return true; + } + + return false; +} + Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) : PP(pp), PreferredType(&actions.getASTContext(), pp.isCodeCompletionEnabled()), @@ -548,6 +566,7 @@ void Parser::Initialize() { nullptr; Ident__except = nullptr; + Ident__except_single = nullptr; Ident__exception_code = Ident__exception_info = nullptr; Ident__abnormal_termination = Ident___exception_code = nullptr; diff --git a/clang/test/Parser/ms-seh-single-underscore-strict.c b/clang/test/Parser/ms-seh-single-underscore-strict.c new file mode 100644 index 0000000000000..c00ede66e9cd7 --- /dev/null +++ b/clang/test/Parser/ms-seh-single-underscore-strict.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -fsyntax-only -fms-extensions -verify +// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -x c++ -fsyntax-only -fms-extensions -verify + +int _except(int); + +int use_except_identifier(int value) { + return _except(value); +} + +void double_except(void) { + __try { + } __except(1) { + } +} + +void single_except(void) { + __try { + } _except(1) { // expected-error {{expected '__except' or '__finally' block}} expected-error {{expected ';' after expression}} + } +} \ No newline at end of file diff --git a/clang/test/Parser/ms-seh-single-underscore.c b/clang/test/Parser/ms-seh-single-underscore.c new file mode 100644 index 0000000000000..c3d7067e5a1c9 --- /dev/null +++ b/clang/test/Parser/ms-seh-single-underscore.c @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -fsyntax-only -fms-compatibility -Wmicrosoft -verify +// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -x c++ -fsyntax-only -fms-compatibility -Wmicrosoft -verify + +int _except(int); + +int use_except_identifier(int value) { + int (*handler)(int) = _except; + return handler(value) + _except(value); +} + +void single_except(void) { + _try { + _leave; + } _except(1) { + } +} + +void single_finally(void) { + _try { + } _finally { + } +} + +void mixed_spellings(void) { + _try { + __leave; + } __except(1) { + } + + __try { + } _except(1) { + } + + __try { + } _finally { + } +} + +void bad_except(void) { + int value; + + _try { + } _except(1) value; // expected-error {{expected '{'}} expected-warning {{expression result unused}} +} \ No newline at end of file _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
