Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -1123,7 +1123,8 @@ ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr, Whitespaces, Encoding, BinPackInconclusiveFunctions); - UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style); + UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style, + Tokens.getKeywords()); Formatter.format(AnnotatedLines, /*DryRun=*/false); return Whitespaces.generateReplacements(); } @@ -1399,6 +1400,7 @@ LangOpts.Bool = 1; LangOpts.ObjC1 = 1; LangOpts.ObjC2 = 1; + LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. return LangOpts; } Index: lib/Format/FormatToken.h =================================================================== --- lib/Format/FormatToken.h +++ lib/Format/FormatToken.h @@ -555,6 +555,7 @@ kw_package = &IdentTable.get("package"); kw_synchronized = &IdentTable.get("synchronized"); kw_throws = &IdentTable.get("throws"); + kw___except = &IdentTable.get("__except"); kw_option = &IdentTable.get("option"); kw_optional = &IdentTable.get("optional"); @@ -563,12 +564,13 @@ kw_returns = &IdentTable.get("returns"); } - // ObjC context sensitive keywords. + // Context sensitive keywords. IdentifierInfo *kw_in; IdentifierInfo *kw_CF_ENUM; IdentifierInfo *kw_CF_OPTIONS; IdentifierInfo *kw_NS_ENUM; IdentifierInfo *kw_NS_OPTIONS; + IdentifierInfo *kw___except; // JavaScript keywords. IdentifierInfo *kw_finally; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -1701,8 +1701,8 @@ (Style.SpaceBeforeParens != FormatStyle::SBPO_Never && (Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch, tok::kw_case) || - (Left.isOneOf(tok::kw_try, tok::kw_catch, tok::kw_new, - tok::kw_delete) && + (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch, + tok::kw_new, tok::kw_delete) && (!Left.Previous || Left.Previous->isNot(tok::period))) || Left.IsForEachMacro)) || (Style.SpaceBeforeParens == FormatStyle::SBPO_Always && Index: lib/Format/UnwrappedLineFormatter.h =================================================================== --- lib/Format/UnwrappedLineFormatter.h +++ lib/Format/UnwrappedLineFormatter.h @@ -32,8 +32,10 @@ public: UnwrappedLineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces, - const FormatStyle &Style) - : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style) {} + const FormatStyle &Style, + const AdditionalKeywords &Keywords) + : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), + Keywords(Keywords) {} unsigned format(const SmallVectorImpl &Lines, bool DryRun, int AdditionalIndent = 0, bool FixBadIndentation = false); @@ -153,6 +155,7 @@ ContinuationIndenter *Indenter; WhitespaceManager *Whitespaces; FormatStyle Style; + const AdditionalKeywords &Keywords; llvm::SpecificBumpPtrAllocator Allocator; Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -27,7 +27,8 @@ class LineJoiner { public: - LineJoiner(const FormatStyle &Style) : Style(Style) {} + LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords) + : Style(Style), Keywords(Keywords) {} /// \brief Calculates how many lines can be merged into 1 starting at \p I. unsigned @@ -200,7 +201,9 @@ if (Line.First->isOneOf(tok::kw_else, tok::kw_case)) return 0; if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try, - tok::kw_catch, tok::kw_for, tok::r_brace)) { + tok::kw___try, tok::kw_catch, tok::kw___finally, + tok::kw_for, tok::r_brace) || + Line.First->is(Keywords.kw___except)) { if (!Style.AllowShortBlocksOnASingleLine) return 0; if (!Style.AllowShortIfStatementsOnASingleLine && @@ -211,7 +214,8 @@ return 0; // FIXME: Consider an option to allow short exception handling clauses on // a single line. - if (Line.First->isOneOf(tok::kw_try, tok::kw_catch)) + if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch, + Keywords.kw___except, tok::kw___finally)) return 0; } @@ -286,6 +290,7 @@ } const FormatStyle &Style; + const AdditionalKeywords &Keywords; }; class NoColumnLimitFormatter { @@ -324,7 +329,7 @@ UnwrappedLineFormatter::format(const SmallVectorImpl &Lines, bool DryRun, int AdditionalIndent, bool FixBadIndentation) { - LineJoiner Joiner(Style); + LineJoiner Joiner(Style, Keywords); // Try to look up already computed penalty in DryRun-mode. std::pair *, unsigned> CacheKey( Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -374,6 +374,7 @@ case tok::kw_for: case tok::kw_switch: case tok::kw_try: + case tok::kw___try: if (!LBraceStack.empty()) LBraceStack.back()->BlockKind = BK_Block; break; @@ -713,6 +714,7 @@ parseCaseLabel(); return; case tok::kw_try: + case tok::kw___try: parseTryCatch(); return; case tok::kw_extern: @@ -1149,7 +1151,7 @@ } void UnwrappedLineParser::parseTryCatch() { - assert(FormatTok->is(tok::kw_try) && "'try' expected"); + assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected"); nextToken(); bool NeedsUnwrappedLine = false; if (FormatTok->is(tok::colon)) { @@ -1189,7 +1191,8 @@ parseStructuralElement(); --Line->Level; } - while (FormatTok->is(tok::kw_catch) || + while (FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except, + tok::kw___finally) || ((Style.Language == FormatStyle::LK_Java || Style.Language == FormatStyle::LK_JavaScript) && FormatTok->is(Keywords.kw_finally))) { Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -2244,6 +2244,26 @@ verifyFormat("try {} catch ("); } +TEST_F(FormatTest, FormatSEHTryCatch) { + verifyFormat("__try {\n" + " int a = b * c;\n" + "} __except (EXCEPTION_EXECUTE_HANDLER) {\n" + " // Do nothing.\n" + "}"); + + verifyFormat("__try {\n" + " int a = b * c;\n" + "} __finally {\n" + " // Do nothing.\n" + "}"); + + verifyFormat("DEBUG({\n" + " __try {\n" + " } __finally {\n" + " }\n" + "});\n"); +} + TEST_F(FormatTest, IncompleteTryCatchBlocks) { verifyFormat("try {\n" " f();\n"