Index: lib/Format/UnwrappedLineParser.h =================================================================== --- lib/Format/UnwrappedLineParser.h +++ lib/Format/UnwrappedLineParser.h @@ -85,6 +85,7 @@ void parseReturn(); void parseParens(); void parseSquare(); + void parseTryCatch(); void parseIfThenElse(); void parseForOrWhileLoop(); void parseDoWhile(); Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -621,6 +621,9 @@ case tok::kw_private: parseAccessSpecifier(); return; + case tok::kw_try: + parseTryCatch(); + return; case tok::kw_if: parseIfThenElse(); return; @@ -708,6 +711,10 @@ // Otherwise this was a braced init list, and the structural // element continues. break; + case tok::kw_try: + // It enters here in function-try blocks + parseTryCatch(); + return; case tok::identifier: { StringRef Text = FormatTok->TokenText; nextToken(); @@ -1028,6 +1035,65 @@ } } +void UnwrappedLineParser::parseTryCatch() { + assert(FormatTok->Tok.is(tok::kw_try) && "'try' expected"); + nextToken(); + bool NeedsUnwrappedLine = false; + if (FormatTok->Tok.is(tok::colon)) { + // We are in a function try block, what comes is an initializer list + nextToken(); + while (FormatTok->Tok.is(tok::identifier)) { + nextToken(); + if (FormatTok->Tok.is(tok::l_paren)) + parseParens(); + else + StructuralError = true; + if (FormatTok->Tok.is(tok::comma)) + nextToken(); + } + } + if (FormatTok->Tok.is(tok::l_brace)) { + CompoundStatementIndenter Indenter(this, Style, Line->Level); + parseBlock(/*MustBeDeclaration=*/false); + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU || + Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) { + addUnwrappedLine(); + } else { + NeedsUnwrappedLine = true; + } + } else if (!FormatTok->Tok.is(tok::kw_catch)) { + // The C++ standard requires a compound-statement after a try. + // If there's none, we try to assume there's a structuralElement + // and try to continue. + StructuralError = true; + addUnwrappedLine(); + ++Line->Level; + parseStructuralElement(); + --Line->Level; + } + while (FormatTok->Tok.is(tok::kw_catch)) { + nextToken(); + if (FormatTok->Tok.is(tok::l_paren)) + parseParens(); + NeedsUnwrappedLine = false; + if (FormatTok->Tok.is(tok::l_brace)) { + CompoundStatementIndenter Indenter(this, Style, Line->Level); + parseBlock(/*MustBeDeclaration=*/false); + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU || + Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) { + addUnwrappedLine(); + } else { + NeedsUnwrappedLine = true; + } + } + } + if (NeedsUnwrappedLine) { + addUnwrappedLine(); + } +} + void UnwrappedLineParser::parseNamespace() { assert(FormatTok->Tok.is(tok::kw_namespace) && "'namespace' expected"); nextToken(); Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -1810,15 +1810,11 @@ } TEST_F(FormatTest, FormatTryCatch) { - // FIXME: Handle try-catch explicitly in the UnwrappedLineParser, then we'll - // also not create single-line-blocks. verifyFormat("try {\n" " throw a * b;\n" - "}\n" - "catch (int a) {\n" + "} catch (int a) {\n" " // Do nothing.\n" - "}\n" - "catch (...) {\n" + "} catch (...) {\n" " exit(42);\n" "}"); @@ -2271,9 +2267,8 @@ " f(x)\n" " try {\n" " q();\n" + " } catch (...) {\n" " }\n" - " catch (...) {\n" - " }\n" "}\n", format("int q() {\n" "f(x)\n" @@ -2288,8 +2283,7 @@ EXPECT_EQ("class A {\n" " A() : t(0) {}\n" " A(X x)\n" // FIXME: function-level try blocks are broken. - " try : t(0) {\n" - " }\n" + " try : t(0) {}\n" " catch (...) {\n" " }\n" "};", @@ -7179,9 +7173,8 @@ TEST_F(FormatTest, CatchExceptionReferenceBinding) { verifyFormat("void f() {\n" " try {\n" + " } catch (const Exception &e) {\n" " }\n" - " catch (const Exception &e) {\n" - " }\n" "}\n", getLLVMStyle()); }