summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2014-05-08 11:58:24 +0000
committerDaniel Jasper <djasper@google.com>2014-05-08 11:58:24 +0000
commit04a71a45ff8e8b8a8493d394dfbc4205724b9353 (patch)
tree2dde5bab1312d53165023a15165af43165c0d5ae
parent8dcb116a3eb6d58636ce765e4d89b9a383c7cd5b (diff)
downloadbcm5719-llvm-04a71a45ff8e8b8a8493d394dfbc4205724b9353.tar.gz
bcm5719-llvm-04a71a45ff8e8b8a8493d394dfbc4205724b9353.zip
clang-format: Initial support for try-catch.
Most of this patch was created by Alexander Rojas in http://reviews.llvm.org/D2555 Thank you! Synced and addressed review comments. llvm-svn: 208302
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp73
-rw-r--r--clang/lib/Format/UnwrappedLineParser.h1
-rw-r--r--clang/unittests/Format/FormatTest.cpp78
-rw-r--r--clang/unittests/Format/FormatTestJS.cpp10
4 files changed, 146 insertions, 16 deletions
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 940fcc8ae2f..e229ff02f5b 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -675,6 +675,9 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_case:
parseCaseLabel();
return;
+ case tok::kw_try:
+ parseTryCatch();
+ return;
case tok::kw_extern:
nextToken();
if (FormatTok->Tok.is(tok::string_literal)) {
@@ -755,6 +758,10 @@ void UnwrappedLineParser::parseStructuralElement() {
// Otherwise this was a braced init list, and the structural
// element continues.
break;
+ case tok::kw_try:
+ // We arrive here when parsing function-try blocks.
+ parseTryCatch();
+ return;
case tok::identifier: {
StringRef Text = FormatTok->TokenText;
nextToken();
@@ -1071,6 +1078,72 @@ void UnwrappedLineParser::parseIfThenElse() {
}
}
+void UnwrappedLineParser::parseTryCatch() {
+ assert(FormatTok->is(tok::kw_try) && "'try' expected");
+ nextToken();
+ bool NeedsUnwrappedLine = false;
+ if (FormatTok->is(tok::colon)) {
+ // We are in a function try block, what comes is an initializer list.
+ nextToken();
+ while (FormatTok->is(tok::identifier)) {
+ nextToken();
+ if (FormatTok->is(tok::l_paren))
+ parseParens();
+ else
+ StructuralError = true;
+ if (FormatTok->is(tok::comma))
+ nextToken();
+ }
+ }
+ if (FormatTok->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->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->is(tok::kw_catch) ||
+ (Style.Language == FormatStyle::LK_JavaScript &&
+ FormatTok->TokenText == "finally")) {
+ nextToken();
+ while (FormatTok->isNot(tok::l_brace)) {
+ if (FormatTok->is(tok::l_paren)) {
+ parseParens();
+ continue;
+ }
+ if (FormatTok->isOneOf(tok::semi, tok::r_brace))
+ return;
+ nextToken();
+ }
+ NeedsUnwrappedLine = false;
+ 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();
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 9eb56011629..63898539b27 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -85,6 +85,7 @@ private:
void parseParens();
void parseSquare();
void parseIfThenElse();
+ void parseTryCatch();
void parseForOrWhileLoop();
void parseDoWhile();
void parseLabel();
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 3ec1ea50848..75b5c6b518e 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2000,32 +2000,81 @@ TEST_F(FormatTest, FormatsInlineASM) {
}
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"
"}");
// Function-level try statements.
- verifyFormat("int f() try { return 4; }\n"
- "catch (...) {\n"
+ verifyFormat("int f() try { return 4; } catch (...) {\n"
" return 5;\n"
"}");
verifyFormat("class A {\n"
" int a;\n"
- " A() try : a(0) {}\n"
- " catch (...) {\n"
+ " A() try : a(0) {\n"
+ " } catch (...) {\n"
" throw;\n"
" }\n"
"};\n");
}
+TEST_F(FormatTest, IncompleteTryCatchBlocks) {
+ verifyFormat("try {\n"
+ " f();\n"
+ "} catch {\n"
+ " g();\n"
+ "}");
+ verifyFormat("try {\n"
+ " f();\n"
+ "} catch (A a) MACRO(x) {\n"
+ " g();\n"
+ "} catch (B b) MACRO(x) {\n"
+ " g();\n"
+ "}");
+}
+
+TEST_F(FormatTest, FormatTryCatchBraceStyles) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BS_Attach;
+ verifyFormat("try {\n"
+ " // something\n"
+ "} catch (...) {\n"
+ " // something\n"
+ "}",
+ Style);
+ Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
+ verifyFormat("try {\n"
+ " // something\n"
+ "}\n"
+ "catch (...) {\n"
+ " // something\n"
+ "}",
+ Style);
+ Style.BreakBeforeBraces = FormatStyle::BS_Allman;
+ verifyFormat("try\n"
+ "{\n"
+ " // something\n"
+ "}\n"
+ "catch (...)\n"
+ "{\n"
+ " // something\n"
+ "}",
+ Style);
+ Style.BreakBeforeBraces = FormatStyle::BS_GNU;
+ verifyFormat("try\n"
+ " {\n"
+ " // something\n"
+ " }\n"
+ "catch (...)\n"
+ " {\n"
+ " // something\n"
+ " }",
+ Style);
+}
+
TEST_F(FormatTest, FormatObjCTryCatch) {
verifyFormat("@try {\n"
" f();\n"
@@ -2453,8 +2502,7 @@ TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) {
" F(x)\n"
" try {\n"
" Q();\n"
- " }\n"
- " catch (...) {\n"
+ " } catch (...) {\n"
" }\n"
"}\n",
format("int q() {\n"
@@ -2471,8 +2519,7 @@ TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) {
" A() : t(0) {}\n"
" A(X x)\n" // FIXME: function-level try blocks are broken.
" try : t(0) {\n"
- " }\n"
- " catch (...) {\n"
+ " } catch (...) {\n"
" }\n"
"};",
format("class A {\n"
@@ -7752,8 +7799,7 @@ TEST_F(FormatTest, GNUBraceBreaking) {
TEST_F(FormatTest, CatchExceptionReferenceBinding) {
verifyFormat("void f() {\n"
" try {\n"
- " }\n"
- " catch (const Exception &e) {\n"
+ " } catch (const Exception &e) {\n"
" }\n"
"}\n",
getLLVMStyle());
diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp
index 2dfd10faf1b..73e050d6f4f 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -118,6 +118,16 @@ TEST_F(FormatTestJS, ClosureStyleComments) {
verifyFormat("var x = /** @type {foo} */ (bar);");
}
+TEST_F(FormatTestJS, TryCatch) {
+ verifyFormat("try {\n"
+ " f();\n"
+ "} catch (e) {\n"
+ " g();\n"
+ "} finally {\n"
+ " h();\n"
+ "}");
+}
+
TEST_F(FormatTestJS, RegexLiteralClassification) {
// Regex literals.
verifyFormat("var regex = /abc/;");
OpenPOWER on IntegriCloud